xref: /original-bsd/usr.sbin/pstat/pstat.c (revision 6b7db209)
1 #ifndef lint
2 static char *sccsid = "@(#) (Berkeley) 82/12/24";
3 #endif
4 /*
5  * Print system stuff
6  */
7 
8 #define mask(x) (x&0377)
9 #define	clear(x) ((int)x&0x7fffffff)
10 
11 #include <sys/param.h>
12 #include <sys/dir.h>
13 #define	KERNEL
14 #include <sys/file.h>
15 #undef	KERNEL
16 #include <sys/user.h>
17 #include <sys/proc.h>
18 #include <sys/text.h>
19 #include <sys/inode.h>
20 #include <sys/map.h>
21 #include <sys/ioctl.h>
22 #include <sys/tty.h>
23 #include <sys/conf.h>
24 #include <sys/vm.h>
25 #include <nlist.h>
26 #include <machine/pte.h>
27 #include <sys/descrip.h>
28 
29 char	*fcore	= "/dev/kmem";
30 char	*fnlist	= "/vmunix";
31 int	fc;
32 
33 struct nlist nl[] = {
34 #define	SINODE	0
35 	{ "_inode" },
36 #define	STEXT	1
37 	{ "_text" },
38 #define	SPROC	2
39 	{ "_proc" },
40 #define	SDZ	3
41 	{ "_dz_tty" },
42 #define	SNDZ	4
43 	{ "_dz_cnt" },
44 #define	SKL	5
45 	{ "_cons" },
46 #define	SFIL	6
47 	{ "_file" },
48 #define	USRPTMA	7
49 	{ "_Usrptmap" },
50 #define	USRPT	8
51 	{ "_usrpt" },
52 #define	SNSWAP	9
53 	{ "_nswap" },
54 #define	SWAPMAP	10
55 	{ "_swapmap" },
56 #define	SDH	11
57 	{ "_dh11" },
58 #define	SNDH	12
59 	{ "_ndh11" },
60 #define	SNPROC	13
61 	{ "_nproc" },
62 #define	SNTEXT	14
63 	{ "_ntext" },
64 #define	SNFILE	15
65 	{ "_nfile" },
66 #define	SNINODE	16
67 	{ "_ninode" },
68 #define	SNSWAPMAP 17
69 	{ "_nswapmap" },
70 #define	SPTY	18
71 	{ "_pt_tty" },
72 	0,
73 };
74 
75 int	inof;
76 int	txtf;
77 int	prcf;
78 int	ttyf;
79 int	usrf;
80 long	ubase;
81 int	filf;
82 int	swpf;
83 int	totflg;
84 char	partab[1];
85 struct	cdevsw	cdevsw[1];
86 struct	bdevsw	bdevsw[1];
87 int	allflg;
88 int	kflg;
89 struct	pte *Usrptma;
90 struct	pte *usrpt;
91 
92 main(argc, argv)
93 char **argv;
94 {
95 	register char *argp;
96 	int allflags;
97 
98 	argc--, argv++;
99 	while (argc > 0 && **argv == '-') {
100 		argp = *argv++;
101 		argp++;
102 		argc--;
103 		while (*argp++)
104 		switch (argp[-1]) {
105 
106 		case 'T':
107 			totflg++;
108 			break;
109 
110 		case 'a':
111 			allflg++;
112 			break;
113 
114 		case 'i':
115 			inof++;
116 			break;
117 
118 		case 'k':
119 			kflg++;
120 			fcore = "/vmcore";
121 			break;
122 
123 		case 'x':
124 			txtf++;
125 			break;
126 
127 		case 'p':
128 			prcf++;
129 			break;
130 
131 		case 't':
132 			ttyf++;
133 			break;
134 
135 		case 'u':
136 			if (argc == 0)
137 				break;
138 			argc--;
139 			usrf++;
140 			sscanf( *argv++, "%x", &ubase);
141 			break;
142 
143 		case 'f':
144 			filf++;
145 			break;
146 		case 's':
147 			swpf++;
148 			break;
149 		default:
150 			usage();
151 			exit(1);
152 		}
153 	}
154 	if (argc>1)
155 		fcore = argv[1];
156 	if ((fc = open(fcore, 0)) < 0) {
157 		printf("Can't find %s\n", fcore);
158 		exit(1);
159 	}
160 	if (argc>0)
161 		fnlist = argv[0];
162 	nlist(fnlist, nl);
163 	usrpt = (struct pte *)nl[USRPT].n_value;
164 	Usrptma = (struct pte *)nl[USRPTMA].n_value;
165 	if (nl[0].n_type == 0) {
166 		printf("no namelist\n");
167 		exit(1);
168 	}
169 	allflags = filf | totflg | inof | prcf | txtf | ttyf | usrf | swpf;
170 	if (allflags == 0) {
171 		printf("pstat: one or more of -[aixptfsu] is required\n");
172 		exit(1);
173 	}
174 	if (filf||totflg)
175 		dofile();
176 	if (inof||totflg)
177 		doinode();
178 	if (prcf||totflg)
179 		doproc();
180 	if (txtf||totflg)
181 		dotext();
182 	if (ttyf)
183 		dotty();
184 	if (usrf)
185 		dousr();
186 	if (swpf||totflg)
187 		doswap();
188 }
189 
190 usage()
191 {
192 
193 	printf("usage: pstat -[aixptfs] [-u [ubase]] [system] [core]\n");
194 }
195 
196 doinode()
197 {
198 	register struct inode *ip;
199 	struct inode *xinode, *ainode;
200 	register int nin;
201 	int ninode;
202 
203 	nin = 0;
204 	ninode = getw(nl[SNINODE].n_value);
205 	xinode = (struct inode *)calloc(ninode, sizeof (struct inode));
206 	lseek(fc, (int)(ainode = (struct inode *)getw(nl[SINODE].n_value)), 0);
207 	read(fc, xinode, ninode * sizeof(struct inode));
208 	for (ip = xinode; ip < &xinode[ninode]; ip++)
209 		if (ip->i_count)
210 			nin++;
211 	if (totflg) {
212 		printf("%3d/%3d inodes\n", nin, ninode);
213 		return;
214 	}
215 	printf("%d/%d active inodes\n", nin, ninode);
216 printf("   LOC      FLAGS    CNT DEVICE  RDC WRC  INO  MODE  NLK UID   SIZE/DEV\n");
217 	for (ip = xinode; ip < &xinode[ninode]; ip++) {
218 		if (ip->i_count == 0)
219 			continue;
220 		printf("%8.1x ", ainode + (ip - xinode));
221 		putf(ip->i_flag&ILOCKED, 'L');
222 		putf(ip->i_flag&IUPD, 'U');
223 		putf(ip->i_flag&IACC, 'A');
224 		putf(ip->i_flag&IMOUNT, 'M');
225 		putf(ip->i_flag&IWANT, 'W');
226 		putf(ip->i_flag&ITEXT, 'T');
227 		putf(ip->i_flag&ICHG, 'C');
228 		putf(ip->i_flag&ISHLOCK, 'S');
229 		putf(ip->i_flag&IEXLOCK, 'E');
230 		putf(ip->i_flag&ILWAIT, 'Z');
231 		printf("%4d", ip->i_count&0377);
232 		printf("%4d,%3d", major(ip->i_dev), minor(ip->i_dev));
233 		printf("%4d", ip->i_shlockc&0377);
234 		printf("%4d", ip->i_exlockc&0377);
235 		printf("%6d", ip->i_number);
236 		printf("%6x", ip->i_mode & 0xffff);
237 		printf("%4d", ip->i_nlink);
238 		printf("%4d", ip->i_uid);
239 		if ((ip->i_mode&IFMT)==IFBLK || (ip->i_mode&IFMT)==IFCHR)
240 			printf("%6d,%3d", major(ip->i_rdev), minor(ip->i_rdev));
241 		else
242 			printf("%10ld", ip->i_size);
243 		printf("\n");
244 	}
245 	free(xinode);
246 }
247 
248 getw(loc)
249 	off_t loc;
250 {
251 	int word;
252 
253 	if (kflg)
254 		loc &= 0x7fffffff;
255 	lseek(fc, loc, 0);
256 	read(fc, &word, sizeof (word));
257 	if (kflg)
258 		word &= 0x7fffffff;
259 	return (word);
260 }
261 
262 putf(v, n)
263 {
264 	if (v)
265 		printf("%c", n);
266 	else
267 		printf(" ");
268 }
269 
270 dotext()
271 {
272 	register struct text *xp;
273 	int ntext;
274 	struct text *xtext, *atext;
275 	int ntx;
276 
277 	ntx = 0;
278 	ntext = getw(nl[SNTEXT].n_value);
279 	xtext = (struct text *)calloc(ntext, sizeof (struct text));
280 	lseek(fc, (int)(atext = (struct text *)getw(nl[STEXT].n_value)), 0);
281 	read(fc, xtext, ntext * sizeof (struct text));
282 	for (xp = xtext; xp < &xtext[ntext]; xp++)
283 		if (xp->x_iptr!=NULL)
284 			ntx++;
285 	if (totflg) {
286 		printf("%3d/%3d texts\n", ntx, ntext);
287 		return;
288 	}
289 	printf("%d/%d active texts\n", ntx, ntext);
290 	printf("   LOC   FLAGS DADDR      CADDR  RSS SIZE      IPTR  CNT CCNT\n");
291 	for (xp = xtext; xp < &xtext[ntext]; xp++) {
292 		if (xp->x_iptr == NULL)
293 			continue;
294 		printf("%8.1x", atext + (xp - xtext));
295 		printf(" ");
296 		putf(xp->x_flag&XPAGI, 'P');
297 		putf(xp->x_flag&XTRC, 'T');
298 		putf(xp->x_flag&XWRIT, 'W');
299 		putf(xp->x_flag&XLOAD, 'L');
300 		putf(xp->x_flag&XLOCK, 'K');
301 		putf(xp->x_flag&XWANT, 'w');
302 		printf("%5x", xp->x_daddr[0]);
303 		printf("%11x", xp->x_caddr);
304 		printf("%5d", xp->x_rssize);
305 		printf("%5d", xp->x_size);
306 		printf("%10.1x", xp->x_iptr);
307 		printf("%5d", xp->x_count&0377);
308 		printf("%5d", xp->x_ccount);
309 		printf("\n");
310 	}
311 	free(xtext);
312 }
313 
314 doproc()
315 {
316 	struct proc *xproc, *aproc;
317 	int nproc;
318 	register struct proc *pp;
319 	register loc, np;
320 	struct pte apte;
321 
322 	nproc = getw(nl[SNPROC].n_value);
323 	xproc = (struct proc *)calloc(nproc, sizeof (struct proc));
324 	lseek(fc, (int)(aproc = (struct proc *)getw(nl[SPROC].n_value)), 0);
325 	read(fc, xproc, nproc * sizeof (struct proc));
326 	np = 0;
327 	for (pp=xproc; pp < &xproc[nproc]; pp++)
328 		if (pp->p_stat)
329 			np++;
330 	if (totflg) {
331 		printf("%3d/%3d processes\n", np, nproc);
332 		return;
333 	}
334 	printf("%d/%d processes\n", np, nproc);
335 	printf("   LOC    S    F POIP PRI      SIG  UID SLP TIM  CPU  NI   PGRP    PID   PPID    ADDR   RSS SRSS SIZE    WCHAN    LINK   TEXTP CLKT\n");
336 	for (pp=xproc; pp<&xproc[nproc]; pp++) {
337 		if (pp->p_stat==0 && allflg==0)
338 			continue;
339 		printf("%8x", aproc + (pp - xproc));
340 		printf(" %2d", pp->p_stat);
341 		printf(" %4x", pp->p_flag & 0xffff);
342 		printf(" %4d", pp->p_poip);
343 		printf(" %3d", pp->p_pri);
344 		printf(" %8x", pp->p_sig);
345 		printf(" %4d", pp->p_uid);
346 		printf(" %3d", pp->p_slptime);
347 		printf(" %3d", pp->p_time);
348 		printf(" %4d", pp->p_cpu&0377);
349 		printf(" %3d", pp->p_nice);
350 		printf(" %6d", pp->p_pgrp);
351 		printf(" %6d", pp->p_pid);
352 		printf(" %6d", pp->p_ppid);
353 		if (kflg)
354 			pp->p_addr = (struct pte *)clear((int)pp->p_addr);
355 		lseek(fc, (long)(Usrptma+btokmx(pp->p_addr)), 0);
356 		read(fc, &apte, sizeof(apte));
357 		printf(" %8x", ctob(apte.pg_pfnum+1) - sizeof(struct pte) * UPAGES);
358 		printf(" %4x", pp->p_rssize);
359 		printf(" %4x", pp->p_swrss);
360 		printf(" %5x", pp->p_dsize+pp->p_ssize);
361 		printf(" %7x", clear(pp->p_wchan));
362 		printf(" %7x", clear(pp->p_link));
363 		printf(" %7x", clear(pp->p_textp));
364 		printf("\n");
365 	}
366 }
367 
368 dotty()
369 {
370 	struct tty dz_tty[128];
371 	int ndz;
372 	register struct tty *tp;
373 	register char *mesg;
374 
375 	printf("1 cons\n");
376 	if (kflg)
377 		nl[SKL].n_value = clear(nl[SKL].n_value);
378 	lseek(fc, (long)nl[SKL].n_value, 0);
379 	read(fc, dz_tty, sizeof(dz_tty[0]));
380 	mesg = " # RAW CAN OUT   MODE    ADDR   DEL COL  STATE   PGRP DISC\n";
381 	printf(mesg);
382 	ttyprt(&dz_tty[0], 0);
383 	if (nl[SNDZ].n_type == 0)
384 		goto dh;
385 	if (kflg) {
386 		nl[SNDZ].n_value = clear(nl[SNDZ].n_value);
387 		nl[SDZ].n_value = clear(nl[SDZ].n_value);
388 	}
389 	lseek(fc, (long)nl[SNDZ].n_value, 0);
390 	read(fc, &ndz, sizeof(ndz));
391 	printf("%d dz lines\n", ndz);
392 	lseek(fc, (long)nl[SDZ].n_value, 0);
393 	read(fc, dz_tty, ndz * sizeof (struct tty));
394 	for (tp = dz_tty; tp < &dz_tty[ndz]; tp++)
395 		ttyprt(tp, tp - dz_tty);
396 dh:
397 	if (nl[SNDH].n_type == 0)
398 		goto pty;
399 	if (kflg) {
400 		nl[SNDH].n_value = clear(nl[SNDH].n_value);
401 		nl[SDH].n_value = clear(nl[SDH].n_value);
402 	}
403 	lseek(fc, (long)nl[SNDH].n_value, 0);
404 	read(fc, &ndz, sizeof(ndz));
405 	printf("%d dh lines\n", ndz);
406 	lseek(fc, (long)nl[SDH].n_value, 0);
407 	read(fc, dz_tty, ndz * sizeof(struct tty));
408 	for (tp = dz_tty; tp < &dz_tty[ndz]; tp++)
409 		ttyprt(tp, tp - dz_tty);
410 pty:
411 	if (nl[SPTY].n_type == 0)
412 		goto pty;
413 	if (kflg) {
414 		nl[SPTY].n_value = clear(nl[SPTY].n_value);
415 	}
416 	printf("32 pty lines\n");
417 	lseek(fc, (long)nl[SPTY].n_value, 0);
418 	read(fc, dz_tty, 32*sizeof(struct tty));
419 	for (tp = dz_tty; tp < &dz_tty[32]; tp++)
420 		ttyprt(tp, tp - dz_tty);
421 }
422 
423 ttyprt(atp, line)
424 struct tty *atp;
425 {
426 	register struct tty *tp;
427 
428 	printf("%2d", line);
429 	tp = atp;
430 	switch (tp->t_line) {
431 
432 /*
433 	case NETLDISC:
434 		if (tp->t_rec)
435 			printf("%4d%4d", 0, tp->t_inbuf);
436 		else
437 			printf("%4d%4d", tp->t_inbuf, 0);
438 		break;
439 */
440 
441 	default:
442 		printf("%4d", tp->t_rawq.c_cc);
443 		printf("%4d", tp->t_canq.c_cc);
444 	}
445 	printf("%4d", tp->t_outq.c_cc);
446 	printf("%8.1x", tp->t_flags);
447 	printf(" %8.1x", tp->t_addr);
448 	printf("%3d", tp->t_delct);
449 	printf("%4d ", tp->t_col);
450 	putf(tp->t_state&TS_TIMEOUT, 'T');
451 	putf(tp->t_state&TS_WOPEN, 'W');
452 	putf(tp->t_state&TS_ISOPEN, 'O');
453 	putf(tp->t_state&TS_CARR_ON, 'C');
454 	putf(tp->t_state&TS_BUSY, 'B');
455 	putf(tp->t_state&TS_ASLEEP, 'A');
456 	putf(tp->t_state&TS_XCLUDE, 'X');
457 	putf(tp->t_state&TS_HUPCLS, 'H');
458 	printf("%6d", tp->t_pgrp);
459 	switch (tp->t_line) {
460 
461 	case NTTYDISC:
462 		printf(" ntty");
463 		break;
464 
465 	case NETLDISC:
466 		printf(" net");
467 		break;
468 	}
469 	printf("\n");
470 }
471 
472 dousr()
473 {
474 	struct user U;
475 	register i, j, *ip;
476 
477 	/* This wins only if PAGSIZ > sizeof (struct user) */
478 	lseek(fc, ubase * NBPG, 0);
479 	read(fc, &U, sizeof(U));
480 	printf("pcb");
481 	ip = (int *)&U.u_pcb;
482 	while (ip < &U.u_arg[0]) {
483 		if ((ip - (int *)&U.u_pcb) % 4 == 0)
484 			printf("\t");
485 		printf("%x ", *ip++);
486 		if ((ip - (int *)&U.u_pcb) % 4 == 0)
487 			printf("\n");
488 	}
489 	if ((ip - (int *)&U.u_pcb) % 4 != 0)
490 		printf("\n");
491 	printf("arg\t");
492 	for (i=0; i<5; i++)
493 		printf(" %.1x", U.u_arg[i]);
494 	printf("\n");
495 	for (i=0; i<sizeof(label_t)/sizeof(int); i++) {
496 		if (i%5==0)
497 			printf("\t");
498 		printf("%9.1x", U.u_ssave.val[i]);
499 		if (i%5==4)
500 			printf("\n");
501 	}
502 	if (i%5)
503 		printf("\n");
504 	printf("segflg\t%d\nerror %d\n", U.u_segflg, U.u_error);
505 	printf("uids\t%d,%d,%d,%d\n", U.u_uid,U.u_gid,U.u_ruid,U.u_rgid);
506 	printf("procp\t%.1x\n", U.u_procp);
507 	printf("ap\t%.1x\n", U.u_ap);
508 	printf("r_val?\t%.1x %.1x\n", U.u_r.r_val1, U.u_r.r_val2);
509 	printf("base, count, offset %.1x %.1x %ld\n", U.u_base,
510 		U.u_count, U.u_offset);
511 	printf("cdir rdir %.1x %.1x\n", U.u_cdir, U.u_rdir);
512 	printf("dirp %.1x\n", U.u_dirp);
513 	printf("dent %d %.14s\n", U.u_dent.d_ino, U.u_dent.d_name);
514 	printf("pdir %.1o\n", U.u_pdir);
515 	printf("file\t");
516 	for (i=0; i<10; i++)
517 		printf("%9.1x", U.u_ofile[i]);
518 	printf("\n\t");
519 	for (i=10; i<NOFILE; i++)
520 		printf("%9.1x", U.u_ofile[i]);
521 	printf("\n");
522 	printf("pofile\t");
523 	for (i=0; i<10; i++)
524 		printf("%9.1x", U.u_pofile[i]);
525 	printf("\n\t");
526 	for (i=10; i<NOFILE; i++)
527 		printf("%9.1x", U.u_pofile[i]);
528 	printf("\n");
529 	printf("ssave");
530 	for (i=0; i<sizeof(label_t)/sizeof(int); i++) {
531 		if (i%5==0)
532 			printf("\t");
533 		printf("%9.1x", U.u_ssave.val[i]);
534 		if (i%5==4)
535 			printf("\n");
536 	}
537 	if (i%5)
538 		printf("\n");
539 	printf("sigs\t");
540 	for (i=0; i<NSIG; i++)
541 		printf("%.1x ", U.u_signal[i]);
542 	printf("\n");
543 	printf("code\t%.1x\n", U.u_code);
544 	printf("ar0\t%.1x\n", U.u_ar0);
545 	printf("prof\t%X %X %X %X\n", U.u_prof.pr_base, U.u_prof.pr_size,
546 	    U.u_prof.pr_off, U.u_prof.pr_scale);
547 	printf("\neosys\t%d\n", U.u_eosys);
548 	printf("ttyp\t%.1x\n", U.u_ttyp);
549 	printf("ttyd\t%d,%d\n", major(U.u_ttyd), minor(U.u_ttyd));
550 	printf("exdata\t");
551 	ip = (int *)&U.u_exdata;
552 	for (i = 0; i < 8; i++)
553 		printf("%.1D ", *ip++);
554 	printf("\n");
555 	printf("comm %.14s\n", U.u_comm);
556 	printf("start\t%D\n", U.u_start);
557 	printf("acflag\t%D\n", U.u_acflag);
558 	printf("cmask\t%D\n", U.u_cmask);
559 	printf("sizes\t%.1x %.1x %.1x\n", U.u_tsize, U.u_dsize, U.u_ssize);
560 	printf("ru\t");
561 	ip = (int *)&U.u_ru;
562 	for (i = 0; i < sizeof(U.u_ru)/sizeof(int); i++)
563 		printf("%D ", ip[i]);
564 	printf("\n");
565 	ip = (int *)&U.u_cru;
566 	printf("cru\t");
567 	for (i = 0; i < sizeof(U.u_cru)/sizeof(int); i++)
568 		printf("%D ", ip[i]);
569 	printf("\n");
570 /*
571 	i =  U.u_stack - &U;
572 	while (U[++i] == 0);
573 	i &= ~07;
574 	while (i < 512) {
575 		printf("%x ", 0140000+2*i);
576 		for (j=0; j<8; j++)
577 			printf("%9x", U[i++]);
578 		printf("\n");
579 	}
580 */
581 }
582 
583 oatoi(s)
584 char *s;
585 {
586 	register v;
587 
588 	v = 0;
589 	while (*s)
590 		v = (v<<3) + *s++ - '0';
591 	return(v);
592 }
593 
594 dofile()
595 {
596 	int nfile;
597 	struct file *xfile, *afile;
598 	register struct file *fp;
599 	register nf;
600 	int loc;
601 	static char *dtypes[] = {
602 		"???", "kernel", "fsys", "file", "dir", "bdev",
603 		"cdev", "proc", "socket", "domain", "tty"
604 	};
605 
606 	nf = 0;
607 	nfile = getw(nl[SNFILE].n_value);
608 	xfile = (struct file *)calloc(nfile, sizeof (struct file));
609 	lseek(fc, (int)(afile = (struct file *)getw(nl[SFIL].n_value)), 0);
610 	read(fc, xfile, nfile * sizeof (struct file));
611 	for (fp=xfile; fp < &xfile[nfile]; fp++)
612 		if (fp->f_count)
613 			nf++;
614 	if (totflg) {
615 		printf("%3d/%3d files\n", nf, nfile);
616 		return;
617 	}
618 	printf("%d/%d open files\n", nf, nfile);
619 	printf("   LOC   TYPE    FLG  CNT   INO    OFFS|SOCK\n");
620 	for (fp=xfile,loc=(int)afile; fp < &xfile[nfile]; fp++,loc+=sizeof(xfile[0])) {
621 		if (fp->f_count==0)
622 			continue;
623 		printf("%8x ", loc);
624 		if (fp->f_type <= DTYPE_TERMINAL)
625 			printf("%-8.8s", dtypes[fp->f_type]);
626 		else
627 			printf("8d", fp->f_type);
628 		putf(fp->f_flag&FREAD, 'R');
629 		putf(fp->f_flag&FWRITE, 'W');
630 		putf(fp->f_flag&FAPPEND, 'A');
631 		printf("%4d", mask(fp->f_count));
632 		printf("%9.1x", fp->f_inode);
633 		if (fp->f_type == DTYPE_SOCKET)
634 			printf("  %x\n", fp->f_socket);
635 		else
636 			printf("  %ld\n", fp->f_offset);
637 	}
638 }
639 
640 doswap()
641 {
642 	struct proc *proc;
643 	int nproc;
644 	struct text *xtext;
645 	int ntext;
646 	struct map *swapmap;
647 	int nswapmap;
648 	register struct proc *pp;
649 	int nswap, used, tused, free;
650 	register struct mapent *me;
651 	register struct text *xp;
652 
653 	nproc = getw(nl[SNPROC].n_value);
654 	proc = (struct proc *)calloc(nproc, sizeof (struct proc));
655 	lseek(fc, getw(nl[SPROC].n_value), 0);
656 	read(fc, proc, nproc * sizeof (struct proc));
657 	nswapmap = getw(nl[SNSWAPMAP].n_value);
658 	swapmap = (struct map *)calloc(nswapmap, sizeof (struct map));
659 	lseek(fc, getw(nl[SWAPMAP].n_value), 0);
660 	read(fc, swapmap, nswapmap * sizeof (struct map));
661 	nswap = getw(nl[SNSWAP].n_value);
662 	free = 0;
663 	for (me = (struct mapent *)(swapmap+1);
664 	    me < (struct mapent *)&swapmap[nswapmap]; me++)
665 		free += me->m_size;
666 	ntext = getw(nl[SNTEXT].n_value);
667 	xtext = (struct text *)calloc(ntext, sizeof (struct text));
668 	lseek(fc, getw(nl[STEXT].n_value), 0);
669 	read(fc, xtext, ntext * sizeof (struct text));
670 	tused = 0;
671 	for (xp = xtext; xp < &xtext[ntext]; xp++)
672 		if (xp->x_iptr!=NULL)
673 			tused += xdsize(xp);
674 	used = tused;
675 	for (pp = proc; pp < &proc[nproc]; pp++) {
676 		if (pp->p_stat == 0 || pp->p_stat == SZOMB)
677 			continue;
678 		if (pp->p_flag & SSYS)
679 			continue;
680 		used += up(pp->p_dsize) + up(pp->p_ssize);
681 		if ((pp->p_flag&SLOAD) == 0)
682 			used += vusize(pp);
683 	}
684 	/* a DMMAX/2 block goes to argmap */
685 	if (totflg) {
686 		printf("%3d/%3d 00k swap\n", used/2/100, (used+free)/2/100);
687 		return;
688 	}
689 	printf("%d used (%d text), %d free, %d missing\n",
690 	    used/2, tused/2, free/2, (nswap - DMMAX/2 - (used + free))/2);
691 }
692 
693 up(size)
694 	register int size;
695 {
696 	register int i, block;
697 
698 	i = 0;
699 	block = DMMIN;
700 	while (i < size) {
701 		i += block;
702 		if (block < DMMAX)
703 			block *= 2;
704 	}
705 	return (i);
706 }
707 
708 vusize(p)
709 struct proc *p;
710 {
711 	register int tsz = p->p_tsize / NPTEPG;
712 
713 	return (clrnd(UPAGES + clrnd(ctopt(p->p_tsize+p->p_dsize+p->p_ssize+UPAGES)) - tsz));
714 }
715 
716 xdsize(xp)
717 struct text *xp;
718 {
719 
720 	if (xp->x_flag & XPAGI)
721 		return (clrnd(xp->x_size + ctopt(xp->x_size)));
722 	return (xp->x_size);
723 }
724