1*dde46bf8Sclaudio /* $OpenBSD: kvm_proc2.c,v 1.39 2024/07/08 13:18:26 claudio Exp $ */
272596c46Sguenther /* $NetBSD: kvm_proc.c,v 1.30 1999/03/24 05:50:50 mrg Exp $ */
372596c46Sguenther /*-
472596c46Sguenther * Copyright (c) 1998 The NetBSD Foundation, Inc.
572596c46Sguenther * All rights reserved.
672596c46Sguenther *
772596c46Sguenther * This code is derived from software contributed to The NetBSD Foundation
872596c46Sguenther * by Charles M. Hannum.
972596c46Sguenther *
1072596c46Sguenther * Redistribution and use in source and binary forms, with or without
1172596c46Sguenther * modification, are permitted provided that the following conditions
1272596c46Sguenther * are met:
1372596c46Sguenther * 1. Redistributions of source code must retain the above copyright
1472596c46Sguenther * notice, this list of conditions and the following disclaimer.
1572596c46Sguenther * 2. Redistributions in binary form must reproduce the above copyright
1672596c46Sguenther * notice, this list of conditions and the following disclaimer in the
1772596c46Sguenther * documentation and/or other materials provided with the distribution.
1872596c46Sguenther *
1972596c46Sguenther * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2072596c46Sguenther * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2172596c46Sguenther * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2272596c46Sguenther * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2372596c46Sguenther * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2472596c46Sguenther * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2572596c46Sguenther * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2672596c46Sguenther * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2772596c46Sguenther * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2872596c46Sguenther * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2972596c46Sguenther * POSSIBILITY OF SUCH DAMAGE.
3072596c46Sguenther */
3172596c46Sguenther /*-
3272596c46Sguenther * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
3372596c46Sguenther * Copyright (c) 1989, 1992, 1993
3472596c46Sguenther * The Regents of the University of California. All rights reserved.
3572596c46Sguenther *
3672596c46Sguenther * This code is derived from software developed by the Computer Systems
3772596c46Sguenther * Engineering group at Lawrence Berkeley Laboratory under DARPA contract
3872596c46Sguenther * BG 91-66 and contributed to Berkeley.
3972596c46Sguenther *
4072596c46Sguenther * Redistribution and use in source and binary forms, with or without
4172596c46Sguenther * modification, are permitted provided that the following conditions
4272596c46Sguenther * are met:
4372596c46Sguenther * 1. Redistributions of source code must retain the above copyright
4472596c46Sguenther * notice, this list of conditions and the following disclaimer.
4572596c46Sguenther * 2. Redistributions in binary form must reproduce the above copyright
4672596c46Sguenther * notice, this list of conditions and the following disclaimer in the
4772596c46Sguenther * documentation and/or other materials provided with the distribution.
4872596c46Sguenther * 3. Neither the name of the University nor the names of its contributors
4972596c46Sguenther * may be used to endorse or promote products derived from this software
5072596c46Sguenther * without specific prior written permission.
5172596c46Sguenther *
5272596c46Sguenther * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
5372596c46Sguenther * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5472596c46Sguenther * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5572596c46Sguenther * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
5672596c46Sguenther * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5772596c46Sguenther * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5872596c46Sguenther * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5972596c46Sguenther * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
6072596c46Sguenther * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
6172596c46Sguenther * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
6272596c46Sguenther * SUCH DAMAGE.
6372596c46Sguenther */
6472596c46Sguenther
6572596c46Sguenther /*
6672596c46Sguenther * Proc traversal interface for kvm. ps and w are (probably) the exclusive
6772596c46Sguenther * users of this code, so we've factored it out into a separate module.
6872596c46Sguenther * Thus, we keep this grunge out of the other kvm applications (i.e.,
6972596c46Sguenther * most other applications are interested only in open/close/read/nlist).
7072596c46Sguenther */
7172596c46Sguenther
7272596c46Sguenther #define __need_process
734ec73a12Sderaadt #include <sys/param.h> /* NODEV */
740b082c0eSderaadt #include <sys/types.h>
750b082c0eSderaadt #include <sys/signal.h>
7672596c46Sguenther #include <sys/proc.h>
7772596c46Sguenther #include <sys/exec.h>
7872596c46Sguenther #include <sys/stat.h>
79925bd4b5Sderaadt #include <sys/ucred.h>
8072596c46Sguenther #include <sys/ioctl.h>
8172596c46Sguenther #include <sys/tty.h>
82925bd4b5Sderaadt #include <sys/resource.h>
83925bd4b5Sderaadt #include <sys/resourcevar.h>
842725daddSguenther #include <sys/signalvar.h>
858d8661adSderaadt #include <sys/pledge.h>
864b7f768dSsthen #include <sys/wait.h>
8772596c46Sguenther #include <stddef.h>
8872596c46Sguenther #include <stdlib.h>
8972596c46Sguenther #include <string.h>
9072596c46Sguenther #include <unistd.h>
9172596c46Sguenther #include <nlist.h>
9272596c46Sguenther #include <kvm.h>
9372596c46Sguenther
9472596c46Sguenther #include <uvm/uvm_extern.h>
9572596c46Sguenther #include <uvm/uvm_amap.h>
9672596c46Sguenther #include <machine/vmparam.h>
9772596c46Sguenther #include <machine/pmap.h>
9872596c46Sguenther
9972596c46Sguenther #include <sys/sysctl.h>
10072596c46Sguenther
10172596c46Sguenther #include <limits.h>
10258b561c5Sdlg #include <errno.h>
10372596c46Sguenther #include <db.h>
10472596c46Sguenther #include <paths.h>
10572596c46Sguenther
10672596c46Sguenther #include "kvm_private.h"
10772596c46Sguenther
10872596c46Sguenther /*
10972596c46Sguenther * Read proc's from memory file into buffer bp, which has space to hold
11072596c46Sguenther * at most maxcnt procs.
11172596c46Sguenther */
11272596c46Sguenther static int
kvm_proclist(kvm_t * kd,int op,int arg,struct process * pr,char * bp,int maxcnt,size_t esize)113712e2ef1Sguenther kvm_proclist(kvm_t *kd, int op, int arg, struct process *pr,
11472596c46Sguenther char *bp, int maxcnt, size_t esize)
11572596c46Sguenther {
11609431e5cSguenther struct kinfo_proc kp;
11772596c46Sguenther struct session sess;
11872596c46Sguenther struct ucred ucred;
1193b7181b7Sguenther struct proc proc, *p;
120207e4b38Sguenther struct process process, process2;
12172596c46Sguenther struct pgrp pgrp;
12272596c46Sguenther struct tty tty;
123fe57de6bScheloha struct timeval elapsed, monostart, monostop, realstart, realstop;
124fe57de6bScheloha struct nlist nl[3];
1252725daddSguenther struct sigacts sa, *sap;
12672596c46Sguenther struct vmspace vm, *vmp;
12772596c46Sguenther struct plimit limits, *limp;
1283b7181b7Sguenther pid_t parent_pid, leader_pid;
12972596c46Sguenther int cnt = 0;
1306171375dSpirofti int dothreads = 0;
131fe57de6bScheloha int i;
1326171375dSpirofti
1336171375dSpirofti dothreads = op & KERN_PROC_SHOW_THREADS;
1346171375dSpirofti op &= ~KERN_PROC_SHOW_THREADS;
13572596c46Sguenther
136fe57de6bScheloha /* Anchor a time to compare process starting times from. */
137fe57de6bScheloha nl[0].n_name = "_time_second";
138fe57de6bScheloha nl[1].n_name = "_time_uptime";
139fe57de6bScheloha nl[2].n_name = NULL;
140fe57de6bScheloha if (kvm_nlist(kd, nl) != 0) {
141fe57de6bScheloha for (i = 0; nl[i].n_type != 0; ++i)
142fe57de6bScheloha continue;
143fe57de6bScheloha _kvm_err(kd, kd->program, "%s: no such symbol", nl[i].n_name);
144fe57de6bScheloha return (-1);
145fe57de6bScheloha }
146fe57de6bScheloha timerclear(&realstop);
147fe57de6bScheloha timerclear(&monostop);
148fe57de6bScheloha if (KREAD(kd, nl[0].n_value, &realstop.tv_sec)) {
149fe57de6bScheloha _kvm_err(kd, kd->program, "cannot read time_second");
150fe57de6bScheloha return (-1);
151fe57de6bScheloha }
152fe57de6bScheloha if (KREAD(kd, nl[1].n_value, &monostop.tv_sec)) {
153fe57de6bScheloha _kvm_err(kd, kd->program, "cannot read time_uptime");
154fe57de6bScheloha return (-1);
155fe57de6bScheloha }
156fe57de6bScheloha
157712e2ef1Sguenther /*
158712e2ef1Sguenther * Modelled on sysctl_doproc() in sys/kern/kern_sysctl.c
159712e2ef1Sguenther */
160712e2ef1Sguenther for (; cnt < maxcnt && pr != NULL; pr = LIST_NEXT(&process, ps_list)) {
161712e2ef1Sguenther if (KREAD(kd, (u_long)pr, &process)) {
162b3c702ccSguenther _kvm_err(kd, kd->program, "can't read process at %lx",
163712e2ef1Sguenther (u_long)pr);
16472596c46Sguenther return (-1);
16572596c46Sguenther }
166712e2ef1Sguenther if (process.ps_pgrp == NULL)
167712e2ef1Sguenther continue;
168644b4788Sguenther if (process.ps_flags & PS_EMBRYO)
169644b4788Sguenther continue;
170d559b8cbSguenther if (KREAD(kd, (u_long)process.ps_ucred, &ucred)) {
171b3c702ccSguenther _kvm_err(kd, kd->program, "can't read ucred at %lx",
172d559b8cbSguenther (u_long)process.ps_ucred);
17372596c46Sguenther return (-1);
17472596c46Sguenther }
175207e4b38Sguenther if (KREAD(kd, (u_long)process.ps_pgrp, &pgrp)) {
176b3c702ccSguenther _kvm_err(kd, kd->program, "can't read pgrp at %lx",
177b3c702ccSguenther (u_long)process.ps_pgrp);
17872596c46Sguenther return (-1);
17972596c46Sguenther }
18072596c46Sguenther if (KREAD(kd, (u_long)pgrp.pg_session, &sess)) {
181b3c702ccSguenther _kvm_err(kd, kd->program, "can't read session at %lx",
182b3c702ccSguenther (u_long)pgrp.pg_session);
18372596c46Sguenther return (-1);
18472596c46Sguenther }
185207e4b38Sguenther if ((process.ps_flags & PS_CONTROLT) && sess.s_ttyp != NULL &&
18672596c46Sguenther KREAD(kd, (u_long)sess.s_ttyp, &tty)) {
187b3c702ccSguenther _kvm_err(kd, kd->program, "can't read tty at %lx",
188b3c702ccSguenther (u_long)sess.s_ttyp);
18972596c46Sguenther return (-1);
19072596c46Sguenther }
191207e4b38Sguenther if (process.ps_pptr) {
192207e4b38Sguenther if (KREAD(kd, (u_long)process.ps_pptr, &process2)) {
19372596c46Sguenther _kvm_err(kd, kd->program,
194b3c702ccSguenther "can't read process at %lx",
195b3c702ccSguenther (u_long)process.ps_pptr);
196207e4b38Sguenther return (-1);
197207e4b38Sguenther }
1983b7181b7Sguenther parent_pid = process2.ps_pid;
19972596c46Sguenther }
20072596c46Sguenther else
20172596c46Sguenther parent_pid = 0;
20272596c46Sguenther if (sess.s_leader) {
203207e4b38Sguenther if (KREAD(kd, (u_long)sess.s_leader, &process2)) {
20472596c46Sguenther _kvm_err(kd, kd->program,
205b3c702ccSguenther "can't read proc at %lx",
206b3c702ccSguenther (u_long)sess.s_leader);
20772596c46Sguenther return (-1);
20872596c46Sguenther }
2093b7181b7Sguenther leader_pid = process2.ps_pid;
21072596c46Sguenther }
21172596c46Sguenther else
21272596c46Sguenther leader_pid = 0;
213de30f5ceSflorian if (process.ps_sigacts) {
214de30f5ceSflorian if (KREAD(kd, (u_long)process.ps_sigacts, &sa)) {
215b3c702ccSguenther _kvm_err(kd, kd->program,
216b3c702ccSguenther "can't read sigacts at %lx",
217de30f5ceSflorian (u_long)process.ps_sigacts);
2182725daddSguenther return (-1);
2192725daddSguenther }
2202725daddSguenther sap = &sa;
2212725daddSguenther }
2222725daddSguenther else
2232725daddSguenther sap = NULL;
22472596c46Sguenther
22572596c46Sguenther switch (op) {
22672596c46Sguenther case KERN_PROC_PID:
2279865b3a9Sasou if (process.ps_pid != (pid_t)arg)
22872596c46Sguenther continue;
22972596c46Sguenther break;
23072596c46Sguenther
23172596c46Sguenther case KERN_PROC_PGRP:
23272596c46Sguenther if (pgrp.pg_id != (pid_t)arg)
23372596c46Sguenther continue;
23472596c46Sguenther break;
23572596c46Sguenther
23672596c46Sguenther case KERN_PROC_SESSION:
23772596c46Sguenther if (sess.s_leader == NULL ||
238207e4b38Sguenther leader_pid != (pid_t)arg)
23972596c46Sguenther continue;
24072596c46Sguenther break;
24172596c46Sguenther
24272596c46Sguenther case KERN_PROC_TTY:
243207e4b38Sguenther if ((process.ps_flags & PS_CONTROLT) == 0 ||
24472596c46Sguenther sess.s_ttyp == NULL ||
24572596c46Sguenther tty.t_dev != (dev_t)arg)
24672596c46Sguenther continue;
24772596c46Sguenther break;
24872596c46Sguenther
24972596c46Sguenther case KERN_PROC_UID:
25072596c46Sguenther if (ucred.cr_uid != (uid_t)arg)
25172596c46Sguenther continue;
25272596c46Sguenther break;
25372596c46Sguenther
25472596c46Sguenther case KERN_PROC_RUID:
255d559b8cbSguenther if (ucred.cr_ruid != (uid_t)arg)
25672596c46Sguenther continue;
25772596c46Sguenther break;
25872596c46Sguenther
25972596c46Sguenther case KERN_PROC_ALL:
2603b7181b7Sguenther if (process.ps_flags & PS_SYSTEM)
26172596c46Sguenther continue;
26272596c46Sguenther break;
26372596c46Sguenther
26472596c46Sguenther case KERN_PROC_KTHREAD:
26572596c46Sguenther /* no filtering */
26672596c46Sguenther break;
26772596c46Sguenther
26872596c46Sguenther default:
26972596c46Sguenther _kvm_err(kd, kd->program, "invalid filter");
27072596c46Sguenther return (-1);
27172596c46Sguenther }
27272596c46Sguenther
27372596c46Sguenther /*
27472596c46Sguenther * We're going to add another proc to the set. If this
27572596c46Sguenther * will overflow the buffer, assume the reason is because
276f92569a5Sguenther * nthreads (or the proc list) is corrupt and declare an error.
27772596c46Sguenther */
27872596c46Sguenther if (cnt >= maxcnt) {
279f92569a5Sguenther _kvm_err(kd, kd->program, "nthreads corrupt");
28072596c46Sguenther return (-1);
28172596c46Sguenther }
28272596c46Sguenther
28372596c46Sguenther /* set up stuff that might not always be there */
28472596c46Sguenther limp = &limits;
28572596c46Sguenther if (!process.ps_limit ||
28672596c46Sguenther KREAD(kd, (u_long)process.ps_limit, &limits))
28772596c46Sguenther limp = NULL;
28872596c46Sguenther
289712e2ef1Sguenther vmp = NULL;
290712e2ef1Sguenther
291644b4788Sguenther if ((process.ps_flags & PS_ZOMBIE) == 0 &&
2929dac71e5Sguenther !KREAD(kd, (u_long)process.ps_vmspace, &vm))
293712e2ef1Sguenther vmp = &vm;
294712e2ef1Sguenther
29572596c46Sguenther #define do_copy_str(_d, _s, _l) kvm_read(kd, (u_long)(_s), (_d), (_l)-1)
296d559b8cbSguenther FILL_KPROC(&kp, do_copy_str, &proc, &process,
2973b7181b7Sguenther &ucred, &pgrp, process.ps_mainproc, pr, &sess,
298*dde46bf8Sclaudio vmp, limp, sap, &process.ps_tu, 0, 1);
299243c13beSpirofti
300243c13beSpirofti /* stuff that's too painful to generalize */
301243c13beSpirofti kp.p_ppid = parent_pid;
302243c13beSpirofti kp.p_sid = leader_pid;
303712e2ef1Sguenther if ((process.ps_flags & PS_CONTROLT) && sess.s_ttyp != NULL) {
304712e2ef1Sguenther kp.p_tdev = tty.t_dev;
305712e2ef1Sguenther if (tty.t_pgrp != NULL &&
306712e2ef1Sguenther tty.t_pgrp != process.ps_pgrp &&
307712e2ef1Sguenther KREAD(kd, (u_long)tty.t_pgrp, &pgrp)) {
308712e2ef1Sguenther _kvm_err(kd, kd->program,
309712e2ef1Sguenther "can't read tpgrp at %lx",
310712e2ef1Sguenther (u_long)tty.t_pgrp);
311712e2ef1Sguenther return (-1);
312712e2ef1Sguenther }
313712e2ef1Sguenther kp.p_tpgid = tty.t_pgrp ? pgrp.pg_id : -1;
314712e2ef1Sguenther kp.p_tsess = PTRTOINT64(tty.t_session);
315712e2ef1Sguenther } else {
316712e2ef1Sguenther kp.p_tpgid = -1;
317712e2ef1Sguenther kp.p_tdev = NODEV;
318712e2ef1Sguenther }
319712e2ef1Sguenther
320fe57de6bScheloha /* Convert the starting uptime to a starting UTC time. */
321fe57de6bScheloha if ((process.ps_flags & PS_ZOMBIE) == 0) {
322fe57de6bScheloha monostart.tv_sec = kp.p_ustart_sec;
323fe57de6bScheloha monostart.tv_usec = kp.p_ustart_usec;
324fe57de6bScheloha timersub(&monostop, &monostart, &elapsed);
325fe57de6bScheloha if (elapsed.tv_sec < 0)
326fe57de6bScheloha timerclear(&elapsed);
327fe57de6bScheloha timersub(&realstop, &elapsed, &realstart);
328fe57de6bScheloha kp.p_ustart_sec = realstart.tv_sec;
329fe57de6bScheloha kp.p_ustart_usec = realstart.tv_usec;
330fe57de6bScheloha }
331fe57de6bScheloha
332712e2ef1Sguenther /* update %cpu for all threads */
333644b4788Sguenther if (dothreads) {
3343b7181b7Sguenther if (KREAD(kd, (u_long)process.ps_mainproc, &proc)) {
3353b7181b7Sguenther _kvm_err(kd, kd->program,
3363b7181b7Sguenther "can't read proc at %lx",
3373b7181b7Sguenther (u_long)process.ps_mainproc);
3383b7181b7Sguenther return (-1);
3393b7181b7Sguenther }
340644b4788Sguenther kp.p_pctcpu = proc.p_pctcpu;
341644b4788Sguenther kp.p_stat = proc.p_stat;
342644b4788Sguenther } else {
343644b4788Sguenther kp.p_pctcpu = 0;
344644b4788Sguenther kp.p_stat = (process.ps_flags & PS_ZOMBIE) ? SDEAD :
345644b4788Sguenther SIDL;
346193f316cSmpi for (p = TAILQ_FIRST(&process.ps_threads); p != NULL;
347193f316cSmpi p = TAILQ_NEXT(&proc, p_thr_link)) {
348712e2ef1Sguenther if (KREAD(kd, (u_long)p, &proc)) {
349712e2ef1Sguenther _kvm_err(kd, kd->program,
350712e2ef1Sguenther "can't read proc at %lx",
351712e2ef1Sguenther (u_long)p);
352712e2ef1Sguenther return (-1);
353712e2ef1Sguenther }
354712e2ef1Sguenther kp.p_pctcpu += proc.p_pctcpu;
355644b4788Sguenther /*
356644b4788Sguenther * find best state:
357644b4788Sguenther * ONPROC > RUN > STOP > SLEEP > ...
358644b4788Sguenther */
359644b4788Sguenther if (proc.p_stat == SONPROC ||
360644b4788Sguenther kp.p_stat == SONPROC)
361644b4788Sguenther kp.p_stat = SONPROC;
362644b4788Sguenther else if (proc.p_stat == SRUN ||
363644b4788Sguenther kp.p_stat == SRUN)
364644b4788Sguenther kp.p_stat = SRUN;
365644b4788Sguenther else if (proc.p_stat == SSTOP ||
366644b4788Sguenther kp.p_stat == SSTOP)
367644b4788Sguenther kp.p_stat = SSTOP;
368644b4788Sguenther else if (proc.p_stat == SSLEEP)
369644b4788Sguenther kp.p_stat = SSLEEP;
370712e2ef1Sguenther }
371712e2ef1Sguenther }
372712e2ef1Sguenther
373712e2ef1Sguenther memcpy(bp, &kp, esize);
374712e2ef1Sguenther bp += esize;
375712e2ef1Sguenther ++cnt;
376712e2ef1Sguenther
377712e2ef1Sguenther /* Skip per-thread entries if not required by op */
378712e2ef1Sguenther if (!dothreads)
379712e2ef1Sguenther continue;
380712e2ef1Sguenther
381193f316cSmpi for (p = TAILQ_FIRST(&process.ps_threads); p != NULL;
382193f316cSmpi p = TAILQ_NEXT(&proc, p_thr_link)) {
383712e2ef1Sguenther if (KREAD(kd, (u_long)p, &proc)) {
384712e2ef1Sguenther _kvm_err(kd, kd->program,
385712e2ef1Sguenther "can't read proc at %lx",
386712e2ef1Sguenther (u_long)p);
387712e2ef1Sguenther return (-1);
388712e2ef1Sguenther }
389d559b8cbSguenther FILL_KPROC(&kp, do_copy_str, &proc, &process,
3903b7181b7Sguenther &ucred, &pgrp, p, pr, &sess, vmp, limp, sap,
391*dde46bf8Sclaudio &proc.p_tu, 1, 1);
392712e2ef1Sguenther
393712e2ef1Sguenther /* see above */
394712e2ef1Sguenther kp.p_ppid = parent_pid;
395712e2ef1Sguenther kp.p_sid = leader_pid;
396243c13beSpirofti if ((process.ps_flags & PS_CONTROLT) &&
397243c13beSpirofti sess.s_ttyp != NULL) {
398243c13beSpirofti kp.p_tdev = tty.t_dev;
399243c13beSpirofti if (tty.t_pgrp != NULL &&
400243c13beSpirofti tty.t_pgrp != process.ps_pgrp &&
401243c13beSpirofti KREAD(kd, (u_long)tty.t_pgrp, &pgrp)) {
402243c13beSpirofti _kvm_err(kd, kd->program,
403b3c702ccSguenther "can't read tpgrp at %lx",
404b3c702ccSguenther (u_long)tty.t_pgrp);
405243c13beSpirofti return (-1);
406243c13beSpirofti }
407243c13beSpirofti kp.p_tpgid = tty.t_pgrp ? pgrp.pg_id : -1;
408243c13beSpirofti kp.p_tsess = PTRTOINT64(tty.t_session);
409243c13beSpirofti } else {
410243c13beSpirofti kp.p_tpgid = -1;
411243c13beSpirofti kp.p_tdev = NODEV;
412243c13beSpirofti }
41372596c46Sguenther }
41472596c46Sguenther
41572596c46Sguenther memcpy(bp, &kp, esize);
41672596c46Sguenther bp += esize;
41772596c46Sguenther ++cnt;
418243c13beSpirofti #undef do_copy_str
41972596c46Sguenther }
42072596c46Sguenther return (cnt);
42172596c46Sguenther }
42272596c46Sguenther
42309431e5cSguenther struct kinfo_proc *
kvm_getprocs(kvm_t * kd,int op,int arg,size_t esize,int * cnt)42409431e5cSguenther kvm_getprocs(kvm_t *kd, int op, int arg, size_t esize, int *cnt)
42572596c46Sguenther {
426f92569a5Sguenther int mib[6], st, nthreads;
42758b561c5Sdlg void *procbase;
42872596c46Sguenther size_t size;
42972596c46Sguenther
43072596c46Sguenther if ((ssize_t)esize < 0)
43172596c46Sguenther return (NULL);
43272596c46Sguenther
43372596c46Sguenther if (ISALIVE(kd)) {
43472596c46Sguenther size = 0;
43572596c46Sguenther mib[0] = CTL_KERN;
43609431e5cSguenther mib[1] = KERN_PROC;
43772596c46Sguenther mib[2] = op;
43872596c46Sguenther mib[3] = arg;
43972596c46Sguenther mib[4] = esize;
44058b561c5Sdlg
44158b561c5Sdlg do {
44272596c46Sguenther mib[5] = 0;
44372596c46Sguenther st = sysctl(mib, 6, NULL, &size, NULL, 0);
44472596c46Sguenther if (st == -1) {
44509431e5cSguenther _kvm_syserr(kd, kd->program, "kvm_getprocs");
44672596c46Sguenther return (NULL);
44772596c46Sguenther }
44872596c46Sguenther
44958b561c5Sdlg size += size / 8; /* add ~10% */
45058b561c5Sdlg
45158b561c5Sdlg procbase = _kvm_realloc(kd, kd->procbase, size);
45258b561c5Sdlg if (procbase == NULL)
45372596c46Sguenther return (NULL);
45458b561c5Sdlg
45558b561c5Sdlg kd->procbase = procbase;
45658b561c5Sdlg
45758b561c5Sdlg mib[5] = size / esize;
45809431e5cSguenther st = sysctl(mib, 6, kd->procbase, &size, NULL, 0);
45958b561c5Sdlg if (st == -1 && errno != ENOMEM) {
46009431e5cSguenther _kvm_syserr(kd, kd->program, "kvm_getprocs");
46172596c46Sguenther return (NULL);
46272596c46Sguenther }
46358b561c5Sdlg } while (st == -1);
46458b561c5Sdlg
465f92569a5Sguenther nthreads = size / esize;
46672596c46Sguenther } else {
467712e2ef1Sguenther struct nlist nl[5];
468712e2ef1Sguenther int i, maxthread, maxprocess;
469712e2ef1Sguenther struct process *pr;
47072596c46Sguenther char *bp;
47172596c46Sguenther
47209431e5cSguenther if (esize > sizeof(struct kinfo_proc)) {
473d8035eb3Sguenther _kvm_syserr(kd, kd->program,
47409431e5cSguenther "kvm_getprocs: unknown fields requested: libkvm out of date?");
475d8035eb3Sguenther return (NULL);
476d8035eb3Sguenther }
477d8035eb3Sguenther
47872596c46Sguenther memset(nl, 0, sizeof(nl));
479f92569a5Sguenther nl[0].n_name = "_nthreads";
480712e2ef1Sguenther nl[1].n_name = "_nprocesses";
481712e2ef1Sguenther nl[2].n_name = "_allprocess";
482712e2ef1Sguenther nl[3].n_name = "_zombprocess";
483712e2ef1Sguenther nl[4].n_name = NULL;
48472596c46Sguenther
48572596c46Sguenther if (kvm_nlist(kd, nl) != 0) {
48672596c46Sguenther for (i = 0; nl[i].n_type != 0; ++i)
48772596c46Sguenther ;
48872596c46Sguenther _kvm_err(kd, kd->program,
48972596c46Sguenther "%s: no such symbol", nl[i].n_name);
49072596c46Sguenther return (NULL);
49172596c46Sguenther }
492f92569a5Sguenther if (KREAD(kd, nl[0].n_value, &maxthread)) {
493f92569a5Sguenther _kvm_err(kd, kd->program, "can't read nthreads");
49472596c46Sguenther return (NULL);
49572596c46Sguenther }
496712e2ef1Sguenther if (KREAD(kd, nl[1].n_value, &maxprocess)) {
497712e2ef1Sguenther _kvm_err(kd, kd->program, "can't read nprocesses");
498712e2ef1Sguenther return (NULL);
499712e2ef1Sguenther }
500712e2ef1Sguenther maxthread += maxprocess;
50172596c46Sguenther
502f4ccacb3Sderaadt kd->procbase = _kvm_reallocarray(kd, NULL, maxthread, esize);
50309431e5cSguenther if (kd->procbase == 0)
50472596c46Sguenther return (NULL);
50509431e5cSguenther bp = (char *)kd->procbase;
50672596c46Sguenther
507712e2ef1Sguenther /* allprocess */
508712e2ef1Sguenther if (KREAD(kd, nl[2].n_value, &pr)) {
509712e2ef1Sguenther _kvm_err(kd, kd->program, "cannot read allprocess");
51072596c46Sguenther return (NULL);
51172596c46Sguenther }
512712e2ef1Sguenther nthreads = kvm_proclist(kd, op, arg, pr, bp, maxthread, esize);
513f92569a5Sguenther if (nthreads < 0)
51472596c46Sguenther return (NULL);
51572596c46Sguenther
516712e2ef1Sguenther /* zombprocess */
517712e2ef1Sguenther if (KREAD(kd, nl[3].n_value, &pr)) {
518712e2ef1Sguenther _kvm_err(kd, kd->program, "cannot read zombprocess");
51972596c46Sguenther return (NULL);
52072596c46Sguenther }
521712e2ef1Sguenther i = kvm_proclist(kd, op, arg, pr, bp + (esize * nthreads),
522f92569a5Sguenther maxthread - nthreads, esize);
52372596c46Sguenther if (i > 0)
524f92569a5Sguenther nthreads += i;
52572596c46Sguenther }
526f92569a5Sguenther if (kd->procbase != NULL)
527f92569a5Sguenther *cnt = nthreads;
52809431e5cSguenther return (kd->procbase);
52909431e5cSguenther }
530