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