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