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