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