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