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