xref: /original-bsd/usr.sbin/pstat/pstat.c (revision ba762ddc)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 char copyright[] =
9 "@(#) Copyright (c) 1980 Regents of the University of California.\n\
10  All rights reserved.\n";
11 #endif /* not lint */
12 
13 #ifndef lint
14 static char sccsid[] = "@(#)pstat.c	5.30 (Berkeley) 05/02/91";
15 #endif /* not lint */
16 
17 /*
18  * Print system stuff
19  */
20 #include <sys/param.h>
21 #include <sys/user.h>
22 #include <sys/proc.h>
23 #include <sys/text.h>
24 #include <sys/time.h>
25 #include <sys/vnode.h>
26 #include <sys/map.h>
27 #define KERNEL
28 #define NFS
29 #include <sys/file.h>
30 #include <sys/mount.h>
31 #include <ufs/quota.h>
32 #include <ufs/inode.h>
33 #include <sys/stat.h>
34 #include <nfs/nfsv2.h>
35 #include <nfs/nfs.h>
36 #include <nfs/nfsnode.h>
37 #include <sys/ioctl.h>
38 #include <sys/tty.h>
39 #undef KERNEL
40 #include <sys/conf.h>
41 #include <sys/vm.h>
42 #include <machine/pte.h>
43 #include <sys/kinfo.h>
44 
45 #include <nlist.h>
46 #include <kvm.h>
47 #include <stdio.h>
48 #include "pathnames.h"
49 
50 #define mask(x)		(x&0377)
51 #define	clear(x)	((int)x &~ KERNBASE)
52 
53 char	*fnlist	= NULL;
54 char	*fcore	= NULL;
55 
56 struct nlist nl[] = {
57 #define	STEXT	0
58 	{ "_text" },
59 #define	SPROC	1
60 	{ "_proc" },
61 #define	SFIL	2
62 	{ "_file" },
63 #define	SWAPMAP	3
64 	{ "_swapmap" },
65 #define	SNPROC	4
66 	{ "_nproc" },
67 #define	SNTEXT	5
68 	{ "_ntext" },
69 #define	SNFILE	6
70 	{ "_nfile" },
71 #define	SNSWAPMAP 7
72 	{ "_nswapmap" },
73 #define	SDMMIN	8
74 	{ "_dmmin" },
75 #define	SDMMAX	9
76 	{ "_dmmax" },
77 #define	SNSWDEV	10
78 	{ "_nswdev" },
79 #define	SSWDEVT	11
80 	{ "_swdevt" },
81 #define NLMANDATORY SSWDEVT	/* names up to here are mandatory */
82 #define	SCONS	12
83 	{ "_cons" },
84 #define	SPTY	13
85 	{ "_pt_tty" },
86 #define	SNPTY	14
87 	{ "_npty" },
88 #ifdef vax
89 #define	SDZ	(SNPTY+1)
90 	{ "_dz_tty" },
91 #define	SNDZ	(SNPTY+2)
92 	{ "_dz_cnt" },
93 #define	SDMF	(SNPTY+3)
94 	{ "_dmf_tty" },
95 #define	SNDMF	(SNPTY+4)
96 	{ "_ndmf" },
97 #define	SDH	(SNPTY+5)
98 	{ "_dh11" },
99 #define	SNDH	(SNPTY+6)
100 	{ "_ndh11" },
101 #define	SDHU	(SNPTY+7)
102 	{ "_dhu_tty" },
103 #define	SNDHU	(SNPTY+8)
104 	{ "_ndhu" },
105 #define	SDMZ	(SNPTY+9)
106 	{ "_dmz_tty" },
107 #define	SNDMZ	(SNPTY+10)
108 	{ "_ndmz" },
109 #define	SQD	(SNPTY+11)
110 	{ "_qd_tty" },
111 #define	SNQD	(SNPTY+12)
112 	{ "_nNQD" },
113 #endif
114 
115 #ifdef tahoe
116 #define	SVX	(SNPTY+1)
117 	{ "_vx_tty" },
118 #define	SNVX	(SNPTY+2)
119 	{ "_nvx" },
120 #define SMP	(SNPTY+3)
121 	{ "_mp_tty" },
122 #define SNMP	(SNPTY+4)
123 	{ "_nmp" },
124 #endif
125 
126 #ifdef hp300
127 #define	SDCA	(SNPTY+1)
128 	{ "_dca_tty" },
129 #define	SNDCA	(SNPTY+2)
130 	{ "_ndca" },
131 #define	SDCM	(SNPTY+3)
132 	{ "_dcm_tty" },
133 #define	SNDCM	(SNPTY+4)
134 	{ "_ndcm" },
135 #define	SDCL	(SNPTY+5)
136 	{ "_dcl_tty" },
137 #define	SNDCL	(SNPTY+6)
138 	{ "_ndcl" },
139 #define	SITE	(SNPTY+7)
140 	{ "_ite_tty" },
141 #define	SNITE	(SNPTY+8)
142 	{ "_nite" },
143 #endif
144 	{ "" }
145 };
146 
147 int	vnof;
148 int	txtf;
149 int	prcf;
150 int	ttyf;
151 int	usrf;
152 int	upid;
153 int	filf;
154 int	swpf;
155 int	totflg;
156 char	partab[1];
157 struct	cdevsw	cdevsw[1];
158 struct	bdevsw	bdevsw[1];
159 int	allflg;
160 int	nflg;
161 u_long	getword();
162 off_t	mkphys();
163 
164 char	*Program;
165 
166 #define V(x)	(void *)(x)
167 
168 main(argc, argv)
169 	int argc;
170 	char **argv;
171 {
172 	extern char *optarg;
173 	extern int optind;
174 	int ch, ret;
175 
176         Program = argv[0];
177 	while ((ch = getopt(argc, argv, "TafvikptU:sxnu")) != EOF)
178 		switch (ch) {
179 		case 'T':
180 			totflg++;
181 			break;
182 		case 'a':
183 			allflg++;
184 			/*FALLTHROUGH*/
185 		case 'p':
186 			prcf++;
187 			break;
188 		case 'f':
189 			filf++;
190 			break;
191 		case 'v':
192 		case 'i':
193 			vnof++;
194 			break;
195 		case 't':
196 			ttyf++;
197 			break;
198 		case 'U':
199 			usrf++;
200 			sscanf(optarg, "%d", &upid);
201 			break;
202 		case 's':
203 			swpf++;
204 			break;
205 		case 'x':
206 			txtf++;
207 			break;
208 		case 'n':
209 			nflg++;
210 			break;
211 		case 'u':
212 			fprintf(stderr, "pstat: use [ -U pid ] for -u\n");
213 			exit(1);
214 		case '?':
215 		default:
216 			fprintf(stderr, "usage: pstat -[Tafiptsx] [-U [pid]] [system] [core]\n");
217 			exit(1);
218 		}
219 	argc -= optind;
220 	argv += optind;
221 
222 	if (argc > 1)
223 		fcore = argv[1];
224 	if (argc > 0)
225 		fnlist = argv[0];
226 	if (kvm_openfiles(fnlist, fcore, NULL) == -1) {
227 		error("kvm_openfiles: %s", kvm_geterr());
228 		exit(1);
229 	}
230 	if ((ret = kvm_nlist(nl)) != 0) {
231 		int i, quit = 0;
232 
233 		if (ret == -1) {
234 			error("kvm_nlist: %s", kvm_geterr());
235 			exit(1);
236 		}
237 		for (i = 0; i <= NLMANDATORY; i++) {
238 			if (!nl[i].n_value) {
239 				quit = 1;
240 				error("undefined symbol: %s\n",
241 					nl[i].n_name);
242 			}
243 		}
244 		if (quit)
245 			exit(1);
246 	}
247 	if (!(filf | totflg | vnof | prcf | txtf | ttyf | usrf | swpf)) {
248 		printf("pstat: one or more of -[aivxptfsU] is required\n");
249 		exit(1);
250 	}
251 	if (filf||totflg)
252 		dofile();
253 	if (vnof||totflg)
254 		dovnode();
255 	if (prcf||totflg)
256 		doproc();
257 	if (txtf||totflg)
258 		dotext();
259 	if (ttyf)
260 		dotty();
261 	if (usrf)
262 		dousr();
263 	if (swpf||totflg)
264 		doswap();
265 }
266 
267 struct e_vnode {
268 	struct vnode *avnode;
269 	struct vnode vnode;
270 };
271 
272 dovnode()
273 {
274 	register struct e_vnode *e_vnodebase, *endvnode, *evp;
275 	register struct vnode *vp;
276 	register struct mount *maddr = NULL, *mp;
277 	int numvnodes;
278 	struct e_vnode *loadvnodes();
279 	struct mount *getmnt();
280 
281 	e_vnodebase = loadvnodes(&numvnodes);
282 	if (totflg) {
283 		printf("%7d vnodes\n", numvnodes);
284 		return;
285 	}
286 	endvnode = e_vnodebase + numvnodes;
287 	printf("%d active vnodes\n", numvnodes);
288 
289 
290 #define ST	mp->mnt_stat
291 	for (evp = e_vnodebase; evp < endvnode; evp++) {
292 		vp = &evp->vnode;
293 		if (vp->v_mount != maddr) {
294 			/*
295 			 * New filesystem
296 			 */
297 			if ((mp = getmnt(vp->v_mount)) == NULL)
298 				continue;
299 			maddr = vp->v_mount;
300 			mount_print(mp);
301 			vnode_header();
302 			switch(ST.f_type) {
303 			case MOUNT_UFS:
304 			case MOUNT_MFS:
305 				ufs_header();
306 				break;
307 			case MOUNT_NFS:
308 				nfs_header();
309 				break;
310 			case MOUNT_NONE:
311 			case MOUNT_PC:
312 			default:
313 				break;
314 			}
315 			printf("\n");
316 		}
317 		vnode_print(evp->avnode, vp);
318 		switch(ST.f_type) {
319 		case MOUNT_UFS:
320 		case MOUNT_MFS:
321 			ufs_print(vp);
322 			break;
323 		case MOUNT_NFS:
324 			nfs_print(vp);
325 			break;
326 		case MOUNT_NONE:
327 		case MOUNT_PC:
328 		default:
329 			break;
330 		}
331 		printf("\n");
332 	}
333 	free(e_vnodebase);
334 }
335 
336 vnode_header()
337 {
338 	printf("ADDR     TYP VFLAG  USE HOLD");
339 }
340 
341 vnode_print(avnode, vp)
342 	struct vnode *avnode;
343 	struct vnode *vp;
344 {
345 	char *type, flags[16];
346 	char *fp = flags;
347 	register flag;
348 
349 	/*
350 	 * set type
351 	 */
352 	switch(vp->v_type) {
353 	case VNON:
354 		type = "non"; break;
355 	case VREG:
356 		type = "reg"; break;
357 	case VDIR:
358 		type = "dir"; break;
359 	case VBLK:
360 		type = "blk"; break;
361 	case VCHR:
362 		type = "chr"; break;
363 	case VLNK:
364 		type = "lnk"; break;
365 	case VSOCK:
366 		type = "soc"; break;
367 	case VFIFO:
368 		type = "fif"; break;
369 	case VBAD:
370 		type = "bad"; break;
371 	default:
372 		type = "unk"; break;
373 	}
374 	/*
375 	 * gather flags
376 	 */
377 	flag = vp->v_flag;
378 	if (flag & VROOT)
379 		*fp++ = 'R';
380 	if (flag & VTEXT)
381 		*fp++ = 'T';
382 	if (flag & VSYSTEM)
383 		*fp++ = 'S';
384 	if (flag & VXLOCK)
385 		*fp++ = 'L';
386 	if (flag & VXWANT)
387 		*fp++ = 'W';
388 	if (flag & VBWAIT)
389 		*fp++ = 'B';
390 	if (flag & VALIASED)
391 		*fp++ = 'A';
392 	if (flag == 0)
393 		*fp++ = '-';
394 	*fp = '\0';
395 	/*
396 	 * print it
397 	 */
398 	printf("%8x %s %5s %4d %4d",
399 		avnode, type, flags, vp->v_usecount, vp->v_holdcnt);
400 }
401 
402 ufs_header()
403 {
404 	printf(" FILEID IFLAG RDEV|SZ");
405 }
406 
407 ufs_print(vp)
408 	struct vnode *vp;
409 {
410 	struct inode *ip = VTOI(vp);
411 	char flagbuf[16], *flags = flagbuf;
412 	register flag;
413 	char *name;
414 	mode_t type;
415 	extern char *devname();
416 
417 	flag = ip->i_flag;
418 	if (flag & ILOCKED)
419 		*flags++ = 'L';
420 	if (flag & IWANT)
421 		*flags++ = 'W';
422 	if (flag & IRENAME)
423 		*flags++ = 'R';
424 	if (flag & IUPD)
425 		*flags++ = 'U';
426 	if (flag & IACC)
427 		*flags++ = 'A';
428 	if (flag & ICHG)
429 		*flags++ = 'C';
430 	if (flag & IMOD)
431 		*flags++ = 'M';
432 	if (flag & ISHLOCK)
433 		*flags++ = 'S';
434 	if (flag & IEXLOCK)
435 		*flags++ = 'E';
436 	if (flag & ILWAIT)
437 		*flags++ = 'Z';
438 	if (flag == 0)
439 		*flags++ = '-';
440 	*flags = '\0';
441 
442 	printf(" %6d %5s", ip->i_number, flagbuf);
443 	type = ip->i_mode & S_IFMT;
444 	if (type == S_IFCHR || type == S_IFBLK)
445 		if (nflg || ((name = devname(ip->i_rdev, type)) == NULL))
446 			printf("   %2d,%-2d",
447 				major(ip->i_rdev), minor(ip->i_rdev));
448 		else
449 			printf(" %7s", name);
450 	else
451 		printf(" %7d", ip->i_size);
452 }
453 
454 nfs_header()
455 {
456 	printf(" FILEID NFLAG RDEV|SZ");
457 }
458 
459 nfs_print(vp)
460 	struct vnode *vp;
461 {
462 	struct nfsnode *np = VTONFS(vp);
463 	char flagbuf[16], *flags = flagbuf;
464 	register flag;
465 	char *name;
466 	mode_t type;
467 	extern char *devname();
468 
469 	flag = np->n_flag;
470 	if (flag & NLOCKED)
471 		*flags++ = 'L';
472 	if (flag & NWANT)
473 		*flags++ = 'W';
474 	if (flag & NMODIFIED)
475 		*flags++ = 'M';
476 	if (flag & NWRITEERR)
477 		*flags++ = 'E';
478 	if (flag == 0)
479 		*flags++ = '-';
480 	*flags = '\0';
481 
482 #define VT	np->n_vattr
483 	printf(" %6d %5s", VT.va_fileid, flagbuf);
484 	type = VT.va_mode & S_IFMT;
485 	if (type == S_IFCHR || type == S_IFBLK)
486 		if (nflg || ((name = devname(VT.va_rdev, type)) == NULL))
487 			printf("   %2d,%-2d",
488 				major(VT.va_rdev), minor(VT.va_rdev));
489 		else
490 			printf(" %7s", name);
491 	else
492 		printf(" %7d", np->n_size);
493 }
494 
495 /*
496  * Given a pointer to a mount structure in kernel space,
497  * read it in and return a usable pointer to it.
498  */
499 struct mount *
500 getmnt(maddr)
501 	struct mount *maddr;
502 {
503 	static struct mtab {
504 		struct mtab *next;
505 		struct mount *maddr;
506 		struct mount mount;
507 	} *mhead = NULL;
508 	register struct mtab *mt;
509 
510 	for (mt = mhead; mt != NULL; mt = mt->next)
511 		if (maddr == mt->maddr)
512 			return (&mt->mount);
513 	if ((mt = (struct mtab *)malloc(sizeof (struct mtab))) == NULL) {
514 		error("out of memory");
515 		exit(1);
516 	}
517 	if (kvm_read(V(maddr), &mt->mount, sizeof(struct mount)) !=
518 	    sizeof(struct mount)) {
519 		error("can't read mount table at %x", maddr);
520 		return (NULL);
521 	}
522 	mt->maddr = maddr;
523 	mt->next = mhead;
524 	mhead = mt;
525 	return (&mt->mount);
526 }
527 
528 mount_print(mp)
529 	struct mount *mp;
530 {
531 	char *type = "unknown";
532 	register flags;
533 
534 #define ST	mp->mnt_stat
535 	printf("*** MOUNT ");
536 	switch (ST.f_type) {
537 	case MOUNT_NONE:
538 		type = "none";
539 		break;
540 	case MOUNT_UFS:
541 		type = "ufs";
542 		break;
543 	case MOUNT_NFS:
544 		type = "nfs";
545 		break;
546 	case MOUNT_MFS:
547 		type = "mfs";
548 		break;
549 	case MOUNT_PC:
550 		type = "pc";
551 		break;
552 	}
553 	printf("%s %s on %s", type, ST.f_mntfromname, ST.f_mntonname);
554 	if (flags = mp->mnt_flag) {
555 		char *comma = "(";
556 
557 		putchar(' ');
558 		/* user visable flags */
559 		if (flags & MNT_RDONLY) {
560 			printf("%srdonly", comma);
561 			flags &= ~MNT_RDONLY;
562 			comma = ",";
563 		}
564 		if (flags & MNT_SYNCHRONOUS) {
565 			printf("%ssynchronous", comma);
566 			flags &= ~MNT_SYNCHRONOUS;
567 			comma = ",";
568 		}
569 		if (flags & MNT_NOEXEC) {
570 			printf("%snoexec", comma);
571 			flags &= ~MNT_NOEXEC;
572 			comma = ",";
573 		}
574 		if (flags & MNT_NOSUID) {
575 			printf("%snosuid", comma);
576 			flags &= ~MNT_NOSUID;
577 			comma = ",";
578 		}
579 		if (flags & MNT_NODEV) {
580 			printf("%snodev", comma);
581 			flags &= ~MNT_NODEV;
582 			comma = ",";
583 		}
584 		if (flags & MNT_EXPORTED) {
585 			printf("%sexport", comma);
586 			flags &= ~MNT_EXPORTED;
587 			comma = ",";
588 		}
589 		if (flags & MNT_EXRDONLY) {
590 			printf("%sexrdonly", comma);
591 			flags &= ~MNT_EXRDONLY;
592 			comma = ",";
593 		}
594 		if (flags & MNT_LOCAL) {
595 			printf("%slocal", comma);
596 			flags &= ~MNT_LOCAL;
597 			comma = ",";
598 		}
599 		if (flags & MNT_QUOTA) {
600 			printf("%squota", comma);
601 			flags &= ~MNT_QUOTA;
602 			comma = ",";
603 		}
604 		/* filesystem control flags */
605 		if (flags & MNT_UPDATE) {
606 			printf("%supdate", comma);
607 			flags &= ~MNT_UPDATE;
608 			comma = ",";
609 		}
610 		if (flags & MNT_MLOCK) {
611 			printf("%slock", comma);
612 			flags &= ~MNT_MLOCK;
613 			comma = ",";
614 		}
615 		if (flags & MNT_MWAIT) {
616 			printf("%swait", comma);
617 			flags &= ~MNT_MWAIT;
618 			comma = ",";
619 		}
620 		if (flags & MNT_MPBUSY) {
621 			printf("%sbusy", comma);
622 			flags &= ~MNT_MPBUSY;
623 			comma = ",";
624 		}
625 		if (flags & MNT_MPWANT) {
626 			printf("%swant", comma);
627 			flags &= ~MNT_MPWANT;
628 			comma = ",";
629 		}
630 		if (flags & MNT_UNMOUNT) {
631 			printf("%sunmount", comma);
632 			flags &= ~MNT_UNMOUNT;
633 			comma = ",";
634 		}
635 		if (flags)
636 			printf("%sunknown_flags:%x", flags);
637 		printf(")");
638 	}
639 	printf("\n");
640 #undef ST
641 }
642 
643 struct e_vnode *
644 loadvnodes(avnodes)
645 	int *avnodes;
646 {
647 	int ret, copysize;
648 	struct e_vnode *vnodebase;
649 
650 	if (fcore != NULL) {
651 		error("vnodes on dead kernel, not impl yet\n");
652 		exit(1);
653 	}
654 	if ((ret = getkerninfo(KINFO_VNODE, NULL, NULL, 0)) == -1) {
655 		syserror("can't get estimate for kerninfo");
656 		exit(1);
657 	}
658 	copysize = ret;
659 	if ((vnodebase = (struct e_vnode *)malloc(copysize))
660 	     == NULL) {
661 		error("out of memory");
662 		exit(1);
663 	}
664 	if ((ret = getkerninfo(KINFO_VNODE, vnodebase, &copysize, 0))
665 	     == -1) {
666 		syserror("can't get vnode list");
667 		exit(1);
668 	}
669 	if (copysize % sizeof (struct e_vnode)) {
670 		error("vnode size mismatch");
671 		exit(1);
672 	}
673 	*avnodes = copysize / sizeof (struct e_vnode);
674 
675 	return (vnodebase);
676 }
677 
678 u_long
679 getword(loc)
680 	int loc;
681 {
682 	u_long word;
683 
684 	kvm_read(V(loc), &word, sizeof (word));
685 	return (word);
686 }
687 
688 putf(v, n)
689 {
690 	if (v)
691 		printf("%c", n);
692 	else
693 		printf(" ");
694 }
695 
696 dotext()
697 {
698 	register struct text *xp;
699 	int ntext;
700 	struct text *xtext, *atext;
701 	int ntx, ntxca;
702 
703 	ntx = ntxca = 0;
704 	ntext = getword(nl[SNTEXT].n_value);
705 	xtext = (struct text *)calloc(ntext, sizeof (struct text));
706 	atext = (struct text *)getword(nl[STEXT].n_value);
707 	if (ntext < 0 || ntext > 10000) {
708 		fprintf(stderr, "number of texts is preposterous (%d)\n",
709 			ntext);
710 		return;
711 	}
712 	if (xtext == NULL) {
713 		fprintf(stderr, "can't allocate memory for text table\n");
714 		return;
715 	}
716 	kvm_read(atext, xtext, ntext * sizeof (struct text));
717 	for (xp = xtext; xp < &xtext[ntext]; xp++) {
718 		if (xp->x_vptr != NULL)
719 			ntxca++;
720 		if (xp->x_count != 0)
721 			ntx++;
722 	}
723 	if (totflg) {
724 		printf("%3d/%3d texts active, %3d used\n", ntx, ntext, ntxca);
725 		return;
726 	}
727 	printf("%d/%d active texts, %d used\n", ntx, ntext, ntxca);
728 	printf("\
729    LOC   FLAGS DADDR     CADDR  RSS SIZE     VPTR   CNT CCNT      FORW     BACK\n");
730 	for (xp = xtext; xp < &xtext[ntext]; xp++) {
731 		if (xp->x_vptr == NULL)
732 			continue;
733 		printf("%8.1x", atext + (xp - xtext));
734 		printf(" ");
735 		putf(xp->x_flag&XPAGV, 'P');
736 		putf(xp->x_flag&XTRC, 'T');
737 		putf(xp->x_flag&XWRIT, 'W');
738 		putf(xp->x_flag&XLOAD, 'L');
739 		putf(xp->x_flag&XLOCK, 'K');
740 		putf(xp->x_flag&XWANT, 'w');
741 		printf("%5x", xp->x_daddr[0]);
742 		printf("%10x", xp->x_caddr);
743 		printf("%5d", xp->x_rssize);
744 		printf("%5d", xp->x_size);
745 		printf("%10.1x", xp->x_vptr);
746 		printf("%5d", xp->x_count&0377);
747 		printf("%5d", xp->x_ccount);
748 		printf("%10x", xp->x_forw);
749 		printf("%9x", xp->x_back);
750 		printf("\n");
751 	}
752 	free(xtext);
753 }
754 
755 doproc()
756 {
757 	struct proc *xproc, *aproc;
758 	int nproc;
759 	register struct proc *pp;
760 	register loc, np;
761 	/*
762 	struct pte apte;
763 	*/
764 
765 	nproc = getword(nl[SNPROC].n_value);
766 	xproc = (struct proc *)calloc(nproc, sizeof (struct proc));
767 	aproc = (struct proc *)getword(nl[SPROC].n_value);
768 	if (nproc < 0 || nproc > 100000) {
769 		fprintf(stderr, "number of procs is preposterous (%d)\n",
770 			nproc);
771 		return;
772 	}
773 	if (xproc == NULL) {
774 		fprintf(stderr, "can't allocate memory for proc table\n");
775 		return;
776 	}
777 	kvm_read(aproc, xproc, nproc * sizeof (struct proc));
778 	np = 0;
779 	for (pp=xproc; pp < &xproc[nproc]; pp++)
780 		if (pp->p_stat)
781 			np++;
782 	if (totflg) {
783 		printf("%3d/%3d processes\n", np, nproc);
784 		return;
785 	}
786 	printf("%d/%d processes\n", np, nproc);
787 	printf("   LOC    S        F POIP PRI      SIG  UID SLP TIM  CPU  NI    PID   PPID    ADDR   RSS SRSS SIZE    WCHAN    LINK   TEXTP\n");
788 	for (pp=xproc; pp<&xproc[nproc]; pp++) {
789 		if (pp->p_stat==0 && allflg==0)
790 			continue;
791 		printf("%8x", aproc + (pp - xproc));
792 		printf(" %2d", pp->p_stat);
793 		printf(" %8x", pp->p_flag);
794 		printf(" %4d", pp->p_poip);
795 		printf(" %3d", pp->p_pri);
796 		printf(" %8x", pp->p_sig);
797 		printf(" %4d", pp->p_uid);
798 		printf(" %3d", pp->p_slptime);
799 		printf(" %3d", pp->p_time);
800 		printf(" %4d", pp->p_cpu&0377);
801 		printf(" %3d", pp->p_nice);
802 		printf(" %6d", pp->p_pid);
803 		printf(" %6d", pp->p_ppid);
804 		/*
805 		if (pp->p_flag & SLOAD) {
806 			kvm_read(pp->p_addr, &apte, sizeof(apte));
807 			printf(" %8x", apte.pg_pfnum);
808 		} else
809 			printf(" %8x", pp->p_swaddr);
810 		*/
811 		printf(" %4x", pp->p_rssize);
812 		printf(" %4x", pp->p_swrss);
813 		printf(" %5x", pp->p_dsize+pp->p_ssize);
814 		printf(" %7x", clear(pp->p_wchan));
815 		printf(" %7x", clear(pp->p_link));
816 		printf(" %7x", clear(pp->p_textp));
817 		printf("\n");
818 	}
819 	free(xproc);
820 }
821 
822 char mesg[] = "  LINE RAW CAN OUT  HWT LWT     ADDR COL STATE  SESS  PGID DISC\n";
823 int ttyspace = 128;
824 struct tty *tty;
825 
826 dotty()
827 {
828 
829 	if ((tty = (struct tty *)malloc(ttyspace * sizeof(*tty))) == 0) {
830 		printf("pstat: out of memory\n");
831 		return;
832 	}
833 #ifndef hp300
834 	printf("1 cons\n");
835 	kvm_read(V(nl[SCONS].n_value), tty, sizeof(*tty));
836 	printf(mesg);
837 	ttyprt(&tty[0], 0);
838 #endif
839 #ifdef vax
840 	if (nl[SNQD].n_type != 0)
841 		doqdss();
842 	if (nl[SNDZ].n_type != 0)
843 		dottytype("dz", SDZ, SNDZ);
844 	if (nl[SNDH].n_type != 0)
845 		dottytype("dh", SDH, SNDH);
846 	if (nl[SNDMF].n_type != 0)
847 		dottytype("dmf", SDMF, SNDMF);
848 	if (nl[SNDHU].n_type != 0)
849 		dottytype("dhu", SDHU, SNDHU);
850 	if (nl[SNDMZ].n_type != 0)
851 		dottytype("dmz", SDMZ, SNDMZ);
852 #endif
853 #ifdef tahoe
854 	if (nl[SNVX].n_type != 0)
855 		dottytype("vx", SVX, SNVX);
856 	if (nl[SNMP].n_type != 0)
857 		dottytype("mp", SMP, SNMP);
858 #endif
859 #ifdef hp300
860 	if (nl[SNITE].n_type != 0)
861 		dottytype("ite", SITE, SNITE);
862 	if (nl[SNDCA].n_type != 0)
863 		dottytype("dca", SDCA, SNDCA);
864 	if (nl[SNDCM].n_type != 0)
865 		dottytype("dcm", SDCM, SNDCM);
866 	if (nl[SNDCL].n_type != 0)
867 		dottytype("dcl", SDCL, SNDCL);
868 #endif
869 	if (nl[SNPTY].n_type != 0)
870 		dottytype("pty", SPTY, SNPTY);
871 }
872 
873 /*
874  * Special case the qdss: there are 4 ttys per qdss,
875  * but only the first of each is used as a tty.
876  */
877 #ifdef vax
878 doqdss()
879 {
880 	int nqd;
881 	register struct tty *tp;
882 
883 	kvm_read(V(nl[SNQD].n_value), &nqd, sizeof(nqd));
884 	printf("%d qd\n", nqd);
885 	kvm_read((V(nl[SQD].n_value), tty, nqd * sizeof(struct tty) * 4);
886 	printf(mesg);
887 	for (tp = tty; tp < &tty[nqd * 4]; tp += 4)
888 		ttyprt(tp, tp - tty);
889 }
890 #endif
891 
892 dottytype(name, type, number)
893 char *name;
894 {
895 	int ntty;
896 	register struct tty *tp;
897 	extern char *realloc();
898 
899 	if (tty == (struct tty *)0)
900 		return;
901 	kvm_read(V(nl[number].n_value), &ntty, sizeof(ntty));
902 	printf("%d %s lines\n", ntty, name);
903 	if (ntty > ttyspace) {
904 		ttyspace = ntty;
905 		if ((tty = (struct tty *)realloc(tty, ttyspace * sizeof(*tty))) == 0) {
906 			printf("pstat: out of memory\n");
907 			return;
908 		}
909 	}
910 	kvm_read(V(nl[type].n_value), tty, ntty * sizeof(struct tty));
911 	printf(mesg);
912 	for (tp = tty; tp < &tty[ntty]; tp++)
913 		ttyprt(tp, tp - tty);
914 }
915 
916 struct {
917 	int flag;
918 	char val;
919 } ttystates[] = {
920 	TS_WOPEN,	'W',
921 	TS_ISOPEN,	'O',
922 	TS_CARR_ON,	'C',
923 	TS_TIMEOUT,	'T',
924 	TS_FLUSH,	'F',
925 	TS_BUSY,	'B',
926 	TS_ASLEEP,	'A',
927 	TS_XCLUDE,	'X',
928 	TS_TTSTOP,	'S',
929 	TS_HUPCLS,	'H',
930 	TS_TBLOCK,	'K',
931 	TS_RCOLL,	'R',
932 	TS_WCOLL,	'I',	/* running short on letters ! */
933 	TS_ASYNC,	'Y',
934 	TS_BKSL,	'D',
935 	TS_ERASE,	'E',
936 	TS_LNCH,	'L',
937 	TS_TYPEN,	'P',
938 	TS_CNTTB,	'N',
939 	0,	0
940 };
941 
942 ttyprt(atp, line)
943 struct tty *atp;
944 {
945 	register struct tty *tp;
946 	char state[20];
947 	register i, j;
948 	char *name;
949 	extern char *devname();
950 	pid_t pgid;
951 
952 	tp = atp;
953 	if (nflg || tp->t_dev == 0 || 	/* XXX */
954 	   (name = devname(tp->t_dev, S_IFCHR)) == NULL)
955 		printf("%7d ", line);
956 	else
957 		printf("%7s ", name);
958 	printf("%2d %3d ", tp->t_rawq.c_cc, tp->t_canq.c_cc);
959 	printf("%3d %4d %3d %8x %3d ", tp->t_outq.c_cc,
960 		tp->t_hiwat, tp->t_lowat, tp->t_addr, tp->t_col);
961 	for (i = j = 0; ttystates[i].flag; i++)
962 		if (tp->t_state&ttystates[i].flag)
963 			state[j++] = ttystates[i].val;
964 	if (j == 0)
965 		state[j++] = '-';
966 	state[j] = '\0';
967 	printf("%-4s %6x", state, (u_long)tp->t_session & ~KERNBASE);
968 	if (tp->t_pgrp == NULL || kvm_read(&tp->t_pgrp->pg_id, &pgid,
969 	    sizeof (pid_t)) != sizeof (pid_t))
970 		pgid = 0;
971 	printf("%6d ", pgid);
972 	switch (tp->t_line) {
973 
974 	case TTYDISC:
975 		printf("term\n");
976 		break;
977 
978 	case TABLDISC:
979 		printf("tab\n");
980 		break;
981 
982 	case SLIPDISC:
983 		printf("slip\n");
984 		break;
985 
986 	default:
987 		printf("%d\n", tp->t_line);
988 	}
989 }
990 
991 /*
992  * The user structure is going away.  What's left here won't
993  * be around for long.
994  */
995 dousr()
996 {
997 	register struct user *up;
998 	register i, j, *ip;
999 	register struct nameidata *nd;
1000 	struct proc *p;
1001 	int ret;
1002 
1003 	if ((ret = kvm_getprocs(KINFO_PROC_PID, upid)) != 1) {
1004 		if (ret == -1)
1005 			error("kvm_getproc: %s", kvm_geterr());
1006 		else
1007 			error("can't locate process %d", upid);
1008 		return (1);
1009 	}
1010 	if ((p = kvm_nextproc()) == NULL) {
1011 		error("kvm_nextproc: %s", kvm_geterr());
1012 		return (1);
1013 	}
1014 	if ((up = kvm_getu(p)) == NULL) {
1015 		error("kvm_getu: %s", kvm_geterr());
1016 		return (1);
1017 	}
1018 	nd = &up->u_nd;
1019 	printf("pcb");
1020 	ip = (int *)&up->u_pcb;
1021 	i = 0;
1022 	while (ip < (int *)((char *)&up->u_pcb + sizeof (struct pcb))) {
1023 		if (i%4 == 0)
1024 			putchar('\t');
1025 		printf("%#10x ", *ip++);
1026 		if (i%4 == 3)
1027 			putchar('\n');
1028 		i++;
1029 	}
1030 	if (i%4)
1031 		putchar('\n');
1032 	printf("procp\t%#x\n", up->u_procp);
1033 	printf("ar0\t%#x\n", up->u_ar0);
1034 	printf("sizes\ttext %d data %d stack %d\n",
1035 		up->u_tsize, up->u_dsize, up->u_ssize);
1036 	printf("ssave");
1037 	for (i=0; i<sizeof(label_t)/sizeof(int); i++) {
1038 		if (i%5==0)
1039 			printf("\t");
1040 		printf("%#11x", up->u_ssave.val[i]);
1041 		if (i%5==4)
1042 			printf("\n");
1043 	}
1044 	if (i%5)
1045 		printf("\n");
1046 	printf("odsize\t%#x\n", up->u_odsize);
1047 	printf("ossize\t%#x\n", up->u_ossize);
1048 	printf("outime\t%d\n", up->u_outime);
1049 	printf("mmap\t%#x\n", up->u_mmap);
1050 	printf("sigs");
1051 	for (i=0; i<NSIG; i++) {
1052 		if (i % 8 == 0)
1053 			printf("\t");
1054 		printf("%#x ", up->u_signal[i]);
1055 		if (i % 8 == 7)
1056 			printf("\n");
1057 	}
1058 	if (i % 8)
1059 		printf("\n");
1060 	printf("sigmask");
1061 	for (i=0; i<NSIG; i++) {
1062 		if (i % 8 == 0)
1063 			printf("\t");
1064 		printf("%#x ", up->u_sigmask[i]);
1065 		if (i % 8 == 7)
1066 			printf("\n");
1067 	}
1068 	if (i % 8)
1069 		printf("\n");
1070 	printf("sigonstack\t%#x\n", up->u_sigonstack);
1071 	printf("sigintr\t%#x\n", up->u_sigintr);
1072 	printf("oldmask\t%#x\n", up->u_oldmask);
1073 	printf("sigstack\t%#x %#x\n",
1074 		up->u_sigstack.ss_sp, up->u_sigstack.ss_onstack);
1075 	printf("sig\t%#x\n", up->u_sig);
1076 	printf("code\t%#x\n", up->u_code);
1077 	printf("start\t%ld secs %ld usecs\n",
1078 		up->u_start.tv_sec, up->u_start.tv_usec);
1079 	printf("acflag\t%#x\n", up->u_acflag);
1080 	printf("prof\t%#x %#x %#x %#x\n", up->u_prof.pr_base, up->u_prof.pr_size,
1081 	    up->u_prof.pr_off, up->u_prof.pr_scale);
1082 	printf("ru\t");
1083 	ip = (int *)&up->u_ru;
1084 	for (i = 0; i < sizeof(up->u_ru)/sizeof(int); i++)
1085 		printf("%ld ", ip[i]);
1086 	printf("\n");
1087 	ip = (int *)&up->u_cru;
1088 	printf("cru\t");
1089 	for (i = 0; i < sizeof(up->u_cru)/sizeof(int); i++)
1090 		printf("%ld ", ip[i]);
1091 	printf("\n");
1092 }
1093 
1094 oatoi(s)
1095 char *s;
1096 {
1097 	register v;
1098 
1099 	v = 0;
1100 	while (*s)
1101 		v = (v<<3) + *s++ - '0';
1102 	return(v);
1103 }
1104 
1105 dofile()
1106 {
1107 	int nfile;
1108 	struct file *xfile, *afile;
1109 	register struct file *fp;
1110 	register nf;
1111 	int loc;
1112 	static char *dtypes[] = { "???", "inode", "socket" };
1113 
1114 	nf = 0;
1115 	nfile = getword(nl[SNFILE].n_value);
1116 	xfile = (struct file *)calloc(nfile, sizeof (struct file));
1117 	afile = (struct file *)getword(nl[SFIL].n_value);
1118 	if (nfile < 0 || nfile > 100000) {
1119 		fprintf(stderr, "number of files is preposterous (%d)\n",
1120 			nfile);
1121 		return;
1122 	}
1123 	if (xfile == NULL) {
1124 		fprintf(stderr, "can't allocate memory for file table\n");
1125 		return;
1126 	}
1127 	kvm_read(afile, xfile, nfile * sizeof (struct file));
1128 	for (fp=xfile; fp < &xfile[nfile]; fp++)
1129 		if (fp->f_count)
1130 			nf++;
1131 	if (totflg) {
1132 		printf("%3d/%3d files\n", nf, nfile);
1133 		return;
1134 	}
1135 	printf("%d/%d open files\n", nf, nfile);
1136 	printf("   LOC   TYPE    FLG     CNT  MSG    DATA    OFFSET\n");
1137 	for (fp=xfile,loc=(int)afile; fp < &xfile[nfile]; fp++,loc+=sizeof(xfile[0])) {
1138 		if (fp->f_count==0)
1139 			continue;
1140 		printf("%x ", loc);
1141 		if (fp->f_type <= DTYPE_SOCKET)
1142 			printf("%-8.8s", dtypes[fp->f_type]);
1143 		else
1144 			printf("%8d", fp->f_type);
1145 		putf(fp->f_flag&FREAD, 'R');
1146 		putf(fp->f_flag&FWRITE, 'W');
1147 		putf(fp->f_flag&FAPPEND, 'A');
1148 		putf(fp->f_flag&FSHLOCK, 'S');
1149 		putf(fp->f_flag&FEXLOCK, 'X');
1150 		putf(fp->f_flag&FASYNC, 'I');
1151 		printf("  %3d", mask(fp->f_count));
1152 		printf("  %3d", mask(fp->f_msgcount));
1153 		printf("  %8.1x", fp->f_data);
1154 		if (fp->f_offset < 0)
1155 			printf("  %x\n", fp->f_offset);
1156 		else
1157 			printf("  %ld\n", fp->f_offset);
1158 	}
1159 	free(xfile);
1160 }
1161 
1162 int dmmin, dmmax, nswdev;
1163 
1164 doswap()
1165 {
1166 	struct proc *proc;
1167 	int nproc;
1168 	struct text *xtext;
1169 	int ntext;
1170 	struct map *swapmap;
1171 	int nswapmap;
1172 	struct swdevt *swdevt, *sw;
1173 	register struct proc *pp;
1174 	int nswap, used, tused, free, waste;
1175 	int db, sb;
1176 	register struct mapent *me;
1177 	register struct text *xp;
1178 	int i, j;
1179 	long rmalloc();
1180 
1181 	nproc = getword(nl[SNPROC].n_value);
1182 	ntext = getword(nl[SNTEXT].n_value);
1183 	if (nproc < 0 || nproc > 10000 || ntext < 0 || ntext > 10000) {
1184 		fprintf(stderr, "number of procs/texts is preposterous (%d, %d)\n",
1185 			nproc, ntext);
1186 		return;
1187 	}
1188 	proc = (struct proc *)calloc(nproc, sizeof (struct proc));
1189 	if (proc == NULL) {
1190 		fprintf(stderr, "can't allocate memory for proc table\n");
1191 		exit(1);
1192 	}
1193 	xtext = (struct text *)calloc(ntext, sizeof (struct text));
1194 	if (xtext == NULL) {
1195 		fprintf(stderr, "can't allocate memory for text table\n");
1196 		exit(1);
1197 	}
1198 	nswapmap = getword(nl[SNSWAPMAP].n_value);
1199 	swapmap = (struct map *)calloc(nswapmap, sizeof (struct map));
1200 	if (swapmap == NULL) {
1201 		fprintf(stderr, "can't allocate memory for swapmap\n");
1202 		exit(1);
1203 	}
1204 	nswdev = getword(nl[SNSWDEV].n_value);
1205 	swdevt = (struct swdevt *)calloc(nswdev, sizeof (struct swdevt));
1206 	if (swdevt == NULL) {
1207 		fprintf(stderr, "can't allocate memory for swdevt table\n");
1208 		exit(1);
1209 	}
1210 	kvm_read(V(nl[SSWDEVT].n_value), swdevt,
1211 		nswdev * sizeof (struct swdevt));
1212 	kvm_read(V(getword(nl[SPROC].n_value)), proc,
1213 		nproc * sizeof (struct proc));
1214 	kvm_read(V(getword(nl[STEXT].n_value)), xtext,
1215 		ntext * sizeof (struct text));
1216 	kvm_read(V(getword(nl[SWAPMAP].n_value)), swapmap,
1217 		nswapmap * sizeof (struct map));
1218 
1219 	swapmap->m_name = "swap";
1220 	swapmap->m_limit = (struct mapent *)&swapmap[nswapmap];
1221 	dmmin = getword(nl[SDMMIN].n_value);
1222 	dmmax = getword(nl[SDMMAX].n_value);
1223 	nswap = 0;
1224 	for (sw = swdevt; sw < &swdevt[nswdev]; sw++)
1225 		if (sw->sw_freed)
1226 			nswap += sw->sw_nblks;
1227 	free = 0;
1228 	for (me = (struct mapent *)(swapmap+1);
1229 	    me < (struct mapent *)&swapmap[nswapmap]; me++)
1230 		free += me->m_size;
1231 	tused = 0;
1232 	for (xp = xtext; xp < &xtext[ntext]; xp++)
1233 		if (xp->x_vptr!=NULL) {
1234 			tused += ctod(clrnd(xp->x_size));
1235 			if (xp->x_flag & XPAGV)
1236 				tused += ctod(clrnd(ctopt(xp->x_size)));
1237 		}
1238 	used = tused;
1239 	waste = 0;
1240 	for (pp = proc; pp < &proc[nproc]; pp++) {
1241 		if (pp->p_stat == 0 || pp->p_stat == SZOMB)
1242 			continue;
1243 		if (pp->p_flag & SSYS)
1244 			continue;
1245 		db = ctod(pp->p_dsize), sb = up(db);
1246 		used += sb;
1247 		waste += sb - db;
1248 		db = ctod(pp->p_ssize), sb = up(db);
1249 		used += sb;
1250 		waste += sb - db;
1251 		if ((pp->p_flag&SLOAD) == 0)
1252 			used += ctod(vusize(pp));
1253 	}
1254 	if (totflg) {
1255 #define	btok(x)	((x) / (1024 / DEV_BSIZE))
1256 		printf("%3d/%3d 00k swap\n",
1257 		    btok(used/100), btok((used+free)/100));
1258 		return;
1259 	}
1260 	printf("%dk used (%dk text), %dk free, %dk wasted, %dk missing\n",
1261 	    btok(used), btok(tused), btok(free), btok(waste),
1262 /* a dmmax/2 block goes to argmap */
1263 	    btok(nswap - dmmax/2 - (used + free)));
1264 	printf("avail: ");
1265 	for (i = dmmax; i >= dmmin; i /= 2) {
1266 		j = 0;
1267 		while (rmalloc(swapmap, i) != 0)
1268 			j++;
1269 		if (j) printf("%d*%dk ", j, btok(i));
1270 	}
1271 	free = 0;
1272 	for (me = (struct mapent *)(swapmap+1);
1273 	    me < (struct mapent *)&swapmap[nswapmap]; me++)
1274 		free += me->m_size;
1275 	printf("%d*1k\n", btok(free));
1276 }
1277 
1278 up(size)
1279 	register int size;
1280 {
1281 	register int i, block;
1282 
1283 	i = 0;
1284 	block = dmmin;
1285 	while (i < size) {
1286 		i += block;
1287 		if (block < dmmax)
1288 			block *= 2;
1289 	}
1290 	return (i);
1291 }
1292 
1293 /*
1294  * Compute number of pages to be allocated to the u. area
1295  * and data and stack area page tables, which are stored on the
1296  * disk immediately after the u. area.
1297  */
1298 vusize(p)
1299 	register struct proc *p;
1300 {
1301 	register int tsz = p->p_tsize / NPTEPG;
1302 
1303 	/*
1304 	 * We do not need page table space on the disk for page
1305 	 * table pages wholly containing text.
1306 	 */
1307 	return (clrnd(UPAGES +
1308 	    clrnd(ctopt(p->p_tsize+p->p_dsize+p->p_ssize+UPAGES)) - tsz));
1309 }
1310 
1311 /*
1312  * Allocate 'size' units from the given
1313  * map. Return the base of the allocated space.
1314  * In a map, the addresses are increasing and the
1315  * list is terminated by a 0 size.
1316  *
1317  * Algorithm is first-fit.
1318  *
1319  * This routine knows about the interleaving of the swapmap
1320  * and handles that.
1321  */
1322 long
1323 rmalloc(mp, size)
1324 	register struct map *mp;
1325 	long size;
1326 {
1327 	register struct mapent *ep = (struct mapent *)(mp+1);
1328 	register int addr;
1329 	register struct mapent *bp;
1330 	swblk_t first, rest;
1331 
1332 	if (size <= 0 || size > dmmax)
1333 		return (0);
1334 	/*
1335 	 * Search for a piece of the resource map which has enough
1336 	 * free space to accomodate the request.
1337 	 */
1338 	for (bp = ep; bp->m_size; bp++) {
1339 		if (bp->m_size >= size) {
1340 			/*
1341 			 * If allocating from swapmap,
1342 			 * then have to respect interleaving
1343 			 * boundaries.
1344 			 */
1345 			if (nswdev > 1 &&
1346 			    (first = dmmax - bp->m_addr%dmmax) < bp->m_size) {
1347 				if (bp->m_size - first < size)
1348 					continue;
1349 				addr = bp->m_addr + first;
1350 				rest = bp->m_size - first - size;
1351 				bp->m_size = first;
1352 				if (rest)
1353 					rmfree(mp, rest, addr+size);
1354 				return (addr);
1355 			}
1356 			/*
1357 			 * Allocate from the map.
1358 			 * If there is no space left of the piece
1359 			 * we allocated from, move the rest of
1360 			 * the pieces to the left.
1361 			 */
1362 			addr = bp->m_addr;
1363 			bp->m_addr += size;
1364 			if ((bp->m_size -= size) == 0) {
1365 				do {
1366 					bp++;
1367 					(bp-1)->m_addr = bp->m_addr;
1368 				} while ((bp-1)->m_size = bp->m_size);
1369 			}
1370 			if (addr % CLSIZE)
1371 				return (0);
1372 			return (addr);
1373 		}
1374 	}
1375 	return (0);
1376 }
1377 
1378 /*
1379  * Free the previously allocated space at addr
1380  * of size units into the specified map.
1381  * Sort addr into map and combine on
1382  * one or both ends if possible.
1383  */
1384 rmfree(mp, size, addr)
1385 	struct map *mp;
1386 	long size, addr;
1387 {
1388 	struct mapent *firstbp;
1389 	register struct mapent *bp;
1390 	register int t;
1391 
1392 	/*
1393 	 * Both address and size must be
1394 	 * positive, or the protocol has broken down.
1395 	 */
1396 	if (addr <= 0 || size <= 0)
1397 		goto badrmfree;
1398 	/*
1399 	 * Locate the piece of the map which starts after the
1400 	 * returned space (or the end of the map).
1401 	 */
1402 	firstbp = bp = (struct mapent *)(mp + 1);
1403 	for (; bp->m_addr <= addr && bp->m_size != 0; bp++)
1404 		continue;
1405 	/*
1406 	 * If the piece on the left abuts us,
1407 	 * then we should combine with it.
1408 	 */
1409 	if (bp > firstbp && (bp-1)->m_addr+(bp-1)->m_size >= addr) {
1410 		/*
1411 		 * Check no overlap (internal error).
1412 		 */
1413 		if ((bp-1)->m_addr+(bp-1)->m_size > addr)
1414 			goto badrmfree;
1415 		/*
1416 		 * Add into piece on the left by increasing its size.
1417 		 */
1418 		(bp-1)->m_size += size;
1419 		/*
1420 		 * If the combined piece abuts the piece on
1421 		 * the right now, compress it in also,
1422 		 * by shifting the remaining pieces of the map over.
1423 		 */
1424 		if (bp->m_addr && addr+size >= bp->m_addr) {
1425 			if (addr+size > bp->m_addr)
1426 				goto badrmfree;
1427 			(bp-1)->m_size += bp->m_size;
1428 			while (bp->m_size) {
1429 				bp++;
1430 				(bp-1)->m_addr = bp->m_addr;
1431 				(bp-1)->m_size = bp->m_size;
1432 			}
1433 		}
1434 		goto done;
1435 	}
1436 	/*
1437 	 * Don't abut on the left, check for abutting on
1438 	 * the right.
1439 	 */
1440 	if (addr+size >= bp->m_addr && bp->m_size) {
1441 		if (addr+size > bp->m_addr)
1442 			goto badrmfree;
1443 		bp->m_addr -= size;
1444 		bp->m_size += size;
1445 		goto done;
1446 	}
1447 	/*
1448 	 * Don't abut at all.  Make a new entry
1449 	 * and check for map overflow.
1450 	 */
1451 	do {
1452 		t = bp->m_addr;
1453 		bp->m_addr = addr;
1454 		addr = t;
1455 		t = bp->m_size;
1456 		bp->m_size = size;
1457 		bp++;
1458 	} while (size = t);
1459 	/*
1460 	 * Segment at bp is to be the delimiter;
1461 	 * If there is not room for it
1462 	 * then the table is too full
1463 	 * and we must discard something.
1464 	 */
1465 	if (bp+1 > mp->m_limit) {
1466 		/*
1467 		 * Back bp up to last available segment.
1468 		 * which contains a segment already and must
1469 		 * be made into the delimiter.
1470 		 * Discard second to last entry,
1471 		 * since it is presumably smaller than the last
1472 		 * and move the last entry back one.
1473 		 */
1474 		bp--;
1475 		printf("%s: rmap ovflo, lost [%d,%d)\n", mp->m_name,
1476 		    (bp-1)->m_addr, (bp-1)->m_addr+(bp-1)->m_size);
1477 		bp[-1] = bp[0];
1478 		bp[0].m_size = bp[0].m_addr = 0;
1479 	}
1480 done:
1481 	return;
1482 badrmfree:
1483 	printf("bad rmfree\n");
1484 }
1485 
1486 #include <varargs.h>
1487 
1488 error(va_alist)
1489 	va_dcl
1490 {
1491 	char *fmt;
1492 	va_list ap;
1493 	extern errno;
1494 
1495 	fprintf(stderr, "%s: ", Program);
1496 	va_start(ap);
1497 	fmt = va_arg(ap, char *);
1498 	(void) vfprintf(stderr, fmt, ap);
1499 	va_end(ap);
1500 	fprintf(stderr, "\n");
1501 }
1502 
1503 syserror(va_alist)
1504 	va_dcl
1505 {
1506 	char *fmt;
1507 	va_list ap;
1508 	extern errno;
1509 
1510 	fprintf(stderr, "%s: ", Program);
1511 	va_start(ap);
1512 	fmt = va_arg(ap, char *);
1513 	(void) vfprintf(stderr, fmt, ap);
1514 	va_end(ap);
1515 	fprintf(stderr, ": %s\n", strerror(errno));
1516 }
1517