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