Merge from vendor branch LIBARCHIVE:
[games.git] / lib / libkvm / kvm_proc.c
1 /*-
2  * Copyright (c) 1989, 1992, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software developed by the Computer Systems
6  * Engineering group at Lawrence Berkeley Laboratory under DARPA contract
7  * BG 91-66 and contributed to Berkeley.
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  * $FreeBSD: src/lib/libkvm/kvm_proc.c,v 1.25.2.3 2002/08/24 07:27:46 kris Exp $
38  * $DragonFly: src/lib/libkvm/kvm_proc.c,v 1.12 2007/02/18 16:15:23 corecode Exp $
39  *
40  * @(#)kvm_proc.c       8.3 (Berkeley) 9/23/93
41  */
42
43 /*
44  * Proc traversal interface for kvm.  ps and w are (probably) the exclusive
45  * users of this code, so we've factored it out into a separate module.
46  * Thus, we keep this grunge out of the other kvm applications (i.e.,
47  * most other applications are interested only in open/close/read/nlist).
48  */
49
50 #include <sys/user.h>
51 #include <sys/conf.h>
52 #include <sys/param.h>
53 #include <sys/proc.h>
54 #include <sys/exec.h>
55 #include <sys/stat.h>
56 #include <sys/ioctl.h>
57 #include <sys/tty.h>
58 #include <sys/file.h>
59 #include <sys/jail.h>
60 #include <stdio.h>
61 #include <stdlib.h>
62 #include <unistd.h>
63 #include <nlist.h>
64 #include <kvm.h>
65
66 #include <vm/vm.h>
67 #include <vm/vm_param.h>
68 #include <vm/swap_pager.h>
69
70 #include <sys/sysctl.h>
71
72 #include <limits.h>
73 #include <memory.h>
74 #include <paths.h>
75
76 #include "kvm_private.h"
77
78 #if used
79 static char *
80 kvm_readswap(kvm_t *kd, const struct proc *p, u_long va, u_long *cnt)
81 {
82 #if defined(__FreeBSD__) || defined(__DragonFly__)
83         /* XXX Stubbed out, our vm system is differnet */
84         _kvm_err(kd, kd->program, "kvm_readswap not implemented");
85         return(0);
86 #endif
87 }
88 #endif
89
90 #define KREAD(kd, addr, obj) \
91         (kvm_read(kd, addr, (char *)(obj), sizeof(*obj)) != sizeof(*obj))
92
93
94 static struct kinfo_proc *
95 kinfo_resize_proc(kvm_t *kd, struct kinfo_proc *bp)
96 {
97         if (bp < kd->procend)
98                 return bp;
99
100         size_t pos = bp - kd->procend;
101         size_t size = kd->procend - kd->procbase;
102
103         if (size == 0)
104                 size = 8;
105         else
106                 size *= 2;
107         kd->procbase = _kvm_realloc(kd, kd->procbase, sizeof(*bp) * size);
108         if (kd->procbase == NULL)
109                 return NULL;
110         kd->procend = kd->procbase + size;
111         bp = kd->procbase + pos;
112         return bp;
113 }
114
115 /*
116  * Read proc's from memory file into buffer bp, which has space to hold
117  * at most maxcnt procs.
118  */
119 static int
120 kvm_proclist(kvm_t *kd, int what, int arg, struct proc *p,
121              struct kinfo_proc *bp)
122 {
123         struct pgrp pgrp;
124         struct pgrp tpgrp;
125         struct session sess;
126         struct tty tty;
127         struct proc proc;
128         struct ucred ucred;
129         struct thread thread;
130         struct proc pproc;
131         struct cdev cdev;
132         struct vmspace vmspace;
133         struct prison prison;
134         struct lwp lwp;
135         uintptr_t lwppos;
136
137         for (; p != NULL; p = proc.p_list.le_next) {
138                 if (KREAD(kd, (u_long)p, &proc)) {
139                         _kvm_err(kd, kd->program, "can't read proc at %x", p);
140                         return (-1);
141                 }
142                 if (KREAD(kd, (u_long)proc.p_ucred, &ucred)) {
143                         _kvm_err(kd, kd->program, "can't read ucred at %p",
144                                  proc.p_ucred);
145                         return (-1);
146                 }
147                 proc.p_ucred = &ucred;
148
149                 switch(what & ~KERN_PROC_FLAGMASK) {
150
151                 case KERN_PROC_PID:
152                         if (proc.p_pid != (pid_t)arg)
153                                 continue;
154                         break;
155
156                 case KERN_PROC_UID:
157                         if (ucred.cr_uid != (uid_t)arg)
158                                 continue;
159                         break;
160
161                 case KERN_PROC_RUID:
162                         if (ucred.cr_ruid != (uid_t)arg)
163                                 continue;
164                         break;
165                 }
166
167                 if (KREAD(kd, (u_long)proc.p_pgrp, &pgrp)) {
168                         _kvm_err(kd, kd->program, "can't read pgrp at %x",
169                                  proc.p_pgrp);
170                         return (-1);
171                 }
172                 proc.p_pgrp = &pgrp;
173                 if (proc.p_pptr) {
174                   if (KREAD(kd, (u_long)proc.p_pptr, &pproc)) {
175                         _kvm_err(kd, kd->program, "can't read pproc at %x",
176                                  proc.p_pptr);
177                         return (-1);
178                   }
179                   proc.p_pptr = &pproc;
180                 }
181                 if (KREAD(kd, (u_long)pgrp.pg_session, &sess)) {
182                         _kvm_err(kd, kd->program, "can't read session at %x",
183                                 pgrp.pg_session);
184                         return (-1);
185                 }
186                 pgrp.pg_session = &sess;
187
188                 if ((proc.p_flag & P_CONTROLT) && sess.s_ttyp != NULL) {
189                         if (KREAD(kd, (u_long)sess.s_ttyp, &tty)) {
190                                 _kvm_err(kd, kd->program,
191                                          "can't read tty at %x", sess.s_ttyp);
192                                 return (-1);
193                         }
194                         sess.s_ttyp = &tty;
195                         if (tty.t_dev && tty.t_dev != NOCDEV) {
196                                 if (KREAD(kd, (u_long)tty.t_dev, &cdev))
197                                         tty.t_dev = NOCDEV;
198                                 else
199                                         tty.t_dev = &cdev;
200                         }
201                         if (tty.t_pgrp != NULL) {
202                                 if (KREAD(kd, (u_long)tty.t_pgrp, &tpgrp)) {
203                                         _kvm_err(kd, kd->program,
204                                                  "can't read tpgrp at %x",
205                                                 tty.t_pgrp);
206                                         return (-1);
207                                 }
208                                 tty.t_pgrp = &tpgrp;
209                         }
210                 }
211
212                 if (KREAD(kd, (u_long)proc.p_vmspace, &vmspace)) {
213                         _kvm_err(kd, kd->program, "can't read vmspace at %p",
214                                  proc.p_vmspace);
215                         return (-1);
216                 }
217                 proc.p_vmspace = &vmspace;
218
219                 if (ucred.cr_prison != NULL) {
220                         if (KREAD(kd, (u_long)ucred.cr_prison, &prison)) {
221                                 _kvm_err(kd, kd->program, "can't read prison at %p",
222                                          ucred.cr_prison);
223                                 return (-1);
224                         }
225                         ucred.cr_prison = &prison;
226                 }
227
228                 switch (what & ~KERN_PROC_FLAGMASK) {
229
230                 case KERN_PROC_PGRP:
231                         if (proc.p_pgrp->pg_id != (pid_t)arg)
232                                 continue;
233                         break;
234
235                 case KERN_PROC_TTY:
236                         if ((proc.p_flag & P_CONTROLT) == 0 ||
237                             proc.p_pgrp->pg_session->s_ttyp->t_dev->si_udev
238                                         != (dev_t)arg)
239                                 continue;
240                         break;
241                 }
242
243                 if ((bp = kinfo_resize_proc(kd, bp)) == NULL)
244                         return (-1);
245                 fill_kinfo_proc(&proc, bp);
246                 bp->kp_paddr = (uintptr_t)p;
247
248                 lwppos = (uintptr_t)proc.p_lwps.lh_first;
249                 if (lwppos == 0)
250                         bp++;           /* Just export the proc then */
251                 while (lwppos != 0) {
252                         if (KREAD(kd, lwppos, &lwp)) {
253                                 _kvm_err(kd, kd->program, "can't read lwp at %p",
254                                     lwppos);
255                                 return (-1);
256                         }
257                         if (p != lwp.lwp_proc) {
258                                 _kvm_err(kd, kd->program, "lwp has wrong parent");
259                                 return (-1);
260                         }
261                         lwp.lwp_proc = &proc;
262                         if (KREAD(kd, (u_long)lwp.lwp_thread, &thread)) {
263                                 _kvm_err(kd, kd->program, "can't read thread at %x",
264                                     lwp.lwp_thread);
265                                 return (-1);
266                         }
267                         lwp.lwp_thread = &thread;
268
269                         if ((bp = kinfo_resize_proc(kd, bp)) == NULL)
270                                 return (-1);
271                         fill_kinfo_proc(&proc, bp);
272                         fill_kinfo_lwp(&lwp, &bp->kp_lwp);
273                         bp->kp_paddr = (uintptr_t)p;
274                         bp++;
275                         if ((what & KERN_PROC_FLAG_LWP) == 0)
276                                 break;
277
278                         lwppos = (uintptr_t)lwp.lwp_list.le_next;
279                 }
280         }
281         return (0);
282 }
283
284 /*
285  * Build proc info array by reading in proc list from a crash dump.
286  * We reallocate kd->procbase as necessary.
287  */
288 static int
289 kvm_deadprocs(kvm_t *kd, int what, int arg, u_long a_allproc,
290               u_long a_zombproc)
291 {
292         struct kinfo_proc *bp = kd->procbase;
293         int acnt, zcnt;
294         struct proc *p;
295
296         if (KREAD(kd, a_allproc, &p)) {
297                 _kvm_err(kd, kd->program, "cannot read allproc");
298                 return (-1);
299         }
300         acnt = kvm_proclist(kd, what, arg, p, bp);
301         if (acnt < 0)
302                 return (acnt);
303
304         if (KREAD(kd, a_zombproc, &p)) {
305                 _kvm_err(kd, kd->program, "cannot read zombproc");
306                 return (-1);
307         }
308         zcnt = kvm_proclist(kd, what, arg, p, bp + acnt);
309         if (zcnt < 0)
310                 zcnt = 0;
311
312         return (acnt + zcnt);
313 }
314
315 struct kinfo_proc *
316 kvm_getprocs(kvm_t *kd, int op, int arg, int *cnt)
317 {
318         int mib[4], st, nprocs;
319         size_t size;
320
321         if (kd->procbase != 0) {
322                 free((void *)kd->procbase);
323                 /*
324                  * Clear this pointer in case this call fails.  Otherwise,
325                  * kvm_close() will free it again.
326                  */
327                 kd->procbase = 0;
328         }
329         if (ISALIVE(kd)) {
330                 size = 0;
331                 mib[0] = CTL_KERN;
332                 mib[1] = KERN_PROC;
333                 mib[2] = op;
334                 mib[3] = arg;
335                 st = sysctl(mib, op == KERN_PROC_ALL ? 3 : 4, NULL, &size, NULL, 0);
336                 if (st == -1) {
337                         _kvm_syserr(kd, kd->program, "kvm_getprocs");
338                         return (0);
339                 }
340                 do {
341                         size += size / 10;
342                         kd->procbase = (struct kinfo_proc *)
343                             _kvm_realloc(kd, kd->procbase, size);
344                         if (kd->procbase == 0)
345                                 return (0);
346                         st = sysctl(mib, op == KERN_PROC_ALL ? 3 : 4,
347                             kd->procbase, &size, NULL, 0);
348                 } while (st == -1 && errno == ENOMEM);
349                 if (st == -1) {
350                         _kvm_syserr(kd, kd->program, "kvm_getprocs");
351                         return (0);
352                 }
353                 if (size % sizeof(struct kinfo_proc) != 0) {
354                         _kvm_err(kd, kd->program,
355                                 "proc size mismatch (%d total, %d chunks)",
356                                 size, sizeof(struct kinfo_proc));
357                         return (0);
358                 }
359                 nprocs = size / sizeof(struct kinfo_proc);
360         } else {
361                 struct nlist nl[4], *p;
362
363                 nl[0].n_name = "_nprocs";
364                 nl[1].n_name = "_allproc";
365                 nl[2].n_name = "_zombproc";
366                 nl[3].n_name = 0;
367
368                 if (kvm_nlist(kd, nl) != 0) {
369                         for (p = nl; p->n_type != 0; ++p)
370                                 ;
371                         _kvm_err(kd, kd->program,
372                                  "%s: no such symbol", p->n_name);
373                         return (0);
374                 }
375                 if (KREAD(kd, nl[0].n_value, &nprocs)) {
376                         _kvm_err(kd, kd->program, "can't read nprocs");
377                         return (0);
378                 }
379                 nprocs = kvm_deadprocs(kd, op, arg, nl[1].n_value,
380                                       nl[2].n_value);
381 #ifdef notdef
382                 size = nprocs * sizeof(struct kinfo_proc);
383                 (void)realloc(kd->procbase, size);
384 #endif
385         }
386         *cnt = nprocs;
387         return (kd->procbase);
388 }
389
390 void
391 _kvm_freeprocs(kvm_t *kd)
392 {
393         if (kd->procbase) {
394                 free(kd->procbase);
395                 kd->procbase = 0;
396         }
397 }
398
399 void *
400 _kvm_realloc(kvm_t *kd, void *p, size_t n)
401 {
402         void *np = (void *)realloc(p, n);
403
404         if (np == 0) {
405                 free(p);
406                 _kvm_err(kd, kd->program, "out of memory");
407         }
408         return (np);
409 }
410
411 #ifndef MAX
412 #define MAX(a, b) ((a) > (b) ? (a) : (b))
413 #endif
414
415 /*
416  * Read in an argument vector from the user address space of process pid.
417  * addr if the user-space base address of narg null-terminated contiguous
418  * strings.  This is used to read in both the command arguments and
419  * environment strings.  Read at most maxcnt characters of strings.
420  */
421 static char **
422 kvm_argv(kvm_t *kd, pid_t pid, u_long addr, int narg, int maxcnt)
423 {
424         char *np, *cp, *ep, *ap;
425         u_long oaddr = -1;
426         int len, cc;
427         char **argv;
428
429         /*
430          * Check that there aren't an unreasonable number of agruments,
431          * and that the address is in user space.
432          */
433         if (narg > 512 || 
434             addr < VM_MIN_USER_ADDRESS || addr >= VM_MAX_USER_ADDRESS) {
435                 return (0);
436         }
437
438         /*
439          * kd->argv : work space for fetching the strings from the target 
440          *            process's space, and is converted for returning to caller
441          */
442         if (kd->argv == 0) {
443                 /*
444                  * Try to avoid reallocs.
445                  */
446                 kd->argc = MAX(narg + 1, 32);
447                 kd->argv = (char **)_kvm_malloc(kd, kd->argc *
448                                                 sizeof(*kd->argv));
449                 if (kd->argv == 0)
450                         return (0);
451         } else if (narg + 1 > kd->argc) {
452                 kd->argc = MAX(2 * kd->argc, narg + 1);
453                 kd->argv = (char **)_kvm_realloc(kd, kd->argv, kd->argc *
454                                                 sizeof(*kd->argv));
455                 if (kd->argv == 0)
456                         return (0);
457         }
458         /*
459          * kd->argspc : returned to user, this is where the kd->argv
460          *              arrays are left pointing to the collected strings.
461          */
462         if (kd->argspc == 0) {
463                 kd->argspc = (char *)_kvm_malloc(kd, PAGE_SIZE);
464                 if (kd->argspc == 0)
465                         return (0);
466                 kd->arglen = PAGE_SIZE;
467         }
468         /*
469          * kd->argbuf : used to pull in pages from the target process.
470          *              the strings are copied out of here.
471          */
472         if (kd->argbuf == 0) {
473                 kd->argbuf = (char *)_kvm_malloc(kd, PAGE_SIZE);
474                 if (kd->argbuf == 0)
475                         return (0);
476         }
477
478         /* Pull in the target process'es argv vector */
479         cc = sizeof(char *) * narg;
480         if (kvm_uread(kd, pid, addr, (char *)kd->argv, cc) != cc)
481                 return (0);
482         /*
483          * ap : saved start address of string we're working on in kd->argspc
484          * np : pointer to next place to write in kd->argspc
485          * len: length of data in kd->argspc
486          * argv: pointer to the argv vector that we are hunting around the
487          *       target process space for, and converting to addresses in
488          *       our address space (kd->argspc).
489          */
490         ap = np = kd->argspc;
491         argv = kd->argv;
492         len = 0;
493         /*
494          * Loop over pages, filling in the argument vector.
495          * Note that the argv strings could be pointing *anywhere* in
496          * the user address space and are no longer contiguous.
497          * Note that *argv is modified when we are going to fetch a string
498          * that crosses a page boundary.  We copy the next part of the string
499          * into to "np" and eventually convert the pointer.
500          */
501         while (argv < kd->argv + narg && *argv != 0) {
502
503                 /* get the address that the current argv string is on */
504                 addr = (u_long)*argv & ~(PAGE_SIZE - 1);
505
506                 /* is it the same page as the last one? */
507                 if (addr != oaddr) {
508                         if (kvm_uread(kd, pid, addr, kd->argbuf, PAGE_SIZE) !=
509                             PAGE_SIZE)
510                                 return (0);
511                         oaddr = addr;
512                 }
513
514                 /* offset within the page... kd->argbuf */
515                 addr = (u_long)*argv & (PAGE_SIZE - 1);
516
517                 /* cp = start of string, cc = count of chars in this chunk */
518                 cp = kd->argbuf + addr;
519                 cc = PAGE_SIZE - addr;
520
521                 /* dont get more than asked for by user process */
522                 if (maxcnt > 0 && cc > maxcnt - len)
523                         cc = maxcnt - len;
524
525                 /* pointer to end of string if we found it in this page */
526                 ep = memchr(cp, '\0', cc);
527                 if (ep != 0)
528                         cc = ep - cp + 1;
529                 /*
530                  * at this point, cc is the count of the chars that we are
531                  * going to retrieve this time. we may or may not have found
532                  * the end of it.  (ep points to the null if the end is known)
533                  */
534
535                 /* will we exceed the malloc/realloced buffer? */
536                 if (len + cc > kd->arglen) {
537                         int off;
538                         char **pp;
539                         char *op = kd->argspc;
540
541                         kd->arglen *= 2;
542                         kd->argspc = (char *)_kvm_realloc(kd, kd->argspc,
543                                                           kd->arglen);
544                         if (kd->argspc == 0)
545                                 return (0);
546                         /*
547                          * Adjust argv pointers in case realloc moved
548                          * the string space.
549                          */
550                         off = kd->argspc - op;
551                         for (pp = kd->argv; pp < argv; pp++)
552                                 *pp += off;
553                         ap += off;
554                         np += off;
555                 }
556                 /* np = where to put the next part of the string in kd->argspc*/
557                 /* np is kinda redundant.. could use "kd->argspc + len" */
558                 memcpy(np, cp, cc);
559                 np += cc;       /* inc counters */
560                 len += cc;
561
562                 /*
563                  * if end of string found, set the *argv pointer to the
564                  * saved beginning of string, and advance. argv points to
565                  * somewhere in kd->argv..  This is initially relative
566                  * to the target process, but when we close it off, we set
567                  * it to point in our address space.
568                  */
569                 if (ep != 0) {
570                         *argv++ = ap;
571                         ap = np;
572                 } else {
573                         /* update the address relative to the target process */
574                         *argv += cc;
575                 }
576
577                 if (maxcnt > 0 && len >= maxcnt) {
578                         /*
579                          * We're stopping prematurely.  Terminate the
580                          * current string.
581                          */
582                         if (ep == 0) {
583                                 *np = '\0';
584                                 *argv++ = ap;
585                         }
586                         break;
587                 }
588         }
589         /* Make sure argv is terminated. */
590         *argv = 0;
591         return (kd->argv);
592 }
593
594 static void
595 ps_str_a(struct ps_strings *p, u_long *addr, int *n)
596 {
597         *addr = (u_long)p->ps_argvstr;
598         *n = p->ps_nargvstr;
599 }
600
601 static void
602 ps_str_e(struct ps_strings *p, u_long *addr, int *n)
603 {
604         *addr = (u_long)p->ps_envstr;
605         *n = p->ps_nenvstr;
606 }
607
608 /*
609  * Determine if the proc indicated by p is still active.
610  * This test is not 100% foolproof in theory, but chances of
611  * being wrong are very low.
612  */
613 static int
614 proc_verify(kvm_t *kd, const struct kinfo_proc *p)
615 {
616         struct kinfo_proc kp;
617         int mib[4];
618         size_t len;
619         int error;
620
621         mib[0] = CTL_KERN;
622         mib[1] = KERN_PROC;
623         mib[2] = KERN_PROC_PID;
624         mib[3] = p->kp_pid;
625
626         len = sizeof(kp);
627         error = sysctl(mib, 4, &kp, &len, NULL, 0);
628         if (error)
629                 return (0);
630
631         error = (p->kp_pid == kp.kp_pid &&
632             (kp.kp_stat != SZOMB || p->kp_stat == SZOMB));
633         return (error);
634 }
635
636 static char **
637 kvm_doargv(kvm_t *kd, const struct kinfo_proc *kp, int nchr,
638            void (*info)(struct ps_strings *, u_long *, int *))
639 {
640         char **ap;
641         u_long addr;
642         int cnt;
643         static struct ps_strings arginfo;
644         static u_long ps_strings;
645         size_t len;
646
647         if (ps_strings == NULL) {
648                 len = sizeof(ps_strings);
649                 if (sysctlbyname("kern.ps_strings", &ps_strings, &len, NULL,
650                     0) == -1)
651                         ps_strings = PS_STRINGS;
652         }
653
654         /*
655          * Pointers are stored at the top of the user stack.
656          */
657         if (kp->kp_stat == SZOMB ||
658             kvm_uread(kd, kp->kp_pid, ps_strings, (char *)&arginfo,
659                       sizeof(arginfo)) != sizeof(arginfo))
660                 return (0);
661
662         (*info)(&arginfo, &addr, &cnt);
663         if (cnt == 0)
664                 return (0);
665         ap = kvm_argv(kd, kp->kp_pid, addr, cnt, nchr);
666         /*
667          * For live kernels, make sure this process didn't go away.
668          */
669         if (ap != 0 && ISALIVE(kd) &&
670             !proc_verify(kd, kp))
671                 ap = 0;
672         return (ap);
673 }
674
675 /*
676  * Get the command args.  This code is now machine independent.
677  */
678 char **
679 kvm_getargv(kvm_t *kd, const struct kinfo_proc *kp, int nchr)
680 {
681         int oid[4];
682         int i;
683         size_t bufsz;
684         static unsigned long buflen;
685         static char *buf, *p;
686         static char **bufp;
687         static int argc;
688
689         if (!ISALIVE(kd)) {
690                 _kvm_err(kd, kd->program,
691                     "cannot read user space from dead kernel");
692                 return (0);
693         }
694
695         if (!buflen) {
696                 bufsz = sizeof(buflen);
697                 i = sysctlbyname("kern.ps_arg_cache_limit", 
698                     &buflen, &bufsz, NULL, 0);
699                 if (i == -1) {
700                         buflen = 0;
701                 } else {
702                         buf = malloc(buflen);
703                         if (buf == NULL)
704                                 buflen = 0;
705                         argc = 32;
706                         bufp = malloc(sizeof(char *) * argc);
707                 }
708         }
709         if (buf != NULL) {
710                 oid[0] = CTL_KERN;
711                 oid[1] = KERN_PROC;
712                 oid[2] = KERN_PROC_ARGS;
713                 oid[3] = kp->kp_pid;
714                 bufsz = buflen;
715                 i = sysctl(oid, 4, buf, &bufsz, 0, 0);
716                 if (i == 0 && bufsz > 0) {
717                         i = 0;
718                         p = buf;
719                         do {
720                                 bufp[i++] = p;
721                                 p += strlen(p) + 1;
722                                 if (i >= argc) {
723                                         argc += argc;
724                                         bufp = realloc(bufp,
725                                             sizeof(char *) * argc);
726                                 }
727                         } while (p < buf + bufsz);
728                         bufp[i++] = 0;
729                         return (bufp);
730                 }
731         }
732         if (kp->kp_flags & P_SYSTEM)
733                 return (NULL);
734         return (kvm_doargv(kd, kp, nchr, ps_str_a));
735 }
736
737 char **
738 kvm_getenvv(kvm_t *kd, const struct kinfo_proc *kp, int nchr)
739 {
740         return (kvm_doargv(kd, kp, nchr, ps_str_e));
741 }
742
743 /*
744  * Read from user space.  The user context is given by pid.
745  */
746 ssize_t
747 kvm_uread(kvm_t *kd, pid_t pid, u_long uva, char *buf, size_t len)
748 {
749         char *cp;
750         char procfile[MAXPATHLEN];
751         ssize_t amount;
752         int fd;
753
754         if (!ISALIVE(kd)) {
755                 _kvm_err(kd, kd->program,
756                     "cannot read user space from dead kernel");
757                 return (0);
758         }
759
760         sprintf(procfile, "/proc/%d/mem", pid);
761         fd = open(procfile, O_RDONLY, 0);
762         if (fd < 0) {
763                 _kvm_err(kd, kd->program, "cannot open %s", procfile);
764                 close(fd);
765                 return (0);
766         }
767
768         cp = buf;
769         while (len > 0) {
770                 errno = 0;
771                 if (lseek(fd, (off_t)uva, 0) == -1 && errno != 0) {
772                         _kvm_err(kd, kd->program, "invalid address (%x) in %s",
773                             uva, procfile);
774                         break;
775                 }
776                 amount = read(fd, cp, len);
777                 if (amount < 0) {
778                         _kvm_syserr(kd, kd->program, "error reading %s",
779                             procfile);
780                         break;
781                 }
782                 if (amount == 0) {
783                         _kvm_err(kd, kd->program, "EOF reading %s", procfile);
784                         break;
785                 }
786                 cp += amount;
787                 uva += amount;
788                 len -= amount;
789         }
790
791         close(fd);
792         return ((ssize_t)(cp - buf));
793 }