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