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