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