xref: /freebsd/lib/libprocstat/libprocstat.c (revision 094fc1ed0f2627525c7b0342efcbad5be7a8546a)
1 /*-
2  * Copyright (c) 2017 Dell EMC
3  * Copyright (c) 2009 Stanislav Sedov <stas@FreeBSD.org>
4  * Copyright (c) 1988, 1993
5  *      The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by the University of
18  *      California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38 
39 #include <sys/param.h>
40 #include <sys/elf.h>
41 #include <sys/time.h>
42 #include <sys/resourcevar.h>
43 #define	_WANT_UCRED
44 #include <sys/ucred.h>
45 #undef _WANT_UCRED
46 #include <sys/proc.h>
47 #include <sys/user.h>
48 #include <sys/stat.h>
49 #include <sys/vnode.h>
50 #include <sys/socket.h>
51 #define	_WANT_SOCKET
52 #include <sys/socketvar.h>
53 #include <sys/domain.h>
54 #include <sys/protosw.h>
55 #include <sys/un.h>
56 #define	_WANT_UNPCB
57 #include <sys/unpcb.h>
58 #include <sys/sysctl.h>
59 #include <sys/tty.h>
60 #include <sys/filedesc.h>
61 #include <sys/queue.h>
62 #define	_WANT_FILE
63 #include <sys/file.h>
64 #include <sys/conf.h>
65 #include <sys/ksem.h>
66 #include <sys/mman.h>
67 #include <sys/capsicum.h>
68 #include <sys/ptrace.h>
69 #define	_KERNEL
70 #include <sys/mount.h>
71 #include <sys/pipe.h>
72 #include <ufs/ufs/quota.h>
73 #include <ufs/ufs/inode.h>
74 #include <fs/devfs/devfs.h>
75 #include <fs/devfs/devfs_int.h>
76 #undef _KERNEL
77 #include <nfs/nfsproto.h>
78 #include <nfsclient/nfs.h>
79 #include <nfsclient/nfsnode.h>
80 
81 #include <vm/vm.h>
82 #include <vm/vm_map.h>
83 #include <vm/vm_object.h>
84 
85 #include <net/route.h>
86 #include <netinet/in.h>
87 #include <netinet/in_systm.h>
88 #include <netinet/ip.h>
89 #define	_WANT_INPCB
90 #include <netinet/in_pcb.h>
91 
92 #include <assert.h>
93 #include <ctype.h>
94 #include <err.h>
95 #include <fcntl.h>
96 #include <kvm.h>
97 #include <libutil.h>
98 #include <limits.h>
99 #include <paths.h>
100 #include <pwd.h>
101 #include <stdio.h>
102 #include <stdlib.h>
103 #include <stddef.h>
104 #include <string.h>
105 #include <unistd.h>
106 #include <netdb.h>
107 
108 #include <libprocstat.h>
109 #include "libprocstat_internal.h"
110 #include "common_kvm.h"
111 #include "core.h"
112 
113 int     statfs(const char *, struct statfs *);	/* XXX */
114 
115 #define	PROCSTAT_KVM	1
116 #define	PROCSTAT_SYSCTL	2
117 #define	PROCSTAT_CORE	3
118 
119 static char	**getargv(struct procstat *procstat, struct kinfo_proc *kp,
120     size_t nchr, int env);
121 static char	*getmnton(kvm_t *kd, struct mount *m);
122 static struct kinfo_vmentry *	kinfo_getvmmap_core(struct procstat_core *core,
123     int *cntp);
124 static Elf_Auxinfo	*procstat_getauxv_core(struct procstat_core *core,
125     unsigned int *cntp);
126 static Elf_Auxinfo	*procstat_getauxv_sysctl(pid_t pid, unsigned int *cntp);
127 static struct filestat_list	*procstat_getfiles_kvm(
128     struct procstat *procstat, struct kinfo_proc *kp, int mmapped);
129 static struct filestat_list	*procstat_getfiles_sysctl(
130     struct procstat *procstat, struct kinfo_proc *kp, int mmapped);
131 static int	procstat_get_pipe_info_sysctl(struct filestat *fst,
132     struct pipestat *pipe, char *errbuf);
133 static int	procstat_get_pipe_info_kvm(kvm_t *kd, struct filestat *fst,
134     struct pipestat *pipe, char *errbuf);
135 static int	procstat_get_pts_info_sysctl(struct filestat *fst,
136     struct ptsstat *pts, char *errbuf);
137 static int	procstat_get_pts_info_kvm(kvm_t *kd, struct filestat *fst,
138     struct ptsstat *pts, char *errbuf);
139 static int	procstat_get_sem_info_sysctl(struct filestat *fst,
140     struct semstat *sem, char *errbuf);
141 static int	procstat_get_sem_info_kvm(kvm_t *kd, struct filestat *fst,
142     struct semstat *sem, char *errbuf);
143 static int	procstat_get_shm_info_sysctl(struct filestat *fst,
144     struct shmstat *shm, char *errbuf);
145 static int	procstat_get_shm_info_kvm(kvm_t *kd, struct filestat *fst,
146     struct shmstat *shm, char *errbuf);
147 static int	procstat_get_socket_info_sysctl(struct filestat *fst,
148     struct sockstat *sock, char *errbuf);
149 static int	procstat_get_socket_info_kvm(kvm_t *kd, struct filestat *fst,
150     struct sockstat *sock, char *errbuf);
151 static int	to_filestat_flags(int flags);
152 static int	procstat_get_vnode_info_kvm(kvm_t *kd, struct filestat *fst,
153     struct vnstat *vn, char *errbuf);
154 static int	procstat_get_vnode_info_sysctl(struct filestat *fst,
155     struct vnstat *vn, char *errbuf);
156 static gid_t	*procstat_getgroups_core(struct procstat_core *core,
157     unsigned int *count);
158 static gid_t *	procstat_getgroups_kvm(kvm_t *kd, struct kinfo_proc *kp,
159     unsigned int *count);
160 static gid_t	*procstat_getgroups_sysctl(pid_t pid, unsigned int *count);
161 static struct kinfo_kstack	*procstat_getkstack_sysctl(pid_t pid,
162     int *cntp);
163 static int	procstat_getosrel_core(struct procstat_core *core,
164     int *osrelp);
165 static int	procstat_getosrel_kvm(kvm_t *kd, struct kinfo_proc *kp,
166     int *osrelp);
167 static int	procstat_getosrel_sysctl(pid_t pid, int *osrelp);
168 static int	procstat_getpathname_core(struct procstat_core *core,
169     char *pathname, size_t maxlen);
170 static int	procstat_getpathname_sysctl(pid_t pid, char *pathname,
171     size_t maxlen);
172 static int	procstat_getrlimit_core(struct procstat_core *core, int which,
173     struct rlimit* rlimit);
174 static int	procstat_getrlimit_kvm(kvm_t *kd, struct kinfo_proc *kp,
175     int which, struct rlimit* rlimit);
176 static int	procstat_getrlimit_sysctl(pid_t pid, int which,
177     struct rlimit* rlimit);
178 static int	procstat_getumask_core(struct procstat_core *core,
179     unsigned short *maskp);
180 static int	procstat_getumask_kvm(kvm_t *kd, struct kinfo_proc *kp,
181     unsigned short *maskp);
182 static int	procstat_getumask_sysctl(pid_t pid, unsigned short *maskp);
183 static int	vntype2psfsttype(int type);
184 
185 void
186 procstat_close(struct procstat *procstat)
187 {
188 
189 	assert(procstat);
190 	if (procstat->type == PROCSTAT_KVM)
191 		kvm_close(procstat->kd);
192 	else if (procstat->type == PROCSTAT_CORE)
193 		procstat_core_close(procstat->core);
194 	procstat_freeargv(procstat);
195 	procstat_freeenvv(procstat);
196 	free(procstat);
197 }
198 
199 struct procstat *
200 procstat_open_sysctl(void)
201 {
202 	struct procstat *procstat;
203 
204 	procstat = calloc(1, sizeof(*procstat));
205 	if (procstat == NULL) {
206 		warn("malloc()");
207 		return (NULL);
208 	}
209 	procstat->type = PROCSTAT_SYSCTL;
210 	return (procstat);
211 }
212 
213 struct procstat *
214 procstat_open_kvm(const char *nlistf, const char *memf)
215 {
216 	struct procstat *procstat;
217 	kvm_t *kd;
218 	char buf[_POSIX2_LINE_MAX];
219 
220 	procstat = calloc(1, sizeof(*procstat));
221 	if (procstat == NULL) {
222 		warn("malloc()");
223 		return (NULL);
224 	}
225 	kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf);
226 	if (kd == NULL) {
227 		warnx("kvm_openfiles(): %s", buf);
228 		free(procstat);
229 		return (NULL);
230 	}
231 	procstat->type = PROCSTAT_KVM;
232 	procstat->kd = kd;
233 	return (procstat);
234 }
235 
236 struct procstat *
237 procstat_open_core(const char *filename)
238 {
239 	struct procstat *procstat;
240 	struct procstat_core *core;
241 
242 	procstat = calloc(1, sizeof(*procstat));
243 	if (procstat == NULL) {
244 		warn("malloc()");
245 		return (NULL);
246 	}
247 	core = procstat_core_open(filename);
248 	if (core == NULL) {
249 		free(procstat);
250 		return (NULL);
251 	}
252 	procstat->type = PROCSTAT_CORE;
253 	procstat->core = core;
254 	return (procstat);
255 }
256 
257 struct kinfo_proc *
258 procstat_getprocs(struct procstat *procstat, int what, int arg,
259     unsigned int *count)
260 {
261 	struct kinfo_proc *p0, *p;
262 	size_t len, olen;
263 	int name[4];
264 	int cnt;
265 	int error;
266 
267 	assert(procstat);
268 	assert(count);
269 	p = NULL;
270 	if (procstat->type == PROCSTAT_KVM) {
271 		*count = 0;
272 		p0 = kvm_getprocs(procstat->kd, what, arg, &cnt);
273 		if (p0 == NULL || cnt <= 0)
274 			return (NULL);
275 		*count = cnt;
276 		len = *count * sizeof(*p);
277 		p = malloc(len);
278 		if (p == NULL) {
279 			warnx("malloc(%zu)", len);
280 			goto fail;
281 		}
282 		bcopy(p0, p, len);
283 		return (p);
284 	} else if (procstat->type == PROCSTAT_SYSCTL) {
285 		len = 0;
286 		name[0] = CTL_KERN;
287 		name[1] = KERN_PROC;
288 		name[2] = what;
289 		name[3] = arg;
290 		error = sysctl(name, nitems(name), NULL, &len, NULL, 0);
291 		if (error < 0 && errno != EPERM) {
292 			warn("sysctl(kern.proc)");
293 			goto fail;
294 		}
295 		if (len == 0) {
296 			warnx("no processes?");
297 			goto fail;
298 		}
299 		do {
300 			len += len / 10;
301 			p = reallocf(p, len);
302 			if (p == NULL) {
303 				warnx("reallocf(%zu)", len);
304 				goto fail;
305 			}
306 			olen = len;
307 			error = sysctl(name, nitems(name), p, &len, NULL, 0);
308 		} while (error < 0 && errno == ENOMEM && olen == len);
309 		if (error < 0 && errno != EPERM) {
310 			warn("sysctl(kern.proc)");
311 			goto fail;
312 		}
313 		/* Perform simple consistency checks. */
314 		if ((len % sizeof(*p)) != 0 || p->ki_structsize != sizeof(*p)) {
315 			warnx("kinfo_proc structure size mismatch (len = %zu)", len);
316 			goto fail;
317 		}
318 		*count = len / sizeof(*p);
319 		return (p);
320 	} else if (procstat->type == PROCSTAT_CORE) {
321 		p = procstat_core_get(procstat->core, PSC_TYPE_PROC, NULL,
322 		    &len);
323 		if ((len % sizeof(*p)) != 0 || p->ki_structsize != sizeof(*p)) {
324 			warnx("kinfo_proc structure size mismatch");
325 			goto fail;
326 		}
327 		*count = len / sizeof(*p);
328 		return (p);
329 	} else {
330 		warnx("unknown access method: %d", procstat->type);
331 		return (NULL);
332 	}
333 fail:
334 	if (p)
335 		free(p);
336 	return (NULL);
337 }
338 
339 void
340 procstat_freeprocs(struct procstat *procstat __unused, struct kinfo_proc *p)
341 {
342 
343 	if (p != NULL)
344 		free(p);
345 	p = NULL;
346 }
347 
348 struct filestat_list *
349 procstat_getfiles(struct procstat *procstat, struct kinfo_proc *kp, int mmapped)
350 {
351 
352 	switch(procstat->type) {
353 	case PROCSTAT_KVM:
354 		return (procstat_getfiles_kvm(procstat, kp, mmapped));
355 	case PROCSTAT_SYSCTL:
356 	case PROCSTAT_CORE:
357 		return (procstat_getfiles_sysctl(procstat, kp, mmapped));
358 	default:
359 		warnx("unknown access method: %d", procstat->type);
360 		return (NULL);
361 	}
362 }
363 
364 void
365 procstat_freefiles(struct procstat *procstat, struct filestat_list *head)
366 {
367 	struct filestat *fst, *tmp;
368 
369 	STAILQ_FOREACH_SAFE(fst, head, next, tmp) {
370 		if (fst->fs_path != NULL)
371 			free(fst->fs_path);
372 		free(fst);
373 	}
374 	free(head);
375 	if (procstat->vmentries != NULL) {
376 		free(procstat->vmentries);
377 		procstat->vmentries = NULL;
378 	}
379 	if (procstat->files != NULL) {
380 		free(procstat->files);
381 		procstat->files = NULL;
382 	}
383 }
384 
385 static struct filestat *
386 filestat_new_entry(void *typedep, int type, int fd, int fflags, int uflags,
387     int refcount, off_t offset, char *path, cap_rights_t *cap_rightsp)
388 {
389 	struct filestat *entry;
390 
391 	entry = calloc(1, sizeof(*entry));
392 	if (entry == NULL) {
393 		warn("malloc()");
394 		return (NULL);
395 	}
396 	entry->fs_typedep = typedep;
397 	entry->fs_fflags = fflags;
398 	entry->fs_uflags = uflags;
399 	entry->fs_fd = fd;
400 	entry->fs_type = type;
401 	entry->fs_ref_count = refcount;
402 	entry->fs_offset = offset;
403 	entry->fs_path = path;
404 	if (cap_rightsp != NULL)
405 		entry->fs_cap_rights = *cap_rightsp;
406 	else
407 		cap_rights_init(&entry->fs_cap_rights);
408 	return (entry);
409 }
410 
411 static struct vnode *
412 getctty(kvm_t *kd, struct kinfo_proc *kp)
413 {
414 	struct pgrp pgrp;
415 	struct proc proc;
416 	struct session sess;
417 	int error;
418 
419 	assert(kp);
420 	error = kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc,
421 	    sizeof(proc));
422 	if (error == 0) {
423 		warnx("can't read proc struct at %p for pid %d",
424 		    kp->ki_paddr, kp->ki_pid);
425 		return (NULL);
426 	}
427 	if (proc.p_pgrp == NULL)
428 		return (NULL);
429 	error = kvm_read_all(kd, (unsigned long)proc.p_pgrp, &pgrp,
430 	    sizeof(pgrp));
431 	if (error == 0) {
432 		warnx("can't read pgrp struct at %p for pid %d",
433 		    proc.p_pgrp, kp->ki_pid);
434 		return (NULL);
435 	}
436 	error = kvm_read_all(kd, (unsigned long)pgrp.pg_session, &sess,
437 	    sizeof(sess));
438 	if (error == 0) {
439 		warnx("can't read session struct at %p for pid %d",
440 		    pgrp.pg_session, kp->ki_pid);
441 		return (NULL);
442 	}
443 	return (sess.s_ttyvp);
444 }
445 
446 static struct filestat_list *
447 procstat_getfiles_kvm(struct procstat *procstat, struct kinfo_proc *kp, int mmapped)
448 {
449 	struct file file;
450 	struct filedesc filed;
451 	struct vm_map_entry vmentry;
452 	struct vm_object object;
453 	struct vmspace vmspace;
454 	vm_map_entry_t entryp;
455 	vm_map_t map;
456 	vm_object_t objp;
457 	struct vnode *vp;
458 	struct file **ofiles;
459 	struct filestat *entry;
460 	struct filestat_list *head;
461 	kvm_t *kd;
462 	void *data;
463 	int i, fflags;
464 	int prot, type;
465 	unsigned int nfiles;
466 
467 	assert(procstat);
468 	kd = procstat->kd;
469 	if (kd == NULL)
470 		return (NULL);
471 	if (kp->ki_fd == NULL)
472 		return (NULL);
473 	if (!kvm_read_all(kd, (unsigned long)kp->ki_fd, &filed,
474 	    sizeof(filed))) {
475 		warnx("can't read filedesc at %p", (void *)kp->ki_fd);
476 		return (NULL);
477 	}
478 
479 	/*
480 	 * Allocate list head.
481 	 */
482 	head = malloc(sizeof(*head));
483 	if (head == NULL)
484 		return (NULL);
485 	STAILQ_INIT(head);
486 
487 	/* root directory vnode, if one. */
488 	if (filed.fd_rdir) {
489 		entry = filestat_new_entry(filed.fd_rdir, PS_FST_TYPE_VNODE, -1,
490 		    PS_FST_FFLAG_READ, PS_FST_UFLAG_RDIR, 0, 0, NULL, NULL);
491 		if (entry != NULL)
492 			STAILQ_INSERT_TAIL(head, entry, next);
493 	}
494 	/* current working directory vnode. */
495 	if (filed.fd_cdir) {
496 		entry = filestat_new_entry(filed.fd_cdir, PS_FST_TYPE_VNODE, -1,
497 		    PS_FST_FFLAG_READ, PS_FST_UFLAG_CDIR, 0, 0, NULL, NULL);
498 		if (entry != NULL)
499 			STAILQ_INSERT_TAIL(head, entry, next);
500 	}
501 	/* jail root, if any. */
502 	if (filed.fd_jdir) {
503 		entry = filestat_new_entry(filed.fd_jdir, PS_FST_TYPE_VNODE, -1,
504 		    PS_FST_FFLAG_READ, PS_FST_UFLAG_JAIL, 0, 0, NULL, NULL);
505 		if (entry != NULL)
506 			STAILQ_INSERT_TAIL(head, entry, next);
507 	}
508 	/* ktrace vnode, if one */
509 	if (kp->ki_tracep) {
510 		entry = filestat_new_entry(kp->ki_tracep, PS_FST_TYPE_VNODE, -1,
511 		    PS_FST_FFLAG_READ | PS_FST_FFLAG_WRITE,
512 		    PS_FST_UFLAG_TRACE, 0, 0, NULL, NULL);
513 		if (entry != NULL)
514 			STAILQ_INSERT_TAIL(head, entry, next);
515 	}
516 	/* text vnode, if one */
517 	if (kp->ki_textvp) {
518 		entry = filestat_new_entry(kp->ki_textvp, PS_FST_TYPE_VNODE, -1,
519 		    PS_FST_FFLAG_READ, PS_FST_UFLAG_TEXT, 0, 0, NULL, NULL);
520 		if (entry != NULL)
521 			STAILQ_INSERT_TAIL(head, entry, next);
522 	}
523 	/* Controlling terminal. */
524 	if ((vp = getctty(kd, kp)) != NULL) {
525 		entry = filestat_new_entry(vp, PS_FST_TYPE_VNODE, -1,
526 		    PS_FST_FFLAG_READ | PS_FST_FFLAG_WRITE,
527 		    PS_FST_UFLAG_CTTY, 0, 0, NULL, NULL);
528 		if (entry != NULL)
529 			STAILQ_INSERT_TAIL(head, entry, next);
530 	}
531 
532 	nfiles = filed.fd_lastfile + 1;
533 	ofiles = malloc(nfiles * sizeof(struct file *));
534 	if (ofiles == NULL) {
535 		warn("malloc(%zu)", nfiles * sizeof(struct file *));
536 		goto do_mmapped;
537 	}
538 	if (!kvm_read_all(kd, (unsigned long)filed.fd_ofiles, ofiles,
539 	    nfiles * sizeof(struct file *))) {
540 		warnx("cannot read file structures at %p",
541 		    (void *)filed.fd_ofiles);
542 		free(ofiles);
543 		goto do_mmapped;
544 	}
545 	for (i = 0; i <= filed.fd_lastfile; i++) {
546 		if (ofiles[i] == NULL)
547 			continue;
548 		if (!kvm_read_all(kd, (unsigned long)ofiles[i], &file,
549 		    sizeof(struct file))) {
550 			warnx("can't read file %d at %p", i,
551 			    (void *)ofiles[i]);
552 			continue;
553 		}
554 		switch (file.f_type) {
555 		case DTYPE_VNODE:
556 			type = PS_FST_TYPE_VNODE;
557 			data = file.f_vnode;
558 			break;
559 		case DTYPE_SOCKET:
560 			type = PS_FST_TYPE_SOCKET;
561 			data = file.f_data;
562 			break;
563 		case DTYPE_PIPE:
564 			type = PS_FST_TYPE_PIPE;
565 			data = file.f_data;
566 			break;
567 		case DTYPE_FIFO:
568 			type = PS_FST_TYPE_FIFO;
569 			data = file.f_vnode;
570 			break;
571 #ifdef DTYPE_PTS
572 		case DTYPE_PTS:
573 			type = PS_FST_TYPE_PTS;
574 			data = file.f_data;
575 			break;
576 #endif
577 		case DTYPE_SEM:
578 			type = PS_FST_TYPE_SEM;
579 			data = file.f_data;
580 			break;
581 		case DTYPE_SHM:
582 			type = PS_FST_TYPE_SHM;
583 			data = file.f_data;
584 			break;
585 		case DTYPE_PROCDESC:
586 			type = PS_FST_TYPE_PROCDESC;
587 			data = file.f_data;
588 			break;
589 		default:
590 			continue;
591 		}
592 		/* XXXRW: No capability rights support for kvm yet. */
593 		entry = filestat_new_entry(data, type, i,
594 		    to_filestat_flags(file.f_flag), 0, 0, 0, NULL, NULL);
595 		if (entry != NULL)
596 			STAILQ_INSERT_TAIL(head, entry, next);
597 	}
598 	free(ofiles);
599 
600 do_mmapped:
601 
602 	/*
603 	 * Process mmapped files if requested.
604 	 */
605 	if (mmapped) {
606 		if (!kvm_read_all(kd, (unsigned long)kp->ki_vmspace, &vmspace,
607 		    sizeof(vmspace))) {
608 			warnx("can't read vmspace at %p",
609 			    (void *)kp->ki_vmspace);
610 			goto exit;
611 		}
612 		map = &vmspace.vm_map;
613 
614 		for (entryp = map->header.next;
615 		    entryp != &kp->ki_vmspace->vm_map.header;
616 		    entryp = vmentry.next) {
617 			if (!kvm_read_all(kd, (unsigned long)entryp, &vmentry,
618 			    sizeof(vmentry))) {
619 				warnx("can't read vm_map_entry at %p",
620 				    (void *)entryp);
621 				continue;
622 			}
623 			if (vmentry.eflags & MAP_ENTRY_IS_SUB_MAP)
624 				continue;
625 			if ((objp = vmentry.object.vm_object) == NULL)
626 				continue;
627 			for (; objp; objp = object.backing_object) {
628 				if (!kvm_read_all(kd, (unsigned long)objp,
629 				    &object, sizeof(object))) {
630 					warnx("can't read vm_object at %p",
631 					    (void *)objp);
632 					break;
633 				}
634 			}
635 
636 			/* We want only vnode objects. */
637 			if (object.type != OBJT_VNODE)
638 				continue;
639 
640 			prot = vmentry.protection;
641 			fflags = 0;
642 			if (prot & VM_PROT_READ)
643 				fflags = PS_FST_FFLAG_READ;
644 			if ((vmentry.eflags & MAP_ENTRY_COW) == 0 &&
645 			    prot & VM_PROT_WRITE)
646 				fflags |= PS_FST_FFLAG_WRITE;
647 
648 			/*
649 			 * Create filestat entry.
650 			 */
651 			entry = filestat_new_entry(object.handle,
652 			    PS_FST_TYPE_VNODE, -1, fflags,
653 			    PS_FST_UFLAG_MMAP, 0, 0, NULL, NULL);
654 			if (entry != NULL)
655 				STAILQ_INSERT_TAIL(head, entry, next);
656 		}
657 	}
658 exit:
659 	return (head);
660 }
661 
662 /*
663  * kinfo types to filestat translation.
664  */
665 static int
666 kinfo_type2fst(int kftype)
667 {
668 	static struct {
669 		int	kf_type;
670 		int	fst_type;
671 	} kftypes2fst[] = {
672 		{ KF_TYPE_PROCDESC, PS_FST_TYPE_PROCDESC },
673 		{ KF_TYPE_CRYPTO, PS_FST_TYPE_CRYPTO },
674 		{ KF_TYPE_FIFO, PS_FST_TYPE_FIFO },
675 		{ KF_TYPE_KQUEUE, PS_FST_TYPE_KQUEUE },
676 		{ KF_TYPE_MQUEUE, PS_FST_TYPE_MQUEUE },
677 		{ KF_TYPE_NONE, PS_FST_TYPE_NONE },
678 		{ KF_TYPE_PIPE, PS_FST_TYPE_PIPE },
679 		{ KF_TYPE_PTS, PS_FST_TYPE_PTS },
680 		{ KF_TYPE_SEM, PS_FST_TYPE_SEM },
681 		{ KF_TYPE_SHM, PS_FST_TYPE_SHM },
682 		{ KF_TYPE_SOCKET, PS_FST_TYPE_SOCKET },
683 		{ KF_TYPE_VNODE, PS_FST_TYPE_VNODE },
684 		{ KF_TYPE_UNKNOWN, PS_FST_TYPE_UNKNOWN }
685 	};
686 #define NKFTYPES	(sizeof(kftypes2fst) / sizeof(*kftypes2fst))
687 	unsigned int i;
688 
689 	for (i = 0; i < NKFTYPES; i++)
690 		if (kftypes2fst[i].kf_type == kftype)
691 			break;
692 	if (i == NKFTYPES)
693 		return (PS_FST_TYPE_UNKNOWN);
694 	return (kftypes2fst[i].fst_type);
695 }
696 
697 /*
698  * kinfo flags to filestat translation.
699  */
700 static int
701 kinfo_fflags2fst(int kfflags)
702 {
703 	static struct {
704 		int	kf_flag;
705 		int	fst_flag;
706 	} kfflags2fst[] = {
707 		{ KF_FLAG_APPEND, PS_FST_FFLAG_APPEND },
708 		{ KF_FLAG_ASYNC, PS_FST_FFLAG_ASYNC },
709 		{ KF_FLAG_CREAT, PS_FST_FFLAG_CREAT },
710 		{ KF_FLAG_DIRECT, PS_FST_FFLAG_DIRECT },
711 		{ KF_FLAG_EXCL, PS_FST_FFLAG_EXCL },
712 		{ KF_FLAG_EXEC, PS_FST_FFLAG_EXEC },
713 		{ KF_FLAG_EXLOCK, PS_FST_FFLAG_EXLOCK },
714 		{ KF_FLAG_FSYNC, PS_FST_FFLAG_SYNC },
715 		{ KF_FLAG_HASLOCK, PS_FST_FFLAG_HASLOCK },
716 		{ KF_FLAG_NOFOLLOW, PS_FST_FFLAG_NOFOLLOW },
717 		{ KF_FLAG_NONBLOCK, PS_FST_FFLAG_NONBLOCK },
718 		{ KF_FLAG_READ, PS_FST_FFLAG_READ },
719 		{ KF_FLAG_SHLOCK, PS_FST_FFLAG_SHLOCK },
720 		{ KF_FLAG_TRUNC, PS_FST_FFLAG_TRUNC },
721 		{ KF_FLAG_WRITE, PS_FST_FFLAG_WRITE }
722 	};
723 #define NKFFLAGS	(sizeof(kfflags2fst) / sizeof(*kfflags2fst))
724 	unsigned int i;
725 	int flags;
726 
727 	flags = 0;
728 	for (i = 0; i < NKFFLAGS; i++)
729 		if ((kfflags & kfflags2fst[i].kf_flag) != 0)
730 			flags |= kfflags2fst[i].fst_flag;
731 	return (flags);
732 }
733 
734 static int
735 kinfo_uflags2fst(int fd)
736 {
737 
738 	switch (fd) {
739 	case KF_FD_TYPE_CTTY:
740 		return (PS_FST_UFLAG_CTTY);
741 	case KF_FD_TYPE_CWD:
742 		return (PS_FST_UFLAG_CDIR);
743 	case KF_FD_TYPE_JAIL:
744 		return (PS_FST_UFLAG_JAIL);
745 	case KF_FD_TYPE_TEXT:
746 		return (PS_FST_UFLAG_TEXT);
747 	case KF_FD_TYPE_TRACE:
748 		return (PS_FST_UFLAG_TRACE);
749 	case KF_FD_TYPE_ROOT:
750 		return (PS_FST_UFLAG_RDIR);
751 	}
752 	return (0);
753 }
754 
755 static struct kinfo_file *
756 kinfo_getfile_core(struct procstat_core *core, int *cntp)
757 {
758 	int cnt;
759 	size_t len;
760 	char *buf, *bp, *eb;
761 	struct kinfo_file *kif, *kp, *kf;
762 
763 	buf = procstat_core_get(core, PSC_TYPE_FILES, NULL, &len);
764 	if (buf == NULL)
765 		return (NULL);
766 	/*
767 	 * XXXMG: The code below is just copy&past from libutil.
768 	 * The code duplication can be avoided if libutil
769 	 * is extended to provide something like:
770 	 *   struct kinfo_file *kinfo_getfile_from_buf(const char *buf,
771 	 *       size_t len, int *cntp);
772 	 */
773 
774 	/* Pass 1: count items */
775 	cnt = 0;
776 	bp = buf;
777 	eb = buf + len;
778 	while (bp < eb) {
779 		kf = (struct kinfo_file *)(uintptr_t)bp;
780 		if (kf->kf_structsize == 0)
781 			break;
782 		bp += kf->kf_structsize;
783 		cnt++;
784 	}
785 
786 	kif = calloc(cnt, sizeof(*kif));
787 	if (kif == NULL) {
788 		free(buf);
789 		return (NULL);
790 	}
791 	bp = buf;
792 	eb = buf + len;
793 	kp = kif;
794 	/* Pass 2: unpack */
795 	while (bp < eb) {
796 		kf = (struct kinfo_file *)(uintptr_t)bp;
797 		if (kf->kf_structsize == 0)
798 			break;
799 		/* Copy/expand into pre-zeroed buffer */
800 		memcpy(kp, kf, kf->kf_structsize);
801 		/* Advance to next packed record */
802 		bp += kf->kf_structsize;
803 		/* Set field size to fixed length, advance */
804 		kp->kf_structsize = sizeof(*kp);
805 		kp++;
806 	}
807 	free(buf);
808 	*cntp = cnt;
809 	return (kif);	/* Caller must free() return value */
810 }
811 
812 static struct filestat_list *
813 procstat_getfiles_sysctl(struct procstat *procstat, struct kinfo_proc *kp,
814     int mmapped)
815 {
816 	struct kinfo_file *kif, *files;
817 	struct kinfo_vmentry *kve, *vmentries;
818 	struct filestat_list *head;
819 	struct filestat *entry;
820 	char *path;
821 	off_t offset;
822 	int cnt, fd, fflags;
823 	int i, type, uflags;
824 	int refcount;
825 	cap_rights_t cap_rights;
826 
827 	assert(kp);
828 	if (kp->ki_fd == NULL)
829 		return (NULL);
830 	switch(procstat->type) {
831 	case PROCSTAT_SYSCTL:
832 		files = kinfo_getfile(kp->ki_pid, &cnt);
833 		break;
834 	case PROCSTAT_CORE:
835 		files = kinfo_getfile_core(procstat->core, &cnt);
836 		break;
837 	default:
838 		assert(!"invalid type");
839 	}
840 	if (files == NULL && errno != EPERM) {
841 		warn("kinfo_getfile()");
842 		return (NULL);
843 	}
844 	procstat->files = files;
845 
846 	/*
847 	 * Allocate list head.
848 	 */
849 	head = malloc(sizeof(*head));
850 	if (head == NULL)
851 		return (NULL);
852 	STAILQ_INIT(head);
853 	for (i = 0; i < cnt; i++) {
854 		kif = &files[i];
855 
856 		type = kinfo_type2fst(kif->kf_type);
857 		fd = kif->kf_fd >= 0 ? kif->kf_fd : -1;
858 		fflags = kinfo_fflags2fst(kif->kf_flags);
859 		uflags = kinfo_uflags2fst(kif->kf_fd);
860 		refcount = kif->kf_ref_count;
861 		offset = kif->kf_offset;
862 		if (*kif->kf_path != '\0')
863 			path = strdup(kif->kf_path);
864 		else
865 			path = NULL;
866 		cap_rights = kif->kf_cap_rights;
867 
868 		/*
869 		 * Create filestat entry.
870 		 */
871 		entry = filestat_new_entry(kif, type, fd, fflags, uflags,
872 		    refcount, offset, path, &cap_rights);
873 		if (entry != NULL)
874 			STAILQ_INSERT_TAIL(head, entry, next);
875 	}
876 	if (mmapped != 0) {
877 		vmentries = procstat_getvmmap(procstat, kp, &cnt);
878 		procstat->vmentries = vmentries;
879 		if (vmentries == NULL || cnt == 0)
880 			goto fail;
881 		for (i = 0; i < cnt; i++) {
882 			kve = &vmentries[i];
883 			if (kve->kve_type != KVME_TYPE_VNODE)
884 				continue;
885 			fflags = 0;
886 			if (kve->kve_protection & KVME_PROT_READ)
887 				fflags = PS_FST_FFLAG_READ;
888 			if ((kve->kve_flags & KVME_FLAG_COW) == 0 &&
889 			    kve->kve_protection & KVME_PROT_WRITE)
890 				fflags |= PS_FST_FFLAG_WRITE;
891 			offset = kve->kve_offset;
892 			refcount = kve->kve_ref_count;
893 			if (*kve->kve_path != '\0')
894 				path = strdup(kve->kve_path);
895 			else
896 				path = NULL;
897 			entry = filestat_new_entry(kve, PS_FST_TYPE_VNODE, -1,
898 			    fflags, PS_FST_UFLAG_MMAP, refcount, offset, path,
899 			    NULL);
900 			if (entry != NULL)
901 				STAILQ_INSERT_TAIL(head, entry, next);
902 		}
903 	}
904 fail:
905 	return (head);
906 }
907 
908 int
909 procstat_get_pipe_info(struct procstat *procstat, struct filestat *fst,
910     struct pipestat *ps, char *errbuf)
911 {
912 
913 	assert(ps);
914 	if (procstat->type == PROCSTAT_KVM) {
915 		return (procstat_get_pipe_info_kvm(procstat->kd, fst, ps,
916 		    errbuf));
917 	} else if (procstat->type == PROCSTAT_SYSCTL ||
918 		procstat->type == PROCSTAT_CORE) {
919 		return (procstat_get_pipe_info_sysctl(fst, ps, errbuf));
920 	} else {
921 		warnx("unknown access method: %d", procstat->type);
922 		if (errbuf != NULL)
923 			snprintf(errbuf, _POSIX2_LINE_MAX, "error");
924 		return (1);
925 	}
926 }
927 
928 static int
929 procstat_get_pipe_info_kvm(kvm_t *kd, struct filestat *fst,
930     struct pipestat *ps, char *errbuf)
931 {
932 	struct pipe pi;
933 	void *pipep;
934 
935 	assert(kd);
936 	assert(ps);
937 	assert(fst);
938 	bzero(ps, sizeof(*ps));
939 	pipep = fst->fs_typedep;
940 	if (pipep == NULL)
941 		goto fail;
942 	if (!kvm_read_all(kd, (unsigned long)pipep, &pi, sizeof(struct pipe))) {
943 		warnx("can't read pipe at %p", (void *)pipep);
944 		goto fail;
945 	}
946 	ps->addr = (uintptr_t)pipep;
947 	ps->peer = (uintptr_t)pi.pipe_peer;
948 	ps->buffer_cnt = pi.pipe_buffer.cnt;
949 	return (0);
950 
951 fail:
952 	if (errbuf != NULL)
953 		snprintf(errbuf, _POSIX2_LINE_MAX, "error");
954 	return (1);
955 }
956 
957 static int
958 procstat_get_pipe_info_sysctl(struct filestat *fst, struct pipestat *ps,
959     char *errbuf __unused)
960 {
961 	struct kinfo_file *kif;
962 
963 	assert(ps);
964 	assert(fst);
965 	bzero(ps, sizeof(*ps));
966 	kif = fst->fs_typedep;
967 	if (kif == NULL)
968 		return (1);
969 	ps->addr = kif->kf_un.kf_pipe.kf_pipe_addr;
970 	ps->peer = kif->kf_un.kf_pipe.kf_pipe_peer;
971 	ps->buffer_cnt = kif->kf_un.kf_pipe.kf_pipe_buffer_cnt;
972 	return (0);
973 }
974 
975 int
976 procstat_get_pts_info(struct procstat *procstat, struct filestat *fst,
977     struct ptsstat *pts, char *errbuf)
978 {
979 
980 	assert(pts);
981 	if (procstat->type == PROCSTAT_KVM) {
982 		return (procstat_get_pts_info_kvm(procstat->kd, fst, pts,
983 		    errbuf));
984 	} else if (procstat->type == PROCSTAT_SYSCTL ||
985 		procstat->type == PROCSTAT_CORE) {
986 		return (procstat_get_pts_info_sysctl(fst, pts, errbuf));
987 	} else {
988 		warnx("unknown access method: %d", procstat->type);
989 		if (errbuf != NULL)
990 			snprintf(errbuf, _POSIX2_LINE_MAX, "error");
991 		return (1);
992 	}
993 }
994 
995 static int
996 procstat_get_pts_info_kvm(kvm_t *kd, struct filestat *fst,
997     struct ptsstat *pts, char *errbuf)
998 {
999 	struct tty tty;
1000 	void *ttyp;
1001 
1002 	assert(kd);
1003 	assert(pts);
1004 	assert(fst);
1005 	bzero(pts, sizeof(*pts));
1006 	ttyp = fst->fs_typedep;
1007 	if (ttyp == NULL)
1008 		goto fail;
1009 	if (!kvm_read_all(kd, (unsigned long)ttyp, &tty, sizeof(struct tty))) {
1010 		warnx("can't read tty at %p", (void *)ttyp);
1011 		goto fail;
1012 	}
1013 	pts->dev = dev2udev(kd, tty.t_dev);
1014 	(void)kdevtoname(kd, tty.t_dev, pts->devname);
1015 	return (0);
1016 
1017 fail:
1018 	if (errbuf != NULL)
1019 		snprintf(errbuf, _POSIX2_LINE_MAX, "error");
1020 	return (1);
1021 }
1022 
1023 static int
1024 procstat_get_pts_info_sysctl(struct filestat *fst, struct ptsstat *pts,
1025     char *errbuf __unused)
1026 {
1027 	struct kinfo_file *kif;
1028 
1029 	assert(pts);
1030 	assert(fst);
1031 	bzero(pts, sizeof(*pts));
1032 	kif = fst->fs_typedep;
1033 	if (kif == NULL)
1034 		return (0);
1035 	pts->dev = kif->kf_un.kf_pts.kf_pts_dev;
1036 	strlcpy(pts->devname, kif->kf_path, sizeof(pts->devname));
1037 	return (0);
1038 }
1039 
1040 int
1041 procstat_get_sem_info(struct procstat *procstat, struct filestat *fst,
1042     struct semstat *sem, char *errbuf)
1043 {
1044 
1045 	assert(sem);
1046 	if (procstat->type == PROCSTAT_KVM) {
1047 		return (procstat_get_sem_info_kvm(procstat->kd, fst, sem,
1048 		    errbuf));
1049 	} else if (procstat->type == PROCSTAT_SYSCTL ||
1050 	    procstat->type == PROCSTAT_CORE) {
1051 		return (procstat_get_sem_info_sysctl(fst, sem, errbuf));
1052 	} else {
1053 		warnx("unknown access method: %d", procstat->type);
1054 		if (errbuf != NULL)
1055 			snprintf(errbuf, _POSIX2_LINE_MAX, "error");
1056 		return (1);
1057 	}
1058 }
1059 
1060 static int
1061 procstat_get_sem_info_kvm(kvm_t *kd, struct filestat *fst,
1062     struct semstat *sem, char *errbuf)
1063 {
1064 	struct ksem ksem;
1065 	void *ksemp;
1066 	char *path;
1067 	int i;
1068 
1069 	assert(kd);
1070 	assert(sem);
1071 	assert(fst);
1072 	bzero(sem, sizeof(*sem));
1073 	ksemp = fst->fs_typedep;
1074 	if (ksemp == NULL)
1075 		goto fail;
1076 	if (!kvm_read_all(kd, (unsigned long)ksemp, &ksem,
1077 	    sizeof(struct ksem))) {
1078 		warnx("can't read ksem at %p", (void *)ksemp);
1079 		goto fail;
1080 	}
1081 	sem->mode = S_IFREG | ksem.ks_mode;
1082 	sem->value = ksem.ks_value;
1083 	if (fst->fs_path == NULL && ksem.ks_path != NULL) {
1084 		path = malloc(MAXPATHLEN);
1085 		for (i = 0; i < MAXPATHLEN - 1; i++) {
1086 			if (!kvm_read_all(kd, (unsigned long)ksem.ks_path + i,
1087 			    path + i, 1))
1088 				break;
1089 			if (path[i] == '\0')
1090 				break;
1091 		}
1092 		path[i] = '\0';
1093 		if (i == 0)
1094 			free(path);
1095 		else
1096 			fst->fs_path = path;
1097 	}
1098 	return (0);
1099 
1100 fail:
1101 	if (errbuf != NULL)
1102 		snprintf(errbuf, _POSIX2_LINE_MAX, "error");
1103 	return (1);
1104 }
1105 
1106 static int
1107 procstat_get_sem_info_sysctl(struct filestat *fst, struct semstat *sem,
1108     char *errbuf __unused)
1109 {
1110 	struct kinfo_file *kif;
1111 
1112 	assert(sem);
1113 	assert(fst);
1114 	bzero(sem, sizeof(*sem));
1115 	kif = fst->fs_typedep;
1116 	if (kif == NULL)
1117 		return (0);
1118 	sem->value = kif->kf_un.kf_sem.kf_sem_value;
1119 	sem->mode = kif->kf_un.kf_sem.kf_sem_mode;
1120 	return (0);
1121 }
1122 
1123 int
1124 procstat_get_shm_info(struct procstat *procstat, struct filestat *fst,
1125     struct shmstat *shm, char *errbuf)
1126 {
1127 
1128 	assert(shm);
1129 	if (procstat->type == PROCSTAT_KVM) {
1130 		return (procstat_get_shm_info_kvm(procstat->kd, fst, shm,
1131 		    errbuf));
1132 	} else if (procstat->type == PROCSTAT_SYSCTL ||
1133 	    procstat->type == PROCSTAT_CORE) {
1134 		return (procstat_get_shm_info_sysctl(fst, shm, errbuf));
1135 	} else {
1136 		warnx("unknown access method: %d", procstat->type);
1137 		if (errbuf != NULL)
1138 			snprintf(errbuf, _POSIX2_LINE_MAX, "error");
1139 		return (1);
1140 	}
1141 }
1142 
1143 static int
1144 procstat_get_shm_info_kvm(kvm_t *kd, struct filestat *fst,
1145     struct shmstat *shm, char *errbuf)
1146 {
1147 	struct shmfd shmfd;
1148 	void *shmfdp;
1149 	char *path;
1150 	int i;
1151 
1152 	assert(kd);
1153 	assert(shm);
1154 	assert(fst);
1155 	bzero(shm, sizeof(*shm));
1156 	shmfdp = fst->fs_typedep;
1157 	if (shmfdp == NULL)
1158 		goto fail;
1159 	if (!kvm_read_all(kd, (unsigned long)shmfdp, &shmfd,
1160 	    sizeof(struct shmfd))) {
1161 		warnx("can't read shmfd at %p", (void *)shmfdp);
1162 		goto fail;
1163 	}
1164 	shm->mode = S_IFREG | shmfd.shm_mode;
1165 	shm->size = shmfd.shm_size;
1166 	if (fst->fs_path == NULL && shmfd.shm_path != NULL) {
1167 		path = malloc(MAXPATHLEN);
1168 		for (i = 0; i < MAXPATHLEN - 1; i++) {
1169 			if (!kvm_read_all(kd, (unsigned long)shmfd.shm_path + i,
1170 			    path + i, 1))
1171 				break;
1172 			if (path[i] == '\0')
1173 				break;
1174 		}
1175 		path[i] = '\0';
1176 		if (i == 0)
1177 			free(path);
1178 		else
1179 			fst->fs_path = path;
1180 	}
1181 	return (0);
1182 
1183 fail:
1184 	if (errbuf != NULL)
1185 		snprintf(errbuf, _POSIX2_LINE_MAX, "error");
1186 	return (1);
1187 }
1188 
1189 static int
1190 procstat_get_shm_info_sysctl(struct filestat *fst, struct shmstat *shm,
1191     char *errbuf __unused)
1192 {
1193 	struct kinfo_file *kif;
1194 
1195 	assert(shm);
1196 	assert(fst);
1197 	bzero(shm, sizeof(*shm));
1198 	kif = fst->fs_typedep;
1199 	if (kif == NULL)
1200 		return (0);
1201 	shm->size = kif->kf_un.kf_file.kf_file_size;
1202 	shm->mode = kif->kf_un.kf_file.kf_file_mode;
1203 	return (0);
1204 }
1205 
1206 int
1207 procstat_get_vnode_info(struct procstat *procstat, struct filestat *fst,
1208     struct vnstat *vn, char *errbuf)
1209 {
1210 
1211 	assert(vn);
1212 	if (procstat->type == PROCSTAT_KVM) {
1213 		return (procstat_get_vnode_info_kvm(procstat->kd, fst, vn,
1214 		    errbuf));
1215 	} else if (procstat->type == PROCSTAT_SYSCTL ||
1216 		procstat->type == PROCSTAT_CORE) {
1217 		return (procstat_get_vnode_info_sysctl(fst, vn, errbuf));
1218 	} else {
1219 		warnx("unknown access method: %d", procstat->type);
1220 		if (errbuf != NULL)
1221 			snprintf(errbuf, _POSIX2_LINE_MAX, "error");
1222 		return (1);
1223 	}
1224 }
1225 
1226 static int
1227 procstat_get_vnode_info_kvm(kvm_t *kd, struct filestat *fst,
1228     struct vnstat *vn, char *errbuf)
1229 {
1230 	/* Filesystem specific handlers. */
1231 	#define FSTYPE(fst)     {#fst, fst##_filestat}
1232 	struct {
1233 		const char	*tag;
1234 		int		(*handler)(kvm_t *kd, struct vnode *vp,
1235 		    struct vnstat *vn);
1236 	} fstypes[] = {
1237 		FSTYPE(devfs),
1238 		FSTYPE(isofs),
1239 		FSTYPE(msdosfs),
1240 		FSTYPE(nfs),
1241 		FSTYPE(smbfs),
1242 		FSTYPE(udf),
1243 		FSTYPE(ufs),
1244 #ifdef LIBPROCSTAT_ZFS
1245 		FSTYPE(zfs),
1246 #endif
1247 	};
1248 #define	NTYPES	(sizeof(fstypes) / sizeof(*fstypes))
1249 	struct vnode vnode;
1250 	char tagstr[12];
1251 	void *vp;
1252 	int error;
1253 	unsigned int i;
1254 
1255 	assert(kd);
1256 	assert(vn);
1257 	assert(fst);
1258 	vp = fst->fs_typedep;
1259 	if (vp == NULL)
1260 		goto fail;
1261 	error = kvm_read_all(kd, (unsigned long)vp, &vnode, sizeof(vnode));
1262 	if (error == 0) {
1263 		warnx("can't read vnode at %p", (void *)vp);
1264 		goto fail;
1265 	}
1266 	bzero(vn, sizeof(*vn));
1267 	vn->vn_type = vntype2psfsttype(vnode.v_type);
1268 	if (vnode.v_type == VNON || vnode.v_type == VBAD)
1269 		return (0);
1270 	error = kvm_read_all(kd, (unsigned long)vnode.v_tag, tagstr,
1271 	    sizeof(tagstr));
1272 	if (error == 0) {
1273 		warnx("can't read v_tag at %p", (void *)vp);
1274 		goto fail;
1275 	}
1276 	tagstr[sizeof(tagstr) - 1] = '\0';
1277 
1278 	/*
1279 	 * Find appropriate handler.
1280 	 */
1281 	for (i = 0; i < NTYPES; i++)
1282 		if (!strcmp(fstypes[i].tag, tagstr)) {
1283 			if (fstypes[i].handler(kd, &vnode, vn) != 0) {
1284 				goto fail;
1285 			}
1286 			break;
1287 		}
1288 	if (i == NTYPES) {
1289 		if (errbuf != NULL)
1290 			snprintf(errbuf, _POSIX2_LINE_MAX, "?(%s)", tagstr);
1291 		return (1);
1292 	}
1293 	vn->vn_mntdir = getmnton(kd, vnode.v_mount);
1294 	if ((vnode.v_type == VBLK || vnode.v_type == VCHR) &&
1295 	    vnode.v_rdev != NULL){
1296 		vn->vn_dev = dev2udev(kd, vnode.v_rdev);
1297 		(void)kdevtoname(kd, vnode.v_rdev, vn->vn_devname);
1298 	} else {
1299 		vn->vn_dev = -1;
1300 	}
1301 	return (0);
1302 
1303 fail:
1304 	if (errbuf != NULL)
1305 		snprintf(errbuf, _POSIX2_LINE_MAX, "error");
1306 	return (1);
1307 }
1308 
1309 /*
1310  * kinfo vnode type to filestat translation.
1311  */
1312 static int
1313 kinfo_vtype2fst(int kfvtype)
1314 {
1315 	static struct {
1316 		int	kf_vtype;
1317 		int	fst_vtype;
1318 	} kfvtypes2fst[] = {
1319 		{ KF_VTYPE_VBAD, PS_FST_VTYPE_VBAD },
1320 		{ KF_VTYPE_VBLK, PS_FST_VTYPE_VBLK },
1321 		{ KF_VTYPE_VCHR, PS_FST_VTYPE_VCHR },
1322 		{ KF_VTYPE_VDIR, PS_FST_VTYPE_VDIR },
1323 		{ KF_VTYPE_VFIFO, PS_FST_VTYPE_VFIFO },
1324 		{ KF_VTYPE_VLNK, PS_FST_VTYPE_VLNK },
1325 		{ KF_VTYPE_VNON, PS_FST_VTYPE_VNON },
1326 		{ KF_VTYPE_VREG, PS_FST_VTYPE_VREG },
1327 		{ KF_VTYPE_VSOCK, PS_FST_VTYPE_VSOCK }
1328 	};
1329 #define	NKFVTYPES	(sizeof(kfvtypes2fst) / sizeof(*kfvtypes2fst))
1330 	unsigned int i;
1331 
1332 	for (i = 0; i < NKFVTYPES; i++)
1333 		if (kfvtypes2fst[i].kf_vtype == kfvtype)
1334 			break;
1335 	if (i == NKFVTYPES)
1336 		return (PS_FST_VTYPE_UNKNOWN);
1337 	return (kfvtypes2fst[i].fst_vtype);
1338 }
1339 
1340 static int
1341 procstat_get_vnode_info_sysctl(struct filestat *fst, struct vnstat *vn,
1342     char *errbuf)
1343 {
1344 	struct statfs stbuf;
1345 	struct kinfo_file *kif;
1346 	struct kinfo_vmentry *kve;
1347 	char *name, *path;
1348 	uint64_t fileid;
1349 	uint64_t size;
1350 	uint64_t fsid;
1351 	uint64_t rdev;
1352 	uint16_t mode;
1353 	int vntype;
1354 	int status;
1355 
1356 	assert(fst);
1357 	assert(vn);
1358 	bzero(vn, sizeof(*vn));
1359 	if (fst->fs_typedep == NULL)
1360 		return (1);
1361 	if (fst->fs_uflags & PS_FST_UFLAG_MMAP) {
1362 		kve = fst->fs_typedep;
1363 		fileid = kve->kve_vn_fileid;
1364 		fsid = kve->kve_vn_fsid;
1365 		mode = kve->kve_vn_mode;
1366 		path = kve->kve_path;
1367 		rdev = kve->kve_vn_rdev;
1368 		size = kve->kve_vn_size;
1369 		vntype = kinfo_vtype2fst(kve->kve_vn_type);
1370 		status = kve->kve_status;
1371 	} else {
1372 		kif = fst->fs_typedep;
1373 		fileid = kif->kf_un.kf_file.kf_file_fileid;
1374 		fsid = kif->kf_un.kf_file.kf_file_fsid;
1375 		mode = kif->kf_un.kf_file.kf_file_mode;
1376 		path = kif->kf_path;
1377 		rdev = kif->kf_un.kf_file.kf_file_rdev;
1378 		size = kif->kf_un.kf_file.kf_file_size;
1379 		vntype = kinfo_vtype2fst(kif->kf_vnode_type);
1380 		status = kif->kf_status;
1381 	}
1382 	vn->vn_type = vntype;
1383 	if (vntype == PS_FST_VTYPE_VNON || vntype == PS_FST_VTYPE_VBAD)
1384 		return (0);
1385 	if ((status & KF_ATTR_VALID) == 0) {
1386 		if (errbuf != NULL) {
1387 			snprintf(errbuf, _POSIX2_LINE_MAX,
1388 			    "? (no info available)");
1389 		}
1390 		return (1);
1391 	}
1392 	if (path && *path) {
1393 		statfs(path, &stbuf);
1394 		vn->vn_mntdir = strdup(stbuf.f_mntonname);
1395 	} else
1396 		vn->vn_mntdir = strdup("-");
1397 	vn->vn_dev = rdev;
1398 	if (vntype == PS_FST_VTYPE_VBLK) {
1399 		name = devname(rdev, S_IFBLK);
1400 		if (name != NULL)
1401 			strlcpy(vn->vn_devname, name,
1402 			    sizeof(vn->vn_devname));
1403 	} else if (vntype == PS_FST_VTYPE_VCHR) {
1404 		name = devname(vn->vn_dev, S_IFCHR);
1405 		if (name != NULL)
1406 			strlcpy(vn->vn_devname, name,
1407 			    sizeof(vn->vn_devname));
1408 	}
1409 	vn->vn_fsid = fsid;
1410 	vn->vn_fileid = fileid;
1411 	vn->vn_size = size;
1412 	vn->vn_mode = mode;
1413 	return (0);
1414 }
1415 
1416 int
1417 procstat_get_socket_info(struct procstat *procstat, struct filestat *fst,
1418     struct sockstat *sock, char *errbuf)
1419 {
1420 
1421 	assert(sock);
1422 	if (procstat->type == PROCSTAT_KVM) {
1423 		return (procstat_get_socket_info_kvm(procstat->kd, fst, sock,
1424 		    errbuf));
1425 	} else if (procstat->type == PROCSTAT_SYSCTL ||
1426 		procstat->type == PROCSTAT_CORE) {
1427 		return (procstat_get_socket_info_sysctl(fst, sock, errbuf));
1428 	} else {
1429 		warnx("unknown access method: %d", procstat->type);
1430 		if (errbuf != NULL)
1431 			snprintf(errbuf, _POSIX2_LINE_MAX, "error");
1432 		return (1);
1433 	}
1434 }
1435 
1436 static int
1437 procstat_get_socket_info_kvm(kvm_t *kd, struct filestat *fst,
1438     struct sockstat *sock, char *errbuf)
1439 {
1440 	struct domain dom;
1441 	struct inpcb inpcb;
1442 	struct protosw proto;
1443 	struct socket s;
1444 	struct unpcb unpcb;
1445 	ssize_t len;
1446 	void *so;
1447 
1448 	assert(kd);
1449 	assert(sock);
1450 	assert(fst);
1451 	bzero(sock, sizeof(*sock));
1452 	so = fst->fs_typedep;
1453 	if (so == NULL)
1454 		goto fail;
1455 	sock->so_addr = (uintptr_t)so;
1456 	/* fill in socket */
1457 	if (!kvm_read_all(kd, (unsigned long)so, &s,
1458 	    sizeof(struct socket))) {
1459 		warnx("can't read sock at %p", (void *)so);
1460 		goto fail;
1461 	}
1462 	/* fill in protosw entry */
1463 	if (!kvm_read_all(kd, (unsigned long)s.so_proto, &proto,
1464 	    sizeof(struct protosw))) {
1465 		warnx("can't read protosw at %p", (void *)s.so_proto);
1466 		goto fail;
1467 	}
1468 	/* fill in domain */
1469 	if (!kvm_read_all(kd, (unsigned long)proto.pr_domain, &dom,
1470 	    sizeof(struct domain))) {
1471 		warnx("can't read domain at %p",
1472 		    (void *)proto.pr_domain);
1473 		goto fail;
1474 	}
1475 	if ((len = kvm_read(kd, (unsigned long)dom.dom_name, sock->dname,
1476 	    sizeof(sock->dname) - 1)) < 0) {
1477 		warnx("can't read domain name at %p", (void *)dom.dom_name);
1478 		sock->dname[0] = '\0';
1479 	}
1480 	else
1481 		sock->dname[len] = '\0';
1482 
1483 	/*
1484 	 * Fill in known data.
1485 	 */
1486 	sock->type = s.so_type;
1487 	sock->proto = proto.pr_protocol;
1488 	sock->dom_family = dom.dom_family;
1489 	sock->so_pcb = (uintptr_t)s.so_pcb;
1490 
1491 	/*
1492 	 * Protocol specific data.
1493 	 */
1494 	switch(dom.dom_family) {
1495 	case AF_INET:
1496 	case AF_INET6:
1497 		if (proto.pr_protocol == IPPROTO_TCP) {
1498 			if (s.so_pcb) {
1499 				if (kvm_read(kd, (u_long)s.so_pcb,
1500 				    (char *)&inpcb, sizeof(struct inpcb))
1501 				    != sizeof(struct inpcb)) {
1502 					warnx("can't read inpcb at %p",
1503 					    (void *)s.so_pcb);
1504 				} else
1505 					sock->inp_ppcb =
1506 					    (uintptr_t)inpcb.inp_ppcb;
1507 				sock->sendq = s.so_snd.sb_ccc;
1508 				sock->recvq = s.so_rcv.sb_ccc;
1509 			}
1510 		}
1511 		break;
1512 	case AF_UNIX:
1513 		if (s.so_pcb) {
1514 			if (kvm_read(kd, (u_long)s.so_pcb, (char *)&unpcb,
1515 			    sizeof(struct unpcb)) != sizeof(struct unpcb)){
1516 				warnx("can't read unpcb at %p",
1517 				    (void *)s.so_pcb);
1518 			} else if (unpcb.unp_conn) {
1519 				sock->so_rcv_sb_state = s.so_rcv.sb_state;
1520 				sock->so_snd_sb_state = s.so_snd.sb_state;
1521 				sock->unp_conn = (uintptr_t)unpcb.unp_conn;
1522 				sock->sendq = s.so_snd.sb_ccc;
1523 				sock->recvq = s.so_rcv.sb_ccc;
1524 			}
1525 		}
1526 		break;
1527 	default:
1528 		break;
1529 	}
1530 	return (0);
1531 
1532 fail:
1533 	if (errbuf != NULL)
1534 		snprintf(errbuf, _POSIX2_LINE_MAX, "error");
1535 	return (1);
1536 }
1537 
1538 static int
1539 procstat_get_socket_info_sysctl(struct filestat *fst, struct sockstat *sock,
1540     char *errbuf __unused)
1541 {
1542 	struct kinfo_file *kif;
1543 
1544 	assert(sock);
1545 	assert(fst);
1546 	bzero(sock, sizeof(*sock));
1547 	kif = fst->fs_typedep;
1548 	if (kif == NULL)
1549 		return (0);
1550 
1551 	/*
1552 	 * Fill in known data.
1553 	 */
1554 	sock->type = kif->kf_sock_type;
1555 	sock->proto = kif->kf_sock_protocol;
1556 	sock->dom_family = kif->kf_sock_domain;
1557 	sock->so_pcb = kif->kf_un.kf_sock.kf_sock_pcb;
1558 	strlcpy(sock->dname, kif->kf_path, sizeof(sock->dname));
1559 	bcopy(&kif->kf_un.kf_sock.kf_sa_local, &sock->sa_local,
1560 	    kif->kf_un.kf_sock.kf_sa_local.ss_len);
1561 	bcopy(&kif->kf_un.kf_sock.kf_sa_peer, &sock->sa_peer,
1562 	    kif->kf_un.kf_sock.kf_sa_peer.ss_len);
1563 
1564 	/*
1565 	 * Protocol specific data.
1566 	 */
1567 	switch(sock->dom_family) {
1568 	case AF_INET:
1569 	case AF_INET6:
1570 		if (sock->proto == IPPROTO_TCP) {
1571 			sock->inp_ppcb = kif->kf_un.kf_sock.kf_sock_inpcb;
1572 			sock->sendq = kif->kf_un.kf_sock.kf_sock_sendq;
1573 			sock->recvq = kif->kf_un.kf_sock.kf_sock_recvq;
1574 		}
1575 		break;
1576 	case AF_UNIX:
1577 		if (kif->kf_un.kf_sock.kf_sock_unpconn != 0) {
1578 			sock->so_rcv_sb_state =
1579 			    kif->kf_un.kf_sock.kf_sock_rcv_sb_state;
1580 			sock->so_snd_sb_state =
1581 			    kif->kf_un.kf_sock.kf_sock_snd_sb_state;
1582 			sock->unp_conn =
1583 			    kif->kf_un.kf_sock.kf_sock_unpconn;
1584 			sock->sendq = kif->kf_un.kf_sock.kf_sock_sendq;
1585 			sock->recvq = kif->kf_un.kf_sock.kf_sock_recvq;
1586 		}
1587 		break;
1588 	default:
1589 		break;
1590 	}
1591 	return (0);
1592 }
1593 
1594 /*
1595  * Descriptor flags to filestat translation.
1596  */
1597 static int
1598 to_filestat_flags(int flags)
1599 {
1600 	static struct {
1601 		int flag;
1602 		int fst_flag;
1603 	} fstflags[] = {
1604 		{ FREAD, PS_FST_FFLAG_READ },
1605 		{ FWRITE, PS_FST_FFLAG_WRITE },
1606 		{ O_APPEND, PS_FST_FFLAG_APPEND },
1607 		{ O_ASYNC, PS_FST_FFLAG_ASYNC },
1608 		{ O_CREAT, PS_FST_FFLAG_CREAT },
1609 		{ O_DIRECT, PS_FST_FFLAG_DIRECT },
1610 		{ O_EXCL, PS_FST_FFLAG_EXCL },
1611 		{ O_EXEC, PS_FST_FFLAG_EXEC },
1612 		{ O_EXLOCK, PS_FST_FFLAG_EXLOCK },
1613 		{ O_NOFOLLOW, PS_FST_FFLAG_NOFOLLOW },
1614 		{ O_NONBLOCK, PS_FST_FFLAG_NONBLOCK },
1615 		{ O_SHLOCK, PS_FST_FFLAG_SHLOCK },
1616 		{ O_SYNC, PS_FST_FFLAG_SYNC },
1617 		{ O_TRUNC, PS_FST_FFLAG_TRUNC }
1618 	};
1619 #define NFSTFLAGS	(sizeof(fstflags) / sizeof(*fstflags))
1620 	int fst_flags;
1621 	unsigned int i;
1622 
1623 	fst_flags = 0;
1624 	for (i = 0; i < NFSTFLAGS; i++)
1625 		if (flags & fstflags[i].flag)
1626 			fst_flags |= fstflags[i].fst_flag;
1627 	return (fst_flags);
1628 }
1629 
1630 /*
1631  * Vnode type to filestate translation.
1632  */
1633 static int
1634 vntype2psfsttype(int type)
1635 {
1636 	static struct {
1637 		int	vtype;
1638 		int	fst_vtype;
1639 	} vt2fst[] = {
1640 		{ VBAD, PS_FST_VTYPE_VBAD },
1641 		{ VBLK, PS_FST_VTYPE_VBLK },
1642 		{ VCHR, PS_FST_VTYPE_VCHR },
1643 		{ VDIR, PS_FST_VTYPE_VDIR },
1644 		{ VFIFO, PS_FST_VTYPE_VFIFO },
1645 		{ VLNK, PS_FST_VTYPE_VLNK },
1646 		{ VNON, PS_FST_VTYPE_VNON },
1647 		{ VREG, PS_FST_VTYPE_VREG },
1648 		{ VSOCK, PS_FST_VTYPE_VSOCK }
1649 	};
1650 #define	NVFTYPES	(sizeof(vt2fst) / sizeof(*vt2fst))
1651 	unsigned int i, fst_type;
1652 
1653 	fst_type = PS_FST_VTYPE_UNKNOWN;
1654 	for (i = 0; i < NVFTYPES; i++) {
1655 		if (type == vt2fst[i].vtype) {
1656 			fst_type = vt2fst[i].fst_vtype;
1657 			break;
1658 		}
1659 	}
1660 	return (fst_type);
1661 }
1662 
1663 static char *
1664 getmnton(kvm_t *kd, struct mount *m)
1665 {
1666 	struct mount mnt;
1667 	static struct mtab {
1668 		struct mtab *next;
1669 		struct mount *m;
1670 		char mntonname[MNAMELEN + 1];
1671 	} *mhead = NULL;
1672 	struct mtab *mt;
1673 
1674 	for (mt = mhead; mt != NULL; mt = mt->next)
1675 		if (m == mt->m)
1676 			return (mt->mntonname);
1677 	if (!kvm_read_all(kd, (unsigned long)m, &mnt, sizeof(struct mount))) {
1678 		warnx("can't read mount table at %p", (void *)m);
1679 		return (NULL);
1680 	}
1681 	if ((mt = malloc(sizeof (struct mtab))) == NULL)
1682 		err(1, NULL);
1683 	mt->m = m;
1684 	bcopy(&mnt.mnt_stat.f_mntonname[0], &mt->mntonname[0], MNAMELEN);
1685 	mt->mntonname[MNAMELEN] = '\0';
1686 	mt->next = mhead;
1687 	mhead = mt;
1688 	return (mt->mntonname);
1689 }
1690 
1691 /*
1692  * Auxiliary structures and functions to get process environment or
1693  * command line arguments.
1694  */
1695 struct argvec {
1696 	char	*buf;
1697 	size_t	bufsize;
1698 	char	**argv;
1699 	size_t	argc;
1700 };
1701 
1702 static struct argvec *
1703 argvec_alloc(size_t bufsize)
1704 {
1705 	struct argvec *av;
1706 
1707 	av = malloc(sizeof(*av));
1708 	if (av == NULL)
1709 		return (NULL);
1710 	av->bufsize = bufsize;
1711 	av->buf = malloc(av->bufsize);
1712 	if (av->buf == NULL) {
1713 		free(av);
1714 		return (NULL);
1715 	}
1716 	av->argc = 32;
1717 	av->argv = malloc(sizeof(char *) * av->argc);
1718 	if (av->argv == NULL) {
1719 		free(av->buf);
1720 		free(av);
1721 		return (NULL);
1722 	}
1723 	return av;
1724 }
1725 
1726 static void
1727 argvec_free(struct argvec * av)
1728 {
1729 
1730 	free(av->argv);
1731 	free(av->buf);
1732 	free(av);
1733 }
1734 
1735 static char **
1736 getargv(struct procstat *procstat, struct kinfo_proc *kp, size_t nchr, int env)
1737 {
1738 	int error, name[4], argc, i;
1739 	struct argvec *av, **avp;
1740 	enum psc_type type;
1741 	size_t len;
1742 	char *p, **argv;
1743 
1744 	assert(procstat);
1745 	assert(kp);
1746 	if (procstat->type == PROCSTAT_KVM) {
1747 		warnx("can't use kvm access method");
1748 		return (NULL);
1749 	}
1750 	if (procstat->type != PROCSTAT_SYSCTL &&
1751 	    procstat->type != PROCSTAT_CORE) {
1752 		warnx("unknown access method: %d", procstat->type);
1753 		return (NULL);
1754 	}
1755 
1756 	if (nchr == 0 || nchr > ARG_MAX)
1757 		nchr = ARG_MAX;
1758 
1759 	avp = (struct argvec **)(env ? &procstat->argv : &procstat->envv);
1760 	av = *avp;
1761 
1762 	if (av == NULL)
1763 	{
1764 		av = argvec_alloc(nchr);
1765 		if (av == NULL)
1766 		{
1767 			warn("malloc(%zu)", nchr);
1768 			return (NULL);
1769 		}
1770 		*avp = av;
1771 	} else if (av->bufsize < nchr) {
1772 		av->buf = reallocf(av->buf, nchr);
1773 		if (av->buf == NULL) {
1774 			warn("malloc(%zu)", nchr);
1775 			return (NULL);
1776 		}
1777 	}
1778 	if (procstat->type == PROCSTAT_SYSCTL) {
1779 		name[0] = CTL_KERN;
1780 		name[1] = KERN_PROC;
1781 		name[2] = env ? KERN_PROC_ENV : KERN_PROC_ARGS;
1782 		name[3] = kp->ki_pid;
1783 		len = nchr;
1784 		error = sysctl(name, nitems(name), av->buf, &len, NULL, 0);
1785 		if (error != 0 && errno != ESRCH && errno != EPERM)
1786 			warn("sysctl(kern.proc.%s)", env ? "env" : "args");
1787 		if (error != 0 || len == 0)
1788 			return (NULL);
1789 	} else /* procstat->type == PROCSTAT_CORE */ {
1790 		type = env ? PSC_TYPE_ENVV : PSC_TYPE_ARGV;
1791 		len = nchr;
1792 		if (procstat_core_get(procstat->core, type, av->buf, &len)
1793 		    == NULL) {
1794 			return (NULL);
1795 		}
1796 	}
1797 
1798 	argv = av->argv;
1799 	argc = av->argc;
1800 	i = 0;
1801 	for (p = av->buf; p < av->buf + len; p += strlen(p) + 1) {
1802 		argv[i++] = p;
1803 		if (i < argc)
1804 			continue;
1805 		/* Grow argv. */
1806 		argc += argc;
1807 		argv = realloc(argv, sizeof(char *) * argc);
1808 		if (argv == NULL) {
1809 			warn("malloc(%zu)", sizeof(char *) * argc);
1810 			return (NULL);
1811 		}
1812 		av->argv = argv;
1813 		av->argc = argc;
1814 	}
1815 	argv[i] = NULL;
1816 
1817 	return (argv);
1818 }
1819 
1820 /*
1821  * Return process command line arguments.
1822  */
1823 char **
1824 procstat_getargv(struct procstat *procstat, struct kinfo_proc *p, size_t nchr)
1825 {
1826 
1827 	return (getargv(procstat, p, nchr, 0));
1828 }
1829 
1830 /*
1831  * Free the buffer allocated by procstat_getargv().
1832  */
1833 void
1834 procstat_freeargv(struct procstat *procstat)
1835 {
1836 
1837 	if (procstat->argv != NULL) {
1838 		argvec_free(procstat->argv);
1839 		procstat->argv = NULL;
1840 	}
1841 }
1842 
1843 /*
1844  * Return process environment.
1845  */
1846 char **
1847 procstat_getenvv(struct procstat *procstat, struct kinfo_proc *p, size_t nchr)
1848 {
1849 
1850 	return (getargv(procstat, p, nchr, 1));
1851 }
1852 
1853 /*
1854  * Free the buffer allocated by procstat_getenvv().
1855  */
1856 void
1857 procstat_freeenvv(struct procstat *procstat)
1858 {
1859 	if (procstat->envv != NULL) {
1860 		argvec_free(procstat->envv);
1861 		procstat->envv = NULL;
1862 	}
1863 }
1864 
1865 static struct kinfo_vmentry *
1866 kinfo_getvmmap_core(struct procstat_core *core, int *cntp)
1867 {
1868 	int cnt;
1869 	size_t len;
1870 	char *buf, *bp, *eb;
1871 	struct kinfo_vmentry *kiv, *kp, *kv;
1872 
1873 	buf = procstat_core_get(core, PSC_TYPE_VMMAP, NULL, &len);
1874 	if (buf == NULL)
1875 		return (NULL);
1876 
1877 	/*
1878 	 * XXXMG: The code below is just copy&past from libutil.
1879 	 * The code duplication can be avoided if libutil
1880 	 * is extended to provide something like:
1881 	 *   struct kinfo_vmentry *kinfo_getvmmap_from_buf(const char *buf,
1882 	 *       size_t len, int *cntp);
1883 	 */
1884 
1885 	/* Pass 1: count items */
1886 	cnt = 0;
1887 	bp = buf;
1888 	eb = buf + len;
1889 	while (bp < eb) {
1890 		kv = (struct kinfo_vmentry *)(uintptr_t)bp;
1891 		if (kv->kve_structsize == 0)
1892 			break;
1893 		bp += kv->kve_structsize;
1894 		cnt++;
1895 	}
1896 
1897 	kiv = calloc(cnt, sizeof(*kiv));
1898 	if (kiv == NULL) {
1899 		free(buf);
1900 		return (NULL);
1901 	}
1902 	bp = buf;
1903 	eb = buf + len;
1904 	kp = kiv;
1905 	/* Pass 2: unpack */
1906 	while (bp < eb) {
1907 		kv = (struct kinfo_vmentry *)(uintptr_t)bp;
1908 		if (kv->kve_structsize == 0)
1909 			break;
1910 		/* Copy/expand into pre-zeroed buffer */
1911 		memcpy(kp, kv, kv->kve_structsize);
1912 		/* Advance to next packed record */
1913 		bp += kv->kve_structsize;
1914 		/* Set field size to fixed length, advance */
1915 		kp->kve_structsize = sizeof(*kp);
1916 		kp++;
1917 	}
1918 	free(buf);
1919 	*cntp = cnt;
1920 	return (kiv);	/* Caller must free() return value */
1921 }
1922 
1923 struct kinfo_vmentry *
1924 procstat_getvmmap(struct procstat *procstat, struct kinfo_proc *kp,
1925     unsigned int *cntp)
1926 {
1927 
1928 	switch(procstat->type) {
1929 	case PROCSTAT_KVM:
1930 		warnx("kvm method is not supported");
1931 		return (NULL);
1932 	case PROCSTAT_SYSCTL:
1933 		return (kinfo_getvmmap(kp->ki_pid, cntp));
1934 	case PROCSTAT_CORE:
1935 		return (kinfo_getvmmap_core(procstat->core, cntp));
1936 	default:
1937 		warnx("unknown access method: %d", procstat->type);
1938 		return (NULL);
1939 	}
1940 }
1941 
1942 void
1943 procstat_freevmmap(struct procstat *procstat __unused,
1944     struct kinfo_vmentry *vmmap)
1945 {
1946 
1947 	free(vmmap);
1948 }
1949 
1950 static gid_t *
1951 procstat_getgroups_kvm(kvm_t *kd, struct kinfo_proc *kp, unsigned int *cntp)
1952 {
1953 	struct proc proc;
1954 	struct ucred ucred;
1955 	gid_t *groups;
1956 	size_t len;
1957 
1958 	assert(kd != NULL);
1959 	assert(kp != NULL);
1960 	if (!kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc,
1961 	    sizeof(proc))) {
1962 		warnx("can't read proc struct at %p for pid %d",
1963 		    kp->ki_paddr, kp->ki_pid);
1964 		return (NULL);
1965 	}
1966 	if (proc.p_ucred == NOCRED)
1967 		return (NULL);
1968 	if (!kvm_read_all(kd, (unsigned long)proc.p_ucred, &ucred,
1969 	    sizeof(ucred))) {
1970 		warnx("can't read ucred struct at %p for pid %d",
1971 		    proc.p_ucred, kp->ki_pid);
1972 		return (NULL);
1973 	}
1974 	len = ucred.cr_ngroups * sizeof(gid_t);
1975 	groups = malloc(len);
1976 	if (groups == NULL) {
1977 		warn("malloc(%zu)", len);
1978 		return (NULL);
1979 	}
1980 	if (!kvm_read_all(kd, (unsigned long)ucred.cr_groups, groups, len)) {
1981 		warnx("can't read groups at %p for pid %d",
1982 		    ucred.cr_groups, kp->ki_pid);
1983 		free(groups);
1984 		return (NULL);
1985 	}
1986 	*cntp = ucred.cr_ngroups;
1987 	return (groups);
1988 }
1989 
1990 static gid_t *
1991 procstat_getgroups_sysctl(pid_t pid, unsigned int *cntp)
1992 {
1993 	int mib[4];
1994 	size_t len;
1995 	gid_t *groups;
1996 
1997 	mib[0] = CTL_KERN;
1998 	mib[1] = KERN_PROC;
1999 	mib[2] = KERN_PROC_GROUPS;
2000 	mib[3] = pid;
2001 	len = (sysconf(_SC_NGROUPS_MAX) + 1) * sizeof(gid_t);
2002 	groups = malloc(len);
2003 	if (groups == NULL) {
2004 		warn("malloc(%zu)", len);
2005 		return (NULL);
2006 	}
2007 	if (sysctl(mib, nitems(mib), groups, &len, NULL, 0) == -1) {
2008 		warn("sysctl: kern.proc.groups: %d", pid);
2009 		free(groups);
2010 		return (NULL);
2011 	}
2012 	*cntp = len / sizeof(gid_t);
2013 	return (groups);
2014 }
2015 
2016 static gid_t *
2017 procstat_getgroups_core(struct procstat_core *core, unsigned int *cntp)
2018 {
2019 	size_t len;
2020 	gid_t *groups;
2021 
2022 	groups = procstat_core_get(core, PSC_TYPE_GROUPS, NULL, &len);
2023 	if (groups == NULL)
2024 		return (NULL);
2025 	*cntp = len / sizeof(gid_t);
2026 	return (groups);
2027 }
2028 
2029 gid_t *
2030 procstat_getgroups(struct procstat *procstat, struct kinfo_proc *kp,
2031     unsigned int *cntp)
2032 {
2033 	switch(procstat->type) {
2034 	case PROCSTAT_KVM:
2035 		return (procstat_getgroups_kvm(procstat->kd, kp, cntp));
2036 	case PROCSTAT_SYSCTL:
2037 		return (procstat_getgroups_sysctl(kp->ki_pid, cntp));
2038 	case PROCSTAT_CORE:
2039 		return (procstat_getgroups_core(procstat->core, cntp));
2040 	default:
2041 		warnx("unknown access method: %d", procstat->type);
2042 		return (NULL);
2043 	}
2044 }
2045 
2046 void
2047 procstat_freegroups(struct procstat *procstat __unused, gid_t *groups)
2048 {
2049 
2050 	free(groups);
2051 }
2052 
2053 static int
2054 procstat_getumask_kvm(kvm_t *kd, struct kinfo_proc *kp, unsigned short *maskp)
2055 {
2056 	struct filedesc fd;
2057 
2058 	assert(kd != NULL);
2059 	assert(kp != NULL);
2060 	if (kp->ki_fd == NULL)
2061 		return (-1);
2062 	if (!kvm_read_all(kd, (unsigned long)kp->ki_fd, &fd, sizeof(fd))) {
2063 		warnx("can't read filedesc at %p for pid %d", kp->ki_fd,
2064 		    kp->ki_pid);
2065 		return (-1);
2066 	}
2067 	*maskp = fd.fd_cmask;
2068 	return (0);
2069 }
2070 
2071 static int
2072 procstat_getumask_sysctl(pid_t pid, unsigned short *maskp)
2073 {
2074 	int error;
2075 	int mib[4];
2076 	size_t len;
2077 
2078 	mib[0] = CTL_KERN;
2079 	mib[1] = KERN_PROC;
2080 	mib[2] = KERN_PROC_UMASK;
2081 	mib[3] = pid;
2082 	len = sizeof(*maskp);
2083 	error = sysctl(mib, nitems(mib), maskp, &len, NULL, 0);
2084 	if (error != 0 && errno != ESRCH && errno != EPERM)
2085 		warn("sysctl: kern.proc.umask: %d", pid);
2086 	return (error);
2087 }
2088 
2089 static int
2090 procstat_getumask_core(struct procstat_core *core, unsigned short *maskp)
2091 {
2092 	size_t len;
2093 	unsigned short *buf;
2094 
2095 	buf = procstat_core_get(core, PSC_TYPE_UMASK, NULL, &len);
2096 	if (buf == NULL)
2097 		return (-1);
2098 	if (len < sizeof(*maskp)) {
2099 		free(buf);
2100 		return (-1);
2101 	}
2102 	*maskp = *buf;
2103 	free(buf);
2104 	return (0);
2105 }
2106 
2107 int
2108 procstat_getumask(struct procstat *procstat, struct kinfo_proc *kp,
2109     unsigned short *maskp)
2110 {
2111 	switch(procstat->type) {
2112 	case PROCSTAT_KVM:
2113 		return (procstat_getumask_kvm(procstat->kd, kp, maskp));
2114 	case PROCSTAT_SYSCTL:
2115 		return (procstat_getumask_sysctl(kp->ki_pid, maskp));
2116 	case PROCSTAT_CORE:
2117 		return (procstat_getumask_core(procstat->core, maskp));
2118 	default:
2119 		warnx("unknown access method: %d", procstat->type);
2120 		return (-1);
2121 	}
2122 }
2123 
2124 static int
2125 procstat_getrlimit_kvm(kvm_t *kd, struct kinfo_proc *kp, int which,
2126     struct rlimit* rlimit)
2127 {
2128 	struct proc proc;
2129 	unsigned long offset;
2130 
2131 	assert(kd != NULL);
2132 	assert(kp != NULL);
2133 	assert(which >= 0 && which < RLIM_NLIMITS);
2134 	if (!kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc,
2135 	    sizeof(proc))) {
2136 		warnx("can't read proc struct at %p for pid %d",
2137 		    kp->ki_paddr, kp->ki_pid);
2138 		return (-1);
2139 	}
2140 	if (proc.p_limit == NULL)
2141 		return (-1);
2142 	offset = (unsigned long)proc.p_limit + sizeof(struct rlimit) * which;
2143 	if (!kvm_read_all(kd, offset, rlimit, sizeof(*rlimit))) {
2144 		warnx("can't read rlimit struct at %p for pid %d",
2145 		    (void *)offset, kp->ki_pid);
2146 		return (-1);
2147 	}
2148 	return (0);
2149 }
2150 
2151 static int
2152 procstat_getrlimit_sysctl(pid_t pid, int which, struct rlimit* rlimit)
2153 {
2154 	int error, name[5];
2155 	size_t len;
2156 
2157 	name[0] = CTL_KERN;
2158 	name[1] = KERN_PROC;
2159 	name[2] = KERN_PROC_RLIMIT;
2160 	name[3] = pid;
2161 	name[4] = which;
2162 	len = sizeof(struct rlimit);
2163 	error = sysctl(name, nitems(name), rlimit, &len, NULL, 0);
2164 	if (error < 0 && errno != ESRCH) {
2165 		warn("sysctl: kern.proc.rlimit: %d", pid);
2166 		return (-1);
2167 	}
2168 	if (error < 0 || len != sizeof(struct rlimit))
2169 		return (-1);
2170 	return (0);
2171 }
2172 
2173 static int
2174 procstat_getrlimit_core(struct procstat_core *core, int which,
2175     struct rlimit* rlimit)
2176 {
2177 	size_t len;
2178 	struct rlimit* rlimits;
2179 
2180 	if (which < 0 || which >= RLIM_NLIMITS) {
2181 		errno = EINVAL;
2182 		warn("getrlimit: which");
2183 		return (-1);
2184 	}
2185 	rlimits = procstat_core_get(core, PSC_TYPE_RLIMIT, NULL, &len);
2186 	if (rlimits == NULL)
2187 		return (-1);
2188 	if (len < sizeof(struct rlimit) * RLIM_NLIMITS) {
2189 		free(rlimits);
2190 		return (-1);
2191 	}
2192 	*rlimit = rlimits[which];
2193 	return (0);
2194 }
2195 
2196 int
2197 procstat_getrlimit(struct procstat *procstat, struct kinfo_proc *kp, int which,
2198     struct rlimit* rlimit)
2199 {
2200 	switch(procstat->type) {
2201 	case PROCSTAT_KVM:
2202 		return (procstat_getrlimit_kvm(procstat->kd, kp, which,
2203 		    rlimit));
2204 	case PROCSTAT_SYSCTL:
2205 		return (procstat_getrlimit_sysctl(kp->ki_pid, which, rlimit));
2206 	case PROCSTAT_CORE:
2207 		return (procstat_getrlimit_core(procstat->core, which, rlimit));
2208 	default:
2209 		warnx("unknown access method: %d", procstat->type);
2210 		return (-1);
2211 	}
2212 }
2213 
2214 static int
2215 procstat_getpathname_sysctl(pid_t pid, char *pathname, size_t maxlen)
2216 {
2217 	int error, name[4];
2218 	size_t len;
2219 
2220 	name[0] = CTL_KERN;
2221 	name[1] = KERN_PROC;
2222 	name[2] = KERN_PROC_PATHNAME;
2223 	name[3] = pid;
2224 	len = maxlen;
2225 	error = sysctl(name, nitems(name), pathname, &len, NULL, 0);
2226 	if (error != 0 && errno != ESRCH)
2227 		warn("sysctl: kern.proc.pathname: %d", pid);
2228 	if (len == 0)
2229 		pathname[0] = '\0';
2230 	return (error);
2231 }
2232 
2233 static int
2234 procstat_getpathname_core(struct procstat_core *core, char *pathname,
2235     size_t maxlen)
2236 {
2237 	struct kinfo_file *files;
2238 	int cnt, i, result;
2239 
2240 	files = kinfo_getfile_core(core, &cnt);
2241 	if (files == NULL)
2242 		return (-1);
2243 	result = -1;
2244 	for (i = 0; i < cnt; i++) {
2245 		if (files[i].kf_fd != KF_FD_TYPE_TEXT)
2246 			continue;
2247 		strncpy(pathname, files[i].kf_path, maxlen);
2248 		result = 0;
2249 		break;
2250 	}
2251 	free(files);
2252 	return (result);
2253 }
2254 
2255 int
2256 procstat_getpathname(struct procstat *procstat, struct kinfo_proc *kp,
2257     char *pathname, size_t maxlen)
2258 {
2259 	switch(procstat->type) {
2260 	case PROCSTAT_KVM:
2261 		/* XXX: Return empty string. */
2262 		if (maxlen > 0)
2263 			pathname[0] = '\0';
2264 		return (0);
2265 	case PROCSTAT_SYSCTL:
2266 		return (procstat_getpathname_sysctl(kp->ki_pid, pathname,
2267 		    maxlen));
2268 	case PROCSTAT_CORE:
2269 		return (procstat_getpathname_core(procstat->core, pathname,
2270 		    maxlen));
2271 	default:
2272 		warnx("unknown access method: %d", procstat->type);
2273 		return (-1);
2274 	}
2275 }
2276 
2277 static int
2278 procstat_getosrel_kvm(kvm_t *kd, struct kinfo_proc *kp, int *osrelp)
2279 {
2280 	struct proc proc;
2281 
2282 	assert(kd != NULL);
2283 	assert(kp != NULL);
2284 	if (!kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc,
2285 	    sizeof(proc))) {
2286 		warnx("can't read proc struct at %p for pid %d",
2287 		    kp->ki_paddr, kp->ki_pid);
2288 		return (-1);
2289 	}
2290 	*osrelp = proc.p_osrel;
2291 	return (0);
2292 }
2293 
2294 static int
2295 procstat_getosrel_sysctl(pid_t pid, int *osrelp)
2296 {
2297 	int error, name[4];
2298 	size_t len;
2299 
2300 	name[0] = CTL_KERN;
2301 	name[1] = KERN_PROC;
2302 	name[2] = KERN_PROC_OSREL;
2303 	name[3] = pid;
2304 	len = sizeof(*osrelp);
2305 	error = sysctl(name, nitems(name), osrelp, &len, NULL, 0);
2306 	if (error != 0 && errno != ESRCH)
2307 		warn("sysctl: kern.proc.osrel: %d", pid);
2308 	return (error);
2309 }
2310 
2311 static int
2312 procstat_getosrel_core(struct procstat_core *core, int *osrelp)
2313 {
2314 	size_t len;
2315 	int *buf;
2316 
2317 	buf = procstat_core_get(core, PSC_TYPE_OSREL, NULL, &len);
2318 	if (buf == NULL)
2319 		return (-1);
2320 	if (len < sizeof(*osrelp)) {
2321 		free(buf);
2322 		return (-1);
2323 	}
2324 	*osrelp = *buf;
2325 	free(buf);
2326 	return (0);
2327 }
2328 
2329 int
2330 procstat_getosrel(struct procstat *procstat, struct kinfo_proc *kp, int *osrelp)
2331 {
2332 	switch(procstat->type) {
2333 	case PROCSTAT_KVM:
2334 		return (procstat_getosrel_kvm(procstat->kd, kp, osrelp));
2335 	case PROCSTAT_SYSCTL:
2336 		return (procstat_getosrel_sysctl(kp->ki_pid, osrelp));
2337 	case PROCSTAT_CORE:
2338 		return (procstat_getosrel_core(procstat->core, osrelp));
2339 	default:
2340 		warnx("unknown access method: %d", procstat->type);
2341 		return (-1);
2342 	}
2343 }
2344 
2345 #define PROC_AUXV_MAX	256
2346 
2347 #if __ELF_WORD_SIZE == 64
2348 static const char *elf32_sv_names[] = {
2349 	"Linux ELF32",
2350 	"FreeBSD ELF32",
2351 };
2352 
2353 static int
2354 is_elf32_sysctl(pid_t pid)
2355 {
2356 	int error, name[4];
2357 	size_t len, i;
2358 	static char sv_name[256];
2359 
2360 	name[0] = CTL_KERN;
2361 	name[1] = KERN_PROC;
2362 	name[2] = KERN_PROC_SV_NAME;
2363 	name[3] = pid;
2364 	len = sizeof(sv_name);
2365 	error = sysctl(name, nitems(name), sv_name, &len, NULL, 0);
2366 	if (error != 0 || len == 0)
2367 		return (0);
2368 	for (i = 0; i < sizeof(elf32_sv_names) / sizeof(*elf32_sv_names); i++) {
2369 		if (strncmp(sv_name, elf32_sv_names[i], sizeof(sv_name)) == 0)
2370 			return (1);
2371 	}
2372 	return (0);
2373 }
2374 
2375 static Elf_Auxinfo *
2376 procstat_getauxv32_sysctl(pid_t pid, unsigned int *cntp)
2377 {
2378 	Elf_Auxinfo *auxv;
2379 	Elf32_Auxinfo *auxv32;
2380 	void *ptr;
2381 	size_t len;
2382 	unsigned int i, count;
2383 	int name[4];
2384 
2385 	name[0] = CTL_KERN;
2386 	name[1] = KERN_PROC;
2387 	name[2] = KERN_PROC_AUXV;
2388 	name[3] = pid;
2389 	len = PROC_AUXV_MAX * sizeof(Elf32_Auxinfo);
2390 	auxv = NULL;
2391 	auxv32 = malloc(len);
2392 	if (auxv32 == NULL) {
2393 		warn("malloc(%zu)", len);
2394 		goto out;
2395 	}
2396 	if (sysctl(name, nitems(name), auxv32, &len, NULL, 0) == -1) {
2397 		if (errno != ESRCH && errno != EPERM)
2398 			warn("sysctl: kern.proc.auxv: %d: %d", pid, errno);
2399 		goto out;
2400 	}
2401 	count = len / sizeof(Elf_Auxinfo);
2402 	auxv = malloc(count  * sizeof(Elf_Auxinfo));
2403 	if (auxv == NULL) {
2404 		warn("malloc(%zu)", count * sizeof(Elf_Auxinfo));
2405 		goto out;
2406 	}
2407 	for (i = 0; i < count; i++) {
2408 		/*
2409 		 * XXX: We expect that values for a_type on a 32-bit platform
2410 		 * are directly mapped to values on 64-bit one, which is not
2411 		 * necessarily true.
2412 		 */
2413 		auxv[i].a_type = auxv32[i].a_type;
2414 		ptr = &auxv32[i].a_un;
2415 		auxv[i].a_un.a_val = *((uint32_t *)ptr);
2416 	}
2417 	*cntp = count;
2418 out:
2419 	free(auxv32);
2420 	return (auxv);
2421 }
2422 #endif /* __ELF_WORD_SIZE == 64 */
2423 
2424 static Elf_Auxinfo *
2425 procstat_getauxv_sysctl(pid_t pid, unsigned int *cntp)
2426 {
2427 	Elf_Auxinfo *auxv;
2428 	int name[4];
2429 	size_t len;
2430 
2431 #if __ELF_WORD_SIZE == 64
2432 	if (is_elf32_sysctl(pid))
2433 		return (procstat_getauxv32_sysctl(pid, cntp));
2434 #endif
2435 	name[0] = CTL_KERN;
2436 	name[1] = KERN_PROC;
2437 	name[2] = KERN_PROC_AUXV;
2438 	name[3] = pid;
2439 	len = PROC_AUXV_MAX * sizeof(Elf_Auxinfo);
2440 	auxv = malloc(len);
2441 	if (auxv == NULL) {
2442 		warn("malloc(%zu)", len);
2443 		return (NULL);
2444 	}
2445 	if (sysctl(name, nitems(name), auxv, &len, NULL, 0) == -1) {
2446 		if (errno != ESRCH && errno != EPERM)
2447 			warn("sysctl: kern.proc.auxv: %d: %d", pid, errno);
2448 		free(auxv);
2449 		return (NULL);
2450 	}
2451 	*cntp = len / sizeof(Elf_Auxinfo);
2452 	return (auxv);
2453 }
2454 
2455 static Elf_Auxinfo *
2456 procstat_getauxv_core(struct procstat_core *core, unsigned int *cntp)
2457 {
2458 	Elf_Auxinfo *auxv;
2459 	size_t len;
2460 
2461 	auxv = procstat_core_get(core, PSC_TYPE_AUXV, NULL, &len);
2462 	if (auxv == NULL)
2463 		return (NULL);
2464 	*cntp = len / sizeof(Elf_Auxinfo);
2465 	return (auxv);
2466 }
2467 
2468 Elf_Auxinfo *
2469 procstat_getauxv(struct procstat *procstat, struct kinfo_proc *kp,
2470     unsigned int *cntp)
2471 {
2472 	switch(procstat->type) {
2473 	case PROCSTAT_KVM:
2474 		warnx("kvm method is not supported");
2475 		return (NULL);
2476 	case PROCSTAT_SYSCTL:
2477 		return (procstat_getauxv_sysctl(kp->ki_pid, cntp));
2478 	case PROCSTAT_CORE:
2479 		return (procstat_getauxv_core(procstat->core, cntp));
2480 	default:
2481 		warnx("unknown access method: %d", procstat->type);
2482 		return (NULL);
2483 	}
2484 }
2485 
2486 void
2487 procstat_freeauxv(struct procstat *procstat __unused, Elf_Auxinfo *auxv)
2488 {
2489 
2490 	free(auxv);
2491 }
2492 
2493 static struct ptrace_lwpinfo *
2494 procstat_getptlwpinfo_core(struct procstat_core *core, unsigned int *cntp)
2495 {
2496 	void *buf;
2497 	struct ptrace_lwpinfo *pl;
2498 	unsigned int cnt;
2499 	size_t len;
2500 
2501 	cnt = procstat_core_note_count(core, PSC_TYPE_PTLWPINFO);
2502 	if (cnt == 0)
2503 		return (NULL);
2504 
2505 	len = cnt * sizeof(*pl);
2506 	buf = calloc(1, len);
2507 	pl = procstat_core_get(core, PSC_TYPE_PTLWPINFO, buf, &len);
2508 	if (pl == NULL) {
2509 		free(buf);
2510 		return (NULL);
2511 	}
2512 	*cntp = len / sizeof(*pl);
2513 	return (pl);
2514 }
2515 
2516 struct ptrace_lwpinfo *
2517 procstat_getptlwpinfo(struct procstat *procstat, unsigned int *cntp)
2518 {
2519 	switch (procstat->type) {
2520 	case PROCSTAT_KVM:
2521 		warnx("kvm method is not supported");
2522 		return (NULL);
2523 	case PROCSTAT_SYSCTL:
2524 		warnx("sysctl method is not supported");
2525 		return (NULL);
2526 	case PROCSTAT_CORE:
2527 	 	return (procstat_getptlwpinfo_core(procstat->core, cntp));
2528 	default:
2529 		warnx("unknown access method: %d", procstat->type);
2530 		return (NULL);
2531 	}
2532 }
2533 
2534 void
2535 procstat_freeptlwpinfo(struct procstat *procstat __unused,
2536     struct ptrace_lwpinfo *pl)
2537 {
2538 	free(pl);
2539 }
2540 
2541 static struct kinfo_kstack *
2542 procstat_getkstack_sysctl(pid_t pid, int *cntp)
2543 {
2544 	struct kinfo_kstack *kkstp;
2545 	int error, name[4];
2546 	size_t len;
2547 
2548 	name[0] = CTL_KERN;
2549 	name[1] = KERN_PROC;
2550 	name[2] = KERN_PROC_KSTACK;
2551 	name[3] = pid;
2552 
2553 	len = 0;
2554 	error = sysctl(name, nitems(name), NULL, &len, NULL, 0);
2555 	if (error < 0 && errno != ESRCH && errno != EPERM && errno != ENOENT) {
2556 		warn("sysctl: kern.proc.kstack: %d", pid);
2557 		return (NULL);
2558 	}
2559 	if (error == -1 && errno == ENOENT) {
2560 		warnx("sysctl: kern.proc.kstack unavailable"
2561 		    " (options DDB or options STACK required in kernel)");
2562 		return (NULL);
2563 	}
2564 	if (error == -1)
2565 		return (NULL);
2566 	kkstp = malloc(len);
2567 	if (kkstp == NULL) {
2568 		warn("malloc(%zu)", len);
2569 		return (NULL);
2570 	}
2571 	if (sysctl(name, nitems(name), kkstp, &len, NULL, 0) == -1) {
2572 		warn("sysctl: kern.proc.pid: %d", pid);
2573 		free(kkstp);
2574 		return (NULL);
2575 	}
2576 	*cntp = len / sizeof(*kkstp);
2577 
2578 	return (kkstp);
2579 }
2580 
2581 struct kinfo_kstack *
2582 procstat_getkstack(struct procstat *procstat, struct kinfo_proc *kp,
2583     unsigned int *cntp)
2584 {
2585 	switch(procstat->type) {
2586 	case PROCSTAT_KVM:
2587 		warnx("kvm method is not supported");
2588 		return (NULL);
2589 	case PROCSTAT_SYSCTL:
2590 		return (procstat_getkstack_sysctl(kp->ki_pid, cntp));
2591 	case PROCSTAT_CORE:
2592 		warnx("core method is not supported");
2593 		return (NULL);
2594 	default:
2595 		warnx("unknown access method: %d", procstat->type);
2596 		return (NULL);
2597 	}
2598 }
2599 
2600 void
2601 procstat_freekstack(struct procstat *procstat __unused,
2602     struct kinfo_kstack *kkstp)
2603 {
2604 
2605 	free(kkstp);
2606 }
2607