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