Updated shlib version number to 1.0
[unix-history] / lib / libutil / kvm.c
CommitLineData
15637ed4
RG
1/*-
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
15637ed4
RG
33 */
34
35#if defined(LIBC_SCCS) && !defined(lint)
36static char sccsid[] = "@(#)kvm.c 5.18 (Berkeley) 5/7/91";
37#endif /* LIBC_SCCS and not lint */
38
8387d405
DG
39#define DEBUG 0
40#define PROCFS 1
15637ed4
RG
41
42#include <sys/param.h>
43#include <sys/user.h>
44#include <sys/proc.h>
45#include <sys/ioctl.h>
46#include <sys/kinfo.h>
47#include <sys/tty.h>
8387d405
DG
48#include <sys/file.h>
49#include <sys/types.h>
15637ed4
RG
50#include <machine/vmparam.h>
51#include <fcntl.h>
52#include <nlist.h>
53#include <kvm.h>
54#include <ndbm.h>
55#include <limits.h>
56#include <paths.h>
57#include <stdio.h>
58#include <string.h>
8387d405 59#include <sys/mman.h>
15637ed4 60
15637ed4
RG
61#define btop(x) (((unsigned)(x)) >> PGSHIFT) /* XXX */
62#define ptob(x) ((caddr_t)((x) << PGSHIFT)) /* XXX */
63#include <vm/vm.h> /* ??? kinfo_proc currently includes this*/
64#include <vm/vm_page.h>
65#include <vm/swap_pager.h>
66#include <sys/kinfo_proc.h>
15637ed4
RG
67
68/*
69 * files
70 */
71static const char *unixf, *memf, *kmemf, *swapf;
72static int unixx, mem, kmem, swap;
73static DBM *db;
74/*
75 * flags
76 */
77static int deadkernel;
78static int kvminit = 0;
79static int kvmfilesopen = 0;
80/*
81 * state
82 */
83static struct kinfo_proc *kvmprocbase, *kvmprocptr;
84static int kvmnprocs;
85/*
86 * u. buffer
87 */
88static union {
89 struct user user;
90 char upages[UPAGES][NBPG];
91} user;
92
15637ed4
RG
93struct swapblk {
94 long offset; /* offset in swap device */
95 long size; /* remaining size of block in swap device */
96};
15637ed4
RG
97/*
98 * random other stuff
99 */
15637ed4
RG
100static int dmmin, dmmax;
101static int pcbpf;
102static int argaddr0; /* XXX */
103static int argaddr1;
104static int swaddr;
105static int nswap;
106static char *tmp;
15637ed4 107static struct pde *PTD;
15637ed4
RG
108
109#define basename(cp) ((tmp=rindex((cp), '/')) ? tmp+1 : (cp))
110#define MAXSYMSIZE 256
111
15637ed4
RG
112#ifndef pftoc
113#define pftoc(f) (f)
114#endif
115#ifndef iskva
116#define iskva(v) ((u_long)(v) & KERNBASE)
117#endif
118
119static struct nlist nl[] = {
120 { "_Usrptmap" },
121#define X_USRPTMAP 0
122 { "_usrpt" },
123#define X_USRPT 1
124 { "_nswap" },
125#define X_NSWAP 2
126 { "_dmmin" },
127#define X_DMMIN 3
128 { "_dmmax" },
129#define X_DMMAX 4
130 { "_vm_page_buckets" },
131#define X_VM_PAGE_BUCKETS 5
132 { "_vm_page_hash_mask" },
133#define X_VM_PAGE_HASH_MASK 6
134 { "_page_shift" },
135#define X_PAGE_SHIFT 7
8387d405
DG
136 { "_kstack" },
137#define X_KSTACK 8
138 { "_kernel_object" },
139#define X_KERNEL_OBJECT 9
140 { "_btext",},
141#define X_KERNEL_BTEXT 10
15637ed4
RG
142 /*
143 * everything here and down, only if a dead kernel
144 */
145 { "_Sysmap" },
8387d405 146#define X_SYSMAP 11
15637ed4
RG
147#define X_DEADKERNEL X_SYSMAP
148 { "_Syssize" },
8387d405 149#define X_SYSSIZE 12
15637ed4 150 { "_allproc" },
8387d405 151#define X_ALLPROC 13
15637ed4 152 { "_zombproc" },
8387d405 153#define X_ZOMBPROC 14
15637ed4 154 { "_nproc" },
8387d405
DG
155#define X_NPROC 15
156#define X_LAST 15
15637ed4
RG
157 { "_IdlePTD" },
158#define X_IdlePTD (X_LAST+1)
15637ed4
RG
159 { "" },
160};
161
c6500831 162static void seterr(), setsyserr(), vstodb();
15637ed4 163static int getkvars(), kvm_doprocs(), kvm_init();
15637ed4
RG
164
165/*
166 * returns 0 if files were opened now,
167 * 1 if files were already opened,
168 * -1 if files could not be opened.
169 */
170kvm_openfiles(uf, mf, sf)
171 const char *uf, *mf, *sf;
172{
173 if (kvmfilesopen)
174 return (1);
175 unixx = mem = kmem = swap = -1;
176 unixf = (uf == NULL) ? _PATH_UNIX : uf;
177 memf = (mf == NULL) ? _PATH_MEM : mf;
178
179 if ((unixx = open(unixf, O_RDONLY, 0)) == -1) {
180 setsyserr("can't open %s", unixf);
181 goto failed;
182 }
183 if ((mem = open(memf, O_RDONLY, 0)) == -1) {
184 setsyserr("can't open %s", memf);
185 goto failed;
186 }
187 if (sf != NULL)
188 swapf = sf;
189 if (mf != NULL) {
190 deadkernel++;
191 kmemf = mf;
192 kmem = mem;
193 swap = -1;
194 } else {
195 kmemf = _PATH_KMEM;
196 if ((kmem = open(kmemf, O_RDONLY, 0)) == -1) {
197 setsyserr("can't open %s", kmemf);
198 goto failed;
199 }
200 swapf = (sf == NULL) ? _PATH_DRUM : sf;
201 /*
202 * live kernel - avoid looking up nlist entries
203 * past X_DEADKERNEL.
204 */
205 nl[X_DEADKERNEL].n_name = "";
206 }
207 if (swapf != NULL && ((swap = open(swapf, O_RDONLY, 0)) == -1)) {
208 seterr("can't open %s", swapf);
209 goto failed;
210 }
211 kvmfilesopen++;
212 if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1) /*XXX*/
213 return (-1);
214 return (0);
215failed:
216 kvm_close();
217 return (-1);
218}
219
220static
221kvm_init(uf, mf, sf)
222 char *uf, *mf, *sf;
223{
224 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
225 return (-1);
226 if (getkvars() == -1)
227 return (-1);
228 kvminit = 1;
229
230 return (0);
231}
232
233kvm_close()
234{
235 if (unixx != -1) {
236 close(unixx);
237 unixx = -1;
238 }
239 if (kmem != -1) {
240 if (kmem != mem)
241 close(kmem);
242 /* otherwise kmem is a copy of mem, and will be closed below */
243 kmem = -1;
244 }
245 if (mem != -1) {
246 close(mem);
247 mem = -1;
248 }
249 if (swap != -1) {
250 close(swap);
251 swap = -1;
252 }
253 if (db != NULL) {
254 dbm_close(db);
255 db = NULL;
256 }
257 kvminit = 0;
258 kvmfilesopen = 0;
259 deadkernel = 0;
15637ed4
RG
260}
261
262kvm_nlist(nl)
263 struct nlist *nl;
264{
265 datum key, data;
266 char dbname[MAXPATHLEN];
267 char dbversion[_POSIX2_LINE_MAX];
268 char kversion[_POSIX2_LINE_MAX];
269 int dbversionlen;
270 char symbuf[MAXSYMSIZE];
271 struct nlist nbuf, *n;
272 int num, did;
273
274 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
275 return (-1);
276 if (deadkernel)
277 goto hard2;
278 /*
279 * initialize key datum
280 */
281 key.dptr = symbuf;
282
283 if (db != NULL)
284 goto win; /* off to the races */
285 /*
286 * open database
287 */
288 sprintf(dbname, "%s/kvm_%s", _PATH_VARRUN, basename(unixf));
289 if ((db = dbm_open(dbname, O_RDONLY, 0)) == NULL)
290 goto hard2;
291 /*
292 * read version out of database
293 */
294 bcopy("VERSION", symbuf, sizeof ("VERSION")-1);
295 key.dsize = (sizeof ("VERSION") - 1);
296 data = dbm_fetch(db, key);
297 if (data.dptr == NULL)
298 goto hard1;
299 bcopy(data.dptr, dbversion, data.dsize);
300 dbversionlen = data.dsize;
301 /*
302 * read version string from kernel memory
303 */
304 bcopy("_version", symbuf, sizeof ("_version")-1);
305 key.dsize = (sizeof ("_version")-1);
306 data = dbm_fetch(db, key);
307 if (data.dptr == NULL)
308 goto hard1;
309 if (data.dsize != sizeof (struct nlist))
310 goto hard1;
311 bcopy(data.dptr, &nbuf, sizeof (struct nlist));
312 lseek(kmem, nbuf.n_value, 0);
313 if (read(kmem, kversion, dbversionlen) != dbversionlen)
314 goto hard1;
315 /*
316 * if they match, we win - otherwise do it the hard way
317 */
318 if (bcmp(dbversion, kversion, dbversionlen) != 0)
319 goto hard1;
320 /*
321 * getem from the database.
322 */
323win:
324 num = did = 0;
325 for (n = nl; n->n_name && n->n_name[0]; n++, num++) {
326 int len;
327 /*
328 * clear out fields from users buffer
329 */
330 n->n_type = 0;
331 n->n_other = 0;
332 n->n_desc = 0;
333 n->n_value = 0;
334 /*
335 * query db
336 */
337 if ((len = strlen(n->n_name)) > MAXSYMSIZE) {
338 seterr("symbol too large");
339 return (-1);
340 }
341 (void)strcpy(symbuf, n->n_name);
342 key.dsize = len;
343 data = dbm_fetch(db, key);
344 if (data.dptr == NULL || data.dsize != sizeof (struct nlist))
345 continue;
346 bcopy(data.dptr, &nbuf, sizeof (struct nlist));
347 n->n_value = nbuf.n_value;
348 n->n_type = nbuf.n_type;
349 n->n_desc = nbuf.n_desc;
350 n->n_other = nbuf.n_other;
351 did++;
352 }
353 return (num - did);
354hard1:
355 dbm_close(db);
356 db = NULL;
357hard2:
358 num = nlist(unixf, nl);
359 if (num == -1)
360 seterr("nlist (hard way) failed");
361 return (num);
362}
363
364kvm_getprocs(what, arg)
365 int what, arg;
366{
367 static int ocopysize = -1;
368
369 if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1)
370 return (NULL);
371 if (!deadkernel) {
372 int ret, copysize;
373
374 if ((ret = getkerninfo(what, NULL, NULL, arg)) == -1) {
375 setsyserr("can't get estimate for kerninfo");
376 return (-1);
377 }
378 copysize = ret;
379 if (copysize > ocopysize &&
170dc86a
DG
380 (kvmprocbase = (struct kinfo_proc *)
381 realloc(kvmprocbase, copysize)) == NULL) {
15637ed4
RG
382 seterr("out of memory");
383 return (-1);
384 }
385 ocopysize = copysize;
386 if ((ret = getkerninfo(what, kvmprocbase, &copysize,
387 arg)) == -1) {
388 setsyserr("can't get proc list");
389 return (-1);
390 }
391 if (copysize % sizeof (struct kinfo_proc)) {
392 seterr("proc size mismatch (got %d total, kinfo_proc: %d)",
393 copysize, sizeof (struct kinfo_proc));
394 return (-1);
395 }
396 kvmnprocs = copysize / sizeof (struct kinfo_proc);
397 } else {
398 int nproc;
399
400 if (kvm_read((void *) nl[X_NPROC].n_value, &nproc,
401 sizeof (int)) != sizeof (int)) {
402 seterr("can't read nproc");
403 return (-1);
404 }
405 if ((kvmprocbase = (struct kinfo_proc *)
406 malloc(nproc * sizeof (struct kinfo_proc))) == NULL) {
407 seterr("out of memory (addr: %x nproc = %d)",
408 nl[X_NPROC].n_value, nproc);
409 return (-1);
410 }
411 kvmnprocs = kvm_doprocs(what, arg, kvmprocbase);
412 realloc(kvmprocbase, kvmnprocs * sizeof (struct kinfo_proc));
413 }
414 kvmprocptr = kvmprocbase;
415
416 return (kvmnprocs);
417}
418
419/*
420 * XXX - should NOT give up so easily - especially since the kernel
421 * may be corrupt (it died). Should gather as much information as possible.
422 * Follows proc ptrs instead of reading table since table may go
423 * away soon.
424 */
425static
426kvm_doprocs(what, arg, buff)
427 int what, arg;
428 char *buff;
429{
430 struct proc *p, proc;
431 register char *bp = buff;
432 int i = 0;
433 int doingzomb = 0;
434 struct eproc eproc;
435 struct pgrp pgrp;
436 struct session sess;
437 struct tty tty;
15637ed4
RG
438
439 /* allproc */
440 if (kvm_read((void *) nl[X_ALLPROC].n_value, &p,
441 sizeof (struct proc *)) != sizeof (struct proc *)) {
442 seterr("can't read allproc");
443 return (-1);
444 }
445
446again:
447 for (; p; p = proc.p_nxt) {
448 if (kvm_read(p, &proc, sizeof (struct proc)) !=
449 sizeof (struct proc)) {
450 seterr("can't read proc at %x", p);
451 return (-1);
452 }
15637ed4
RG
453 if (kvm_read(proc.p_cred, &eproc.e_pcred,
454 sizeof (struct pcred)) == sizeof (struct pcred))
455 (void) kvm_read(eproc.e_pcred.pc_ucred, &eproc.e_ucred,
456 sizeof (struct ucred));
457 switch(ki_op(what)) {
458
459 case KINFO_PROC_PID:
460 if (proc.p_pid != (pid_t)arg)
461 continue;
462 break;
463
464
465 case KINFO_PROC_UID:
466 if (eproc.e_ucred.cr_uid != (uid_t)arg)
467 continue;
468 break;
469
470 case KINFO_PROC_RUID:
471 if (eproc.e_pcred.p_ruid != (uid_t)arg)
472 continue;
473 break;
474 }
15637ed4
RG
475 /*
476 * gather eproc
477 */
478 eproc.e_paddr = p;
479 if (kvm_read(proc.p_pgrp, &pgrp, sizeof (struct pgrp)) !=
480 sizeof (struct pgrp)) {
481 seterr("can't read pgrp at %x", proc.p_pgrp);
482 return (-1);
483 }
484 eproc.e_sess = pgrp.pg_session;
485 eproc.e_pgid = pgrp.pg_id;
486 eproc.e_jobc = pgrp.pg_jobc;
487 if (kvm_read(pgrp.pg_session, &sess, sizeof (struct session))
488 != sizeof (struct session)) {
489 seterr("can't read session at %x", pgrp.pg_session);
490 return (-1);
491 }
492 if ((proc.p_flag&SCTTY) && sess.s_ttyp != NULL) {
493 if (kvm_read(sess.s_ttyp, &tty, sizeof (struct tty))
494 != sizeof (struct tty)) {
495 seterr("can't read tty at %x", sess.s_ttyp);
496 return (-1);
497 }
498 eproc.e_tdev = tty.t_dev;
499 eproc.e_tsess = tty.t_session;
500 if (tty.t_pgrp != NULL) {
501 if (kvm_read(tty.t_pgrp, &pgrp, sizeof (struct
502 pgrp)) != sizeof (struct pgrp)) {
503 seterr("can't read tpgrp at &x",
504 tty.t_pgrp);
505 return (-1);
506 }
507 eproc.e_tpgid = pgrp.pg_id;
508 } else
509 eproc.e_tpgid = -1;
510 } else
511 eproc.e_tdev = NODEV;
512 if (proc.p_wmesg)
513 kvm_read(proc.p_wmesg, eproc.e_wmesg, WMESGLEN);
15637ed4
RG
514 (void) kvm_read(proc.p_vmspace, &eproc.e_vm,
515 sizeof (struct vmspace));
516 eproc.e_xsize = eproc.e_xrssize =
517 eproc.e_xccount = eproc.e_xswrss = 0;
15637ed4
RG
518
519 switch(ki_op(what)) {
520
521 case KINFO_PROC_PGRP:
522 if (eproc.e_pgid != (pid_t)arg)
523 continue;
524 break;
525
526 case KINFO_PROC_TTY:
527 if ((proc.p_flag&SCTTY) == 0 ||
528 eproc.e_tdev != (dev_t)arg)
529 continue;
530 break;
531 }
532
533 i++;
534 bcopy(&proc, bp, sizeof (struct proc));
535 bp += sizeof (struct proc);
536 bcopy(&eproc, bp, sizeof (struct eproc));
537 bp+= sizeof (struct eproc);
538 }
539 if (!doingzomb) {
540 /* zombproc */
541 if (kvm_read((void *) nl[X_ZOMBPROC].n_value, &p,
542 sizeof (struct proc *)) != sizeof (struct proc *)) {
543 seterr("can't read zombproc");
544 return (-1);
545 }
546 doingzomb = 1;
547 goto again;
548 }
549
550 return (i);
551}
552
553struct proc *
554kvm_nextproc()
555{
556
557 if (!kvmprocbase && kvm_getprocs(0, 0) == -1)
558 return (NULL);
559 if (kvmprocptr >= (kvmprocbase + kvmnprocs)) {
8387d405 560#if 0
15637ed4 561 seterr("end of proc list");
8387d405 562#endif
15637ed4
RG
563 return (NULL);
564 }
565 return((struct proc *)(kvmprocptr++));
566}
567
568struct eproc *
569kvm_geteproc(p)
570 const struct proc *p;
571{
572 return ((struct eproc *)(((char *)p) + sizeof (struct proc)));
573}
574
575kvm_setproc()
576{
577 kvmprocptr = kvmprocbase;
578}
579
580kvm_freeprocs()
581{
582
583 if (kvmprocbase) {
584 free(kvmprocbase);
585 kvmprocbase = NULL;
586 }
587}
588
8387d405
DG
589proc_getmem(const struct proc *p, void *buffer, vm_offset_t size, vm_offset_t offset) {
590 int fd;
591 char fn[512+1];
592 sprintf(fn,"/proc/%d",p->p_pid);
593 if( p->p_flag & SSYS)
594 return 0;
595 fd = open(fn,O_RDONLY);
596 if( fd == -1) {
597 return 0;
598 }
599
600 if( lseek(fd, offset, 0) == -1) {
601 close(fd);
602 return 0;
603 }
604 if( read(fd, buffer, size) <= 0) {
605 close(fd);
606 return 0;
607 }
608 close(fd);
609 return 1;
610}
15637ed4 611
15637ed4
RG
612struct user *
613kvm_getu(p)
614 const struct proc *p;
615{
616 register struct kinfo_proc *kp = (struct kinfo_proc *)p;
617 register int i;
618 register char *up;
619 u_int vaddr;
620 struct swapblk swb;
8387d405 621 int arg_size;
15637ed4
RG
622
623 if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1)
624 return (NULL);
625 if (p->p_stat == SZOMB) {
626 seterr("zombie process");
627 return (NULL);
628 }
629
c6500831 630 if (proc_getmem(p, user.upages, sizeof user.upages, USRSTACK)) {
8387d405
DG
631 kp->kp_eproc.e_vm.vm_rssize =
632 kp->kp_eproc.e_vm.vm_pmap.pm_stats.resident_count; /* XXX */
633 return &user.user;
634 }
635
c6500831 636 return (NULL);
15637ed4 637}
15637ed4
RG
638
639char *
640kvm_getargs(p, up)
641 const struct proc *p;
642 const struct user *up;
643{
8387d405
DG
644 int arg_size, arg_offset;
645 static char cmdbuf[ARG_MAX];
646 char argc[ARG_MAX*3];
647 int *argv;
15637ed4 648 register char *cp;
15637ed4
RG
649 char c;
650 int nbad;
8387d405
DG
651 char *cmdbufp;
652 vm_offset_t vaddr;
653 char procfile[16];
654 int mmfd;
655#if 0
656 char *argc = NULL;
15637ed4 657#endif
15637ed4 658
8387d405
DG
659 *cmdbuf = 0;
660
661 vaddr = (u_int)((struct kinfo_proc *)p)->kp_eproc.e_vm.vm_minsaddr;
662 arg_size = USRSTACK - vaddr;
663
664 if (arg_size >= 3*ARG_MAX)
665 goto bad;
666
667#if 0
668 sprintf(procfile, "/proc/%d", p->p_pid);
669 if ((mmfd = open(procfile, O_RDONLY, 0)) == -1) {
670printf("failed to open %s\n",procfile);
671 goto bad;
672 }
673
674 if ((argc = mmap(0, arg_size, PROT_READ, MAP_FILE, mmfd, vaddr))
675 == (char *)-1) {
676printf("failed to mmap %s error=%s\n", procfile, strerror(errno));
677 goto bad;
678 }
15637ed4 679#endif
8387d405 680
c6500831
DG
681 if (!proc_getmem(p, argc, arg_size, vaddr))
682 goto bad;
15637ed4 683
8387d405
DG
684 argv = (int *)argc;
685
686 arg_offset = argv[0] - vaddr;
687 if (arg_offset >= 3*ARG_MAX)
688 goto bad;
689
15637ed4 690 nbad = 0;
15637ed4 691
8387d405
DG
692 cmdbufp = cmdbuf;
693 for (cp = &argc[arg_offset]; cp < &argc[arg_size]; cp++, cmdbufp++) {
694 c = *cmdbufp = *cp;
15637ed4 695 if (c == 0) { /* convert null between arguments to space */
8387d405 696 *cmdbufp = ' ';
15637ed4
RG
697 if (*(cp+1) == 0) break; /* if null argument follows then no more args */
698 }
699 else if (c < ' ' || c > 0176) {
700 if (++nbad >= 5*(0+1)) { /* eflg -> 0 XXX */ /* limit number of bad chars to 5 */
8387d405 701 *cmdbufp++ = '?';
15637ed4
RG
702 break;
703 }
8387d405 704 *cmdbufp = '?';
15637ed4
RG
705 }
706 else if (0 == 0 && c == '=') { /* eflg -> 0 XXX */
8387d405
DG
707 while (*--cmdbufp != ' ')
708 if (cmdbufp <= cmdbuf)
15637ed4
RG
709 break;
710 break;
711 }
712 }
8387d405
DG
713 *cmdbufp = 0;
714
715 while (*--cmdbufp == ' ')
716 *cmdbufp = 0;
717
718 if (cmdbuf[0] == '-' || cmdbuf[0] == '?' || cmdbuf[0] <= ' ') {
719bad:
15637ed4
RG
720 (void) strcat(cmdbuf, " (");
721 (void) strncat(cmdbuf, p->p_comm, sizeof(p->p_comm));
722 (void) strcat(cmdbuf, ")");
723 }
8387d405
DG
724#if 0
725 if (argc && argc != (char *)-1)
726 munmap(argc, arg_size);
727 if (mmfd && mmfd != -1)
728 close (mmfd);
729#endif
15637ed4
RG
730 return (cmdbuf);
731}
732
15637ed4
RG
733static
734getkvars()
735{
736 if (kvm_nlist(nl) == -1)
737 return (-1);
15637ed4
RG
738 if (kvm_read((void *) nl[X_NSWAP].n_value, &nswap, sizeof (long)) !=
739 sizeof (long)) {
740 seterr("can't read nswap");
741 return (-1);
742 }
743 if (kvm_read((void *) nl[X_DMMIN].n_value, &dmmin, sizeof (long)) !=
744 sizeof (long)) {
745 seterr("can't read dmmin");
746 return (-1);
747 }
748 if (kvm_read((void *) nl[X_DMMAX].n_value, &dmmax, sizeof (long)) !=
749 sizeof (long)) {
750 seterr("can't read dmmax");
751 return (-1);
752 }
753 return (0);
754}
755
756kvm_read(loc, buf, len)
757 void *loc;
758 void *buf;
759{
760 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
761 return (-1);
762 if (iskva(loc)) {
c6500831 763 lseek(kmem, (off_t) loc, 0);
15637ed4
RG
764 if (read(kmem, buf, len) != len) {
765 seterr("error reading kmem at %x", loc);
766 return (-1);
767 }
768 } else {
769 lseek(mem, (off_t) loc, 0);
770 if (read(mem, buf, len) != len) {
771 seterr("error reading mem at %x", loc);
772 return (-1);
773 }
774 }
775 return (len);
776}
777
15637ed4
RG
778#include <varargs.h>
779static char errbuf[_POSIX2_LINE_MAX];
780
781static void
782seterr(va_alist)
783 va_dcl
784{
785 char *fmt;
786 va_list ap;
787
788 va_start(ap);
789 fmt = va_arg(ap, char *);
790 (void) vsnprintf(errbuf, _POSIX2_LINE_MAX, fmt, ap);
791#if DEBUG
792 (void) vfprintf(stderr, fmt, ap);
793#endif
794 va_end(ap);
795}
796
797static void
798setsyserr(va_alist)
799 va_dcl
800{
801 char *fmt, *cp;
802 va_list ap;
803 extern int errno;
804
805 va_start(ap);
806 fmt = va_arg(ap, char *);
807 (void) vsnprintf(errbuf, _POSIX2_LINE_MAX, fmt, ap);
808 for (cp=errbuf; *cp; cp++)
809 ;
810 snprintf(cp, _POSIX2_LINE_MAX - (cp - errbuf), ": %s", strerror(errno));
8387d405
DG
811#if DEBUG
812 (void) fprintf(stderr, "%s\n", errbuf);
813#endif
15637ed4
RG
814 va_end(ap);
815}
816
817char *
818kvm_geterr()
819{
820 return (errbuf);
821}