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