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