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