use getopt; fix usage statement; -a should imply -p; minor cleanups
[unix-history] / usr / src / usr.sbin / pstat / pstat.c
CommitLineData
5ff67f98
DF
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
ae1f9014 7#ifndef lint
5ff67f98
DF
8char copyright[] =
9"@(#) Copyright (c) 1980 Regents of the University of California.\n\
10 All rights reserved.\n";
0dc27808 11#endif /* not lint */
5ff67f98
DF
12
13#ifndef lint
0dc27808
KB
14static char sccsid[] = "@(#)pstat.c 5.17 (Berkeley) %G%";
15#endif /* not lint */
5ff67f98 16
ceb84881
BJ
17/*
18 * Print system stuff
19 */
20
ceb84881
BJ
21#include <sys/param.h>
22#include <sys/dir.h>
ae1f9014 23#define KERNEL
ceb84881 24#include <sys/file.h>
ae1f9014 25#undef KERNEL
ceb84881
BJ
26#include <sys/user.h>
27#include <sys/proc.h>
28#include <sys/text.h>
29#include <sys/inode.h>
30#include <sys/map.h>
88a58f27 31#include <sys/ioctl.h>
ceb84881
BJ
32#include <sys/tty.h>
33#include <sys/conf.h>
34#include <sys/vm.h>
35#include <nlist.h>
0bc29a7d 36#include <machine/pte.h>
9ed2dfb9 37#include <stdio.h>
ceb84881 38
f20270fc
MK
39#define mask(x) (x&0377)
40#define clear(x) ((int)x &~ KERNBASE)
41
ceb84881 42char *fcore = "/dev/kmem";
aadf0902 43char *fmem = "/dev/mem";
ceb84881 44char *fnlist = "/vmunix";
aadf0902 45int fc, fm;
ceb84881
BJ
46
47struct nlist nl[] = {
48#define SINODE 0
49 { "_inode" },
50#define STEXT 1
51 { "_text" },
52#define SPROC 2
53 { "_proc" },
4242be26 54#define SCONS 3
ceb84881 55 { "_cons" },
4242be26 56#define SFIL 4
ceb84881 57 { "_file" },
4242be26 58#define USRPTMA 5
ceb84881 59 { "_Usrptmap" },
4242be26 60#define USRPT 6
ceb84881 61 { "_usrpt" },
4242be26 62#define SWAPMAP 7
ceb84881 63 { "_swapmap" },
4242be26 64#define SNPROC 8
69d3d166 65 { "_nproc" },
4242be26 66#define SNTEXT 9
69d3d166 67 { "_ntext" },
4242be26 68#define SNFILE 10
69d3d166 69 { "_nfile" },
4242be26 70#define SNINODE 11
69d3d166 71 { "_ninode" },
4242be26 72#define SNSWAPMAP 12
69d3d166 73 { "_nswapmap" },
4242be26 74#define SPTY 13
676bc34a 75 { "_pt_tty" },
4242be26 76#define SDMMIN 14
e79dc02e 77 { "_dmmin" },
4242be26 78#define SDMMAX 15
e79dc02e 79 { "_dmmax" },
4242be26 80#define SNSWDEV 16
e79dc02e 81 { "_nswdev" },
4242be26 82#define SSWDEVT 17
b94a50ef 83 { "_swdevt" },
4242be26
SL
84#define SYSMAP 18
85 { "_Sysmap" },
86#define SNPTY 19
87 { "_npty" },
88#ifdef vax
89#define SDZ (SNPTY+1)
90 { "_dz_tty" },
91#define SNDZ (SNPTY+2)
92 { "_dz_cnt" },
93#define SDMF (SNPTY+3)
890571d1 94 { "_dmf_tty" },
4242be26 95#define SNDMF (SNPTY+4)
890571d1 96 { "_ndmf" },
4242be26
SL
97#define SDH (SNPTY+5)
98 { "_dh11" },
99#define SNDH (SNPTY+6)
100 { "_ndh11" },
101#define SDHU (SNPTY+7)
5cf6fff2 102 { "_dhu_tty" },
4242be26 103#define SNDHU (SNPTY+8)
5cf6fff2 104 { "_ndhu" },
4242be26 105#define SDMZ (SNPTY+9)
35d0530f 106 { "_dmz_tty" },
4242be26 107#define SNDMZ (SNPTY+10)
35d0530f 108 { "_ndmz" },
bac975ad
MT
109#define SQD (SNPTY+11)
110 { "_qd_tty" },
111#define SNQD (SNPTY+12)
112 { "_nNQD" },
4242be26
SL
113#endif
114#ifdef tahoe
115#define SVX (SNPTY+1)
116 { "_vx_tty" },
117#define SNVX (SNPTY+2)
118 { "_nvx" },
119#endif
b94a50ef 120 { "" }
ceb84881
BJ
121};
122
123int inof;
124int txtf;
125int prcf;
126int ttyf;
127int usrf;
128long ubase;
129int filf;
130int swpf;
131int totflg;
132char partab[1];
133struct cdevsw cdevsw[1];
134struct bdevsw bdevsw[1];
135int allflg;
136int kflg;
137struct pte *Usrptma;
138struct pte *usrpt;
dc2a22f1 139u_long getword();
9ed2dfb9 140off_t mkphys();
ceb84881
BJ
141
142main(argc, argv)
0dc27808
KB
143 int argc;
144 char **argv;
ceb84881 145{
0dc27808
KB
146 extern char *optarg;
147 extern int optind;
148 int ch;
ceb84881 149
0dc27808
KB
150 while ((ch = getopt(argc, argv, "Tafikptu:sx")) != EOF)
151 switch((char)ch) {
ceb84881
BJ
152 case 'T':
153 totflg++;
154 break;
ceb84881
BJ
155 case 'a':
156 allflg++;
0dc27808
KB
157 /*FALLTHROUGH*/
158 case 'p':
159 prcf++;
160 break;
161 case 'f':
162 filf++;
ceb84881 163 break;
ceb84881
BJ
164 case 'i':
165 inof++;
166 break;
0dc27808 167 case 'k': /* undocumented */
ceb84881 168 kflg++;
aadf0902 169 fcore = fmem = "/vmcore";
ceb84881 170 break;
ceb84881
BJ
171 case 't':
172 ttyf++;
173 break;
ceb84881 174 case 'u':
ceb84881 175 usrf++;
0dc27808 176 sscanf(optarg, "%x", &ubase);
ceb84881
BJ
177 break;
178 case 's':
179 swpf++;
180 break;
0dc27808
KB
181 case 'x':
182 txtf++;
183 break;
184 case '?':
ae1f9014 185 default:
0dc27808 186 printf("usage: pstat -[Tafiptsx] [-u [ubase]] [system] [core]\n");
ae1f9014 187 exit(1);
ceb84881 188 }
0dc27808
KB
189 argc -= optind;
190 argv += optind;
191
9ed2dfb9 192 if (argc>1) {
aadf0902 193 fcore = fmem = argv[1];
9ed2dfb9
MK
194 kflg++;
195 }
0dc27808
KB
196 if ((fc = open(fcore, O_RDONLY, 0)) < 0) {
197 perror(fcore);
ceb84881
BJ
198 exit(1);
199 }
0dc27808
KB
200 if ((fm = open(fmem, O_RDONLY, 0)) < 0) {
201 perror(fmem);
aadf0902
MK
202 exit(1);
203 }
ae1f9014
SL
204 if (argc>0)
205 fnlist = argv[0];
ceb84881 206 nlist(fnlist, nl);
ceb84881 207 if (nl[0].n_type == 0) {
0dc27808 208 printf("pstat: no namelist.\n");
ceb84881
BJ
209 exit(1);
210 }
0dc27808
KB
211 usrpt = (struct pte *)nl[USRPT].n_value;
212 Usrptma = (struct pte *)nl[USRPTMA].n_value;
213 if (!(filf | totflg | inof | prcf | txtf | ttyf | usrf | swpf)) {
ae1f9014
SL
214 printf("pstat: one or more of -[aixptfsu] is required\n");
215 exit(1);
216 }
ceb84881 217 if (filf||totflg)
69d3d166 218 dofile();
ceb84881
BJ
219 if (inof||totflg)
220 doinode();
221 if (prcf||totflg)
222 doproc();
223 if (txtf||totflg)
224 dotext();
225 if (ttyf)
226 dotty();
227 if (usrf)
228 dousr();
229 if (swpf||totflg)
230 doswap();
231}
232
233doinode()
234{
235 register struct inode *ip;
69d3d166
BJ
236 struct inode *xinode, *ainode;
237 register int nin;
238 int ninode;
ceb84881
BJ
239
240 nin = 0;
dc2a22f1 241 ninode = getword(nl[SNINODE].n_value);
69d3d166 242 xinode = (struct inode *)calloc(ninode, sizeof (struct inode));
dc2a22f1 243 ainode = (struct inode *)getword(nl[SINODE].n_value);
9ed2dfb9
MK
244 if (ninode < 0 || ninode > 10000) {
245 fprintf(stderr, "number of inodes is preposterous (%d)\n",
246 ninode);
247 return;
248 }
249 if (xinode == NULL) {
250 fprintf(stderr, "can't allocate memory for inode table\n");
251 return;
252 }
253 lseek(fc, mkphys((off_t)ainode), 0);
69d3d166
BJ
254 read(fc, xinode, ninode * sizeof(struct inode));
255 for (ip = xinode; ip < &xinode[ninode]; ip++)
ceb84881
BJ
256 if (ip->i_count)
257 nin++;
258 if (totflg) {
69d3d166 259 printf("%3d/%3d inodes\n", nin, ninode);
ceb84881
BJ
260 return;
261 }
69d3d166 262 printf("%d/%d active inodes\n", nin, ninode);
ae1f9014 263printf(" LOC FLAGS CNT DEVICE RDC WRC INO MODE NLK UID SIZE/DEV\n");
69d3d166 264 for (ip = xinode; ip < &xinode[ninode]; ip++) {
ceb84881
BJ
265 if (ip->i_count == 0)
266 continue;
69d3d166 267 printf("%8.1x ", ainode + (ip - xinode));
88a58f27 268 putf(ip->i_flag&ILOCKED, 'L');
ceb84881
BJ
269 putf(ip->i_flag&IUPD, 'U');
270 putf(ip->i_flag&IACC, 'A');
271 putf(ip->i_flag&IMOUNT, 'M');
272 putf(ip->i_flag&IWANT, 'W');
273 putf(ip->i_flag&ITEXT, 'T');
ae1f9014
SL
274 putf(ip->i_flag&ICHG, 'C');
275 putf(ip->i_flag&ISHLOCK, 'S');
276 putf(ip->i_flag&IEXLOCK, 'E');
277 putf(ip->i_flag&ILWAIT, 'Z');
ceb84881
BJ
278 printf("%4d", ip->i_count&0377);
279 printf("%4d,%3d", major(ip->i_dev), minor(ip->i_dev));
88a58f27
SL
280 printf("%4d", ip->i_shlockc&0377);
281 printf("%4d", ip->i_exlockc&0377);
ceb84881
BJ
282 printf("%6d", ip->i_number);
283 printf("%6x", ip->i_mode & 0xffff);
284 printf("%4d", ip->i_nlink);
285 printf("%4d", ip->i_uid);
286 if ((ip->i_mode&IFMT)==IFBLK || (ip->i_mode&IFMT)==IFCHR)
a06cf6a1 287 printf("%6d,%3d", major(ip->i_rdev), minor(ip->i_rdev));
ceb84881
BJ
288 else
289 printf("%10ld", ip->i_size);
290 printf("\n");
291 }
69d3d166
BJ
292 free(xinode);
293}
294
9ed2dfb9 295u_long
dc2a22f1 296getword(loc)
69d3d166
BJ
297 off_t loc;
298{
9ed2dfb9 299 u_long word;
69d3d166 300
cea9ae1e 301 if (kflg)
4242be26 302 loc = clear(loc);
69d3d166
BJ
303 lseek(fc, loc, 0);
304 read(fc, &word, sizeof (word));
305 return (word);
ceb84881
BJ
306}
307
308putf(v, n)
309{
310 if (v)
311 printf("%c", n);
312 else
69d3d166 313 printf(" ");
ceb84881
BJ
314}
315
316dotext()
317{
318 register struct text *xp;
69d3d166
BJ
319 int ntext;
320 struct text *xtext, *atext;
9ed2dfb9 321 int ntx, ntxca;
ceb84881 322
9ed2dfb9 323 ntx = ntxca = 0;
dc2a22f1 324 ntext = getword(nl[SNTEXT].n_value);
69d3d166 325 xtext = (struct text *)calloc(ntext, sizeof (struct text));
dc2a22f1 326 atext = (struct text *)getword(nl[STEXT].n_value);
9ed2dfb9
MK
327 if (ntext < 0 || ntext > 10000) {
328 fprintf(stderr, "number of texts is preposterous (%d)\n",
329 ntext);
330 return;
331 }
332 if (xtext == NULL) {
333 fprintf(stderr, "can't allocate memory for text table\n");
334 return;
335 }
336 lseek(fc, mkphys((off_t)atext), 0);
69d3d166 337 read(fc, xtext, ntext * sizeof (struct text));
9ed2dfb9
MK
338 for (xp = xtext; xp < &xtext[ntext]; xp++) {
339 if (xp->x_iptr != NULL)
340 ntxca++;
341 if (xp->x_count != 0)
ceb84881 342 ntx++;
9ed2dfb9 343 }
ceb84881 344 if (totflg) {
9ed2dfb9 345 printf("%3d/%3d texts active, %3d used\n", ntx, ntext, ntxca);
ceb84881
BJ
346 return;
347 }
9ed2dfb9
MK
348 printf("%d/%d active texts, %d used\n", ntx, ntext, ntxca);
349 printf("\
350 LOC FLAGS DADDR CADDR RSS SIZE IPTR CNT CCNT FORW BACK\n");
69d3d166 351 for (xp = xtext; xp < &xtext[ntext]; xp++) {
ceb84881
BJ
352 if (xp->x_iptr == NULL)
353 continue;
69d3d166 354 printf("%8.1x", atext + (xp - xtext));
ceb84881
BJ
355 printf(" ");
356 putf(xp->x_flag&XPAGI, 'P');
357 putf(xp->x_flag&XTRC, 'T');
358 putf(xp->x_flag&XWRIT, 'W');
359 putf(xp->x_flag&XLOAD, 'L');
360 putf(xp->x_flag&XLOCK, 'K');
361 putf(xp->x_flag&XWANT, 'w');
ceb84881 362 printf("%5x", xp->x_daddr[0]);
9ed2dfb9 363 printf("%10x", xp->x_caddr);
ceb84881
BJ
364 printf("%5d", xp->x_rssize);
365 printf("%5d", xp->x_size);
366 printf("%10.1x", xp->x_iptr);
367 printf("%5d", xp->x_count&0377);
54298f71 368 printf("%5d", xp->x_ccount);
9ed2dfb9
MK
369 printf("%10x", xp->x_forw);
370 printf("%9x", xp->x_back);
ceb84881
BJ
371 printf("\n");
372 }
69d3d166 373 free(xtext);
ceb84881
BJ
374}
375
376doproc()
377{
69d3d166
BJ
378 struct proc *xproc, *aproc;
379 int nproc;
ceb84881
BJ
380 register struct proc *pp;
381 register loc, np;
382 struct pte apte;
383
dc2a22f1 384 nproc = getword(nl[SNPROC].n_value);
69d3d166 385 xproc = (struct proc *)calloc(nproc, sizeof (struct proc));
dc2a22f1 386 aproc = (struct proc *)getword(nl[SPROC].n_value);
9ed2dfb9
MK
387 if (nproc < 0 || nproc > 10000) {
388 fprintf(stderr, "number of procs is preposterous (%d)\n",
389 nproc);
390 return;
391 }
392 if (xproc == NULL) {
393 fprintf(stderr, "can't allocate memory for proc table\n");
394 return;
395 }
396 lseek(fc, mkphys((off_t)aproc), 0);
69d3d166 397 read(fc, xproc, nproc * sizeof (struct proc));
ceb84881 398 np = 0;
69d3d166 399 for (pp=xproc; pp < &xproc[nproc]; pp++)
ceb84881
BJ
400 if (pp->p_stat)
401 np++;
402 if (totflg) {
69d3d166 403 printf("%3d/%3d processes\n", np, nproc);
ceb84881
BJ
404 return;
405 }
69d3d166 406 printf("%d/%d processes\n", np, nproc);
aadf0902 407 printf(" LOC S F POIP PRI SIG UID SLP TIM CPU NI PGRP PID PPID ADDR RSS SRSS SIZE WCHAN LINK TEXTP\n");
69d3d166 408 for (pp=xproc; pp<&xproc[nproc]; pp++) {
ceb84881
BJ
409 if (pp->p_stat==0 && allflg==0)
410 continue;
69d3d166 411 printf("%8x", aproc + (pp - xproc));
ceb84881
BJ
412 printf(" %2d", pp->p_stat);
413 printf(" %4x", pp->p_flag & 0xffff);
414 printf(" %4d", pp->p_poip);
415 printf(" %3d", pp->p_pri);
54298f71 416 printf(" %8x", pp->p_sig);
ceb84881
BJ
417 printf(" %4d", pp->p_uid);
418 printf(" %3d", pp->p_slptime);
419 printf(" %3d", pp->p_time);
420 printf(" %4d", pp->p_cpu&0377);
421 printf(" %3d", pp->p_nice);
422 printf(" %6d", pp->p_pgrp);
423 printf(" %6d", pp->p_pid);
424 printf(" %6d", pp->p_ppid);
425 if (kflg)
426 pp->p_addr = (struct pte *)clear((int)pp->p_addr);
aadf0902
MK
427 if (pp->p_flag & SLOAD) {
428 lseek(fc, (long)pp->p_addr, 0);
429 read(fc, &apte, sizeof(apte));
430 printf(" %8x", apte.pg_pfnum);
431 } else
432 printf(" %8x", pp->p_swaddr);
ceb84881
BJ
433 printf(" %4x", pp->p_rssize);
434 printf(" %4x", pp->p_swrss);
435 printf(" %5x", pp->p_dsize+pp->p_ssize);
436 printf(" %7x", clear(pp->p_wchan));
437 printf(" %7x", clear(pp->p_link));
438 printf(" %7x", clear(pp->p_textp));
ceb84881
BJ
439 printf("\n");
440 }
9ed2dfb9 441 free(xproc);
ceb84881
BJ
442}
443
5cf6fff2
KM
444static char mesg[] =
445" # RAW CAN OUT MODE ADDR DEL COL STATE PGRP DISC\n";
446static int ttyspace = 128;
447static struct tty *tty;
448
ceb84881
BJ
449dotty()
450{
5cf6fff2 451 extern char *malloc();
ceb84881 452
13562341
MK
453 if ((tty = (struct tty *)malloc(ttyspace * sizeof(*tty))) == 0) {
454 printf("pstat: out of memory\n");
455 return;
456 }
ceb84881 457 printf("1 cons\n");
835c8965 458 if (kflg)
4242be26
SL
459 nl[SCONS].n_value = clear(nl[SCONS].n_value);
460 lseek(fc, (long)nl[SCONS].n_value, 0);
13562341 461 read(fc, tty, sizeof(*tty));
ceb84881 462 printf(mesg);
13562341 463 ttyprt(&tty[0], 0);
4242be26 464#ifdef vax
bac975ad
MT
465 if (nl[SNQD].n_type != 0)
466 doqdss();
5cf6fff2
KM
467 if (nl[SNDZ].n_type != 0)
468 dottytype("dz", SDZ, SNDZ);
469 if (nl[SNDH].n_type != 0)
470 dottytype("dh", SDH, SNDH);
471 if (nl[SNDMF].n_type != 0)
472 dottytype("dmf", SDMF, SNDMF);
473 if (nl[SNDHU].n_type != 0)
474 dottytype("dhu", SDHU, SNDHU);
35d0530f
JB
475 if (nl[SNDMZ].n_type != 0)
476 dottytype("dmz", SDMZ, SNDMZ);
4242be26
SL
477#endif
478#ifdef tahoe
479 if (nl[SNVX].n_type != 0)
480 dottytype("vx", SVX, SNVX);
481#endif
5cf6fff2
KM
482 if (nl[SNPTY].n_type != 0)
483 dottytype("pty", SPTY, SNPTY);
484}
485
bac975ad
MT
486/*
487 * Special case the qdss because there are 4 tty structs per qdss
488 * and only the first of each is used as a tty.
489 */
490#ifdef vax
491doqdss()
492{
493 int nqd;
494 register struct tty *tp;
495
496 if (kflg) {
497 nl[SNQD].n_value = clear(nl[SNQD].n_value);
498 nl[SQD].n_value = clear(nl[SQD].n_value);
499 }
500 lseek(fc, (long)nl[SNQD].n_value, 0);
501 read(fc, &nqd, sizeof(nqd));
502 printf("%d qd\n", nqd);
503 lseek(fc, (long)nl[SQD].n_value, 0);
504 read(fc, tty, nqd * sizeof(struct tty) * 4);
505 printf(mesg);
506 for (tp = tty; tp < &tty[nqd * 4]; tp += 4)
507 ttyprt(tp, tp - tty);
508}
509#endif
510
5cf6fff2
KM
511dottytype(name, type, number)
512char *name;
513{
514 int ntty;
515 register struct tty *tp;
516 extern char *realloc();
517
bac975ad 518 if (tty == (struct tty *)0)
890571d1 519 return;
676bc34a 520 if (kflg) {
5cf6fff2
KM
521 nl[number].n_value = clear(nl[number].n_value);
522 nl[type].n_value = clear(nl[type].n_value);
13562341 523 }
5cf6fff2 524 lseek(fc, (long)nl[number].n_value, 0);
13562341 525 read(fc, &ntty, sizeof(ntty));
5cf6fff2 526 printf("%d %s lines\n", ntty, name);
13562341
MK
527 if (ntty > ttyspace) {
528 ttyspace = ntty;
529 if ((tty = (struct tty *)realloc(tty, ttyspace * sizeof(*tty))) == 0) {
530 printf("pstat: out of memory\n");
531 return;
532 }
676bc34a 533 }
5cf6fff2
KM
534 lseek(fc, (long)nl[type].n_value, 0);
535 read(fc, tty, ntty * sizeof(struct tty));
8faa0fee 536 printf(mesg);
13562341
MK
537 for (tp = tty; tp < &tty[ntty]; tp++)
538 ttyprt(tp, tp - tty);
ceb84881
BJ
539}
540
541ttyprt(atp, line)
542struct tty *atp;
543{
544 register struct tty *tp;
545
546 printf("%2d", line);
547 tp = atp;
548 switch (tp->t_line) {
549
4242be26 550#ifdef notdef
ceb84881
BJ
551 case NETLDISC:
552 if (tp->t_rec)
553 printf("%4d%4d", 0, tp->t_inbuf);
554 else
555 printf("%4d%4d", tp->t_inbuf, 0);
556 break;
4242be26 557#endif
ceb84881
BJ
558
559 default:
8faa0fee 560 printf("%4d%4d", tp->t_rawq.c_cc, tp->t_canq.c_cc);
ceb84881 561 }
8faa0fee
EW
562 printf("%4d %8x %8x%4d%4d", tp->t_outq.c_cc, tp->t_flags,
563 tp->t_addr, tp->t_delct, tp->t_col);
676bc34a
BJ
564 putf(tp->t_state&TS_TIMEOUT, 'T');
565 putf(tp->t_state&TS_WOPEN, 'W');
566 putf(tp->t_state&TS_ISOPEN, 'O');
8faa0fee 567 putf(tp->t_state&TS_FLUSH, 'F');
676bc34a
BJ
568 putf(tp->t_state&TS_CARR_ON, 'C');
569 putf(tp->t_state&TS_BUSY, 'B');
570 putf(tp->t_state&TS_ASLEEP, 'A');
571 putf(tp->t_state&TS_XCLUDE, 'X');
8faa0fee 572 putf(tp->t_state&TS_TTSTOP, 'S');
676bc34a 573 putf(tp->t_state&TS_HUPCLS, 'H');
ceb84881
BJ
574 printf("%6d", tp->t_pgrp);
575 switch (tp->t_line) {
576
8faa0fee
EW
577 case OTTYDISC:
578 printf("\n");
579 break;
580
ceb84881 581 case NTTYDISC:
8faa0fee 582 printf(" ntty\n");
ceb84881
BJ
583 break;
584
585 case NETLDISC:
1d994a88 586 printf(" berknet\n");
ceb84881 587 break;
8faa0fee
EW
588
589 case TABLDISC:
590 printf(" tab\n");
591 break;
592
399e4254
KB
593 case SLIPDISC:
594 printf(" slip\n");
595 break;
596
8faa0fee
EW
597 default:
598 printf(" %d\n", tp->t_line);
ceb84881 599 }
ceb84881
BJ
600}
601
602dousr()
603{
604 struct user U;
605 register i, j, *ip;
a5bcb7fd 606 register struct nameidata *nd = &U.u_nd;
ceb84881 607
aadf0902
MK
608 /* This wins only if CLBYTES >= sizeof (struct user) */
609 lseek(fm, ubase * NBPG, 0);
610 read(fm, &U, sizeof(U));
ceb84881
BJ
611 printf("pcb");
612 ip = (int *)&U.u_pcb;
613 while (ip < &U.u_arg[0]) {
614 if ((ip - (int *)&U.u_pcb) % 4 == 0)
615 printf("\t");
616 printf("%x ", *ip++);
617 if ((ip - (int *)&U.u_pcb) % 4 == 0)
618 printf("\n");
619 }
620 if ((ip - (int *)&U.u_pcb) % 4 != 0)
621 printf("\n");
aadf0902
MK
622 printf("arg");
623 for (i=0; i<sizeof(U.u_arg)/sizeof(U.u_arg[0]); i++) {
ceb84881
BJ
624 if (i%5==0)
625 printf("\t");
aadf0902 626 printf(" %.1x", U.u_arg[i]);
ceb84881
BJ
627 if (i%5==4)
628 printf("\n");
629 }
630 if (i%5)
631 printf("\n");
a5bcb7fd 632 printf("segflg\t%d\nerror %d\n", nd->ni_segflg, U.u_error);
ceb84881
BJ
633 printf("uids\t%d,%d,%d,%d\n", U.u_uid,U.u_gid,U.u_ruid,U.u_rgid);
634 printf("procp\t%.1x\n", U.u_procp);
635 printf("ap\t%.1x\n", U.u_ap);
636 printf("r_val?\t%.1x %.1x\n", U.u_r.r_val1, U.u_r.r_val2);
a5bcb7fd
JB
637 printf("base, count, offset %.1x %.1x %ld\n", nd->ni_base,
638 nd->ni_count, nd->ni_offset);
ceb84881 639 printf("cdir rdir %.1x %.1x\n", U.u_cdir, U.u_rdir);
a5bcb7fd
JB
640 printf("dirp %.1x\n", nd->ni_dirp);
641 printf("dent %d %.14s\n", nd->ni_dent.d_ino, nd->ni_dent.d_name);
642 printf("pdir %.1o\n", nd->ni_pdir);
aadf0902
MK
643 printf("file");
644 for (i=0; i<NOFILE; i++) {
645 if (i % 8 == 0)
646 printf("\t");
ceb84881 647 printf("%9.1x", U.u_ofile[i]);
aadf0902
MK
648 if (i % 8 == 7)
649 printf("\n");
650 }
651 if (i % 8)
652 printf("\n");
653 printf("pofile");
654 for (i=0; i<NOFILE; i++) {
655 if (i % 8 == 0)
656 printf("\t");
ceb84881 657 printf("%9.1x", U.u_pofile[i]);
aadf0902
MK
658 if (i % 8 == 7)
659 printf("\n");
660 }
661 if (i % 8)
662 printf("\n");
88a58f27 663 printf("ssave");
ceb84881
BJ
664 for (i=0; i<sizeof(label_t)/sizeof(int); i++) {
665 if (i%5==0)
666 printf("\t");
88a58f27 667 printf("%9.1x", U.u_ssave.val[i]);
ceb84881
BJ
668 if (i%5==4)
669 printf("\n");
670 }
671 if (i%5)
672 printf("\n");
aadf0902
MK
673 printf("sigs");
674 for (i=0; i<NSIG; i++) {
675 if (i % 8 == 0)
676 printf("\t");
ceb84881 677 printf("%.1x ", U.u_signal[i]);
aadf0902
MK
678 if (i % 8 == 7)
679 printf("\n");
680 }
681 if (i % 8)
682 printf("\n");
df3e00cc 683 printf("code\t%.1x\n", U.u_code);
ceb84881 684 printf("ar0\t%.1x\n", U.u_ar0);
b9e98a4b 685 printf("prof\t%x %x %x %x\n", U.u_prof.pr_base, U.u_prof.pr_size,
ceb84881
BJ
686 U.u_prof.pr_off, U.u_prof.pr_scale);
687 printf("\neosys\t%d\n", U.u_eosys);
ceb84881
BJ
688 printf("ttyp\t%.1x\n", U.u_ttyp);
689 printf("ttyd\t%d,%d\n", major(U.u_ttyd), minor(U.u_ttyd));
ceb84881 690 printf("comm %.14s\n", U.u_comm);
b9e98a4b
KB
691 printf("start\t%ld\n", U.u_start.tv_sec);
692 printf("acflag\t%ld\n", U.u_acflag);
693 printf("cmask\t%ld\n", U.u_cmask);
ceb84881 694 printf("sizes\t%.1x %.1x %.1x\n", U.u_tsize, U.u_dsize, U.u_ssize);
88a58f27
SL
695 printf("ru\t");
696 ip = (int *)&U.u_ru;
697 for (i = 0; i < sizeof(U.u_ru)/sizeof(int); i++)
b9e98a4b 698 printf("%ld ", ip[i]);
ceb84881 699 printf("\n");
88a58f27
SL
700 ip = (int *)&U.u_cru;
701 printf("cru\t");
702 for (i = 0; i < sizeof(U.u_cru)/sizeof(int); i++)
b9e98a4b 703 printf("%ld ", ip[i]);
ceb84881 704 printf("\n");
4242be26 705#ifdef notdef
ceb84881
BJ
706 i = U.u_stack - &U;
707 while (U[++i] == 0);
708 i &= ~07;
709 while (i < 512) {
710 printf("%x ", 0140000+2*i);
711 for (j=0; j<8; j++)
712 printf("%9x", U[i++]);
713 printf("\n");
714 }
4242be26 715#endif
ceb84881
BJ
716}
717
718oatoi(s)
719char *s;
720{
721 register v;
722
723 v = 0;
724 while (*s)
725 v = (v<<3) + *s++ - '0';
726 return(v);
727}
728
69d3d166 729dofile()
ceb84881 730{
69d3d166
BJ
731 int nfile;
732 struct file *xfile, *afile;
ceb84881
BJ
733 register struct file *fp;
734 register nf;
735 int loc;
71c73ab0 736 static char *dtypes[] = { "???", "inode", "socket" };
ceb84881
BJ
737
738 nf = 0;
dc2a22f1 739 nfile = getword(nl[SNFILE].n_value);
69d3d166 740 xfile = (struct file *)calloc(nfile, sizeof (struct file));
dc2a22f1 741 afile = (struct file *)getword(nl[SFIL].n_value);
9ed2dfb9
MK
742 if (nfile < 0 || nfile > 10000) {
743 fprintf(stderr, "number of files is preposterous (%d)\n",
744 nfile);
745 return;
746 }
747 if (xfile == NULL) {
748 fprintf(stderr, "can't allocate memory for file table\n");
749 return;
750 }
751 lseek(fc, mkphys((off_t)afile), 0);
69d3d166
BJ
752 read(fc, xfile, nfile * sizeof (struct file));
753 for (fp=xfile; fp < &xfile[nfile]; fp++)
ceb84881
BJ
754 if (fp->f_count)
755 nf++;
756 if (totflg) {
69d3d166 757 printf("%3d/%3d files\n", nf, nfile);
ceb84881
BJ
758 return;
759 }
69d3d166 760 printf("%d/%d open files\n", nf, nfile);
192c0cf3 761 printf(" LOC TYPE FLG CNT MSG DATA OFFSET\n");
fd2ae9b6 762 for (fp=xfile,loc=(int)afile; fp < &xfile[nfile]; fp++,loc+=sizeof(xfile[0])) {
ceb84881
BJ
763 if (fp->f_count==0)
764 continue;
765 printf("%8x ", loc);
71c73ab0 766 if (fp->f_type <= DTYPE_SOCKET)
ae1f9014
SL
767 printf("%-8.8s", dtypes[fp->f_type]);
768 else
ff8002b1 769 printf("%8d", fp->f_type);
ceb84881
BJ
770 putf(fp->f_flag&FREAD, 'R');
771 putf(fp->f_flag&FWRITE, 'W');
ae1f9014 772 putf(fp->f_flag&FAPPEND, 'A');
192c0cf3
SL
773 putf(fp->f_flag&FSHLOCK, 'S');
774 putf(fp->f_flag&FEXLOCK, 'X');
775 putf(fp->f_flag&FASYNC, 'I');
71c73ab0
SL
776 printf(" %3d", mask(fp->f_count));
777 printf(" %3d", mask(fp->f_msgcount));
778 printf(" %8.1x", fp->f_data);
779 if (fp->f_offset < 0)
780 printf(" %x\n", fp->f_offset);
676bc34a
BJ
781 else
782 printf(" %ld\n", fp->f_offset);
ceb84881 783 }
9ed2dfb9 784 free(xfile);
ceb84881
BJ
785}
786
e79dc02e
SL
787int dmmin, dmmax, nswdev;
788
ceb84881
BJ
789doswap()
790{
69d3d166
BJ
791 struct proc *proc;
792 int nproc;
793 struct text *xtext;
794 int ntext;
795 struct map *swapmap;
796 int nswapmap;
b94a50ef 797 struct swdevt *swdevt, *sw;
ceb84881 798 register struct proc *pp;
e79dc02e
SL
799 int nswap, used, tused, free, waste;
800 int db, sb;
df3e00cc 801 register struct mapent *me;
ceb84881 802 register struct text *xp;
e79dc02e 803 int i, j;
f85d329a 804 long rmalloc();
ceb84881 805
dc2a22f1
KM
806 nproc = getword(nl[SNPROC].n_value);
807 ntext = getword(nl[SNTEXT].n_value);
9ed2dfb9
MK
808 if (nproc < 0 || nproc > 10000 || ntext < 0 || ntext > 10000) {
809 fprintf(stderr, "number of procs/texts is preposterous (%d, %d)\n",
810 nproc, ntext);
811 return;
812 }
813 proc = (struct proc *)calloc(nproc, sizeof (struct proc));
814 if (proc == NULL) {
815 fprintf(stderr, "can't allocate memory for proc table\n");
816 exit(1);
817 }
b94a50ef 818 xtext = (struct text *)calloc(ntext, sizeof (struct text));
9ed2dfb9
MK
819 if (xtext == NULL) {
820 fprintf(stderr, "can't allocate memory for text table\n");
821 exit(1);
822 }
dc2a22f1 823 nswapmap = getword(nl[SNSWAPMAP].n_value);
69d3d166 824 swapmap = (struct map *)calloc(nswapmap, sizeof (struct map));
9ed2dfb9
MK
825 if (swapmap == NULL) {
826 fprintf(stderr, "can't allocate memory for swapmap\n");
827 exit(1);
828 }
dc2a22f1 829 nswdev = getword(nl[SNSWDEV].n_value);
b94a50ef 830 swdevt = (struct swdevt *)calloc(nswdev, sizeof (struct swdevt));
9ed2dfb9
MK
831 if (swdevt == NULL) {
832 fprintf(stderr, "can't allocate memory for swdevt table\n");
833 exit(1);
834 }
835 lseek(fc, mkphys((off_t)nl[SSWDEVT].n_value), L_SET);
b94a50ef 836 read(fc, swdevt, nswdev * sizeof (struct swdevt));
dc2a22f1 837 lseek(fc, mkphys((off_t)getword(nl[SPROC].n_value)), 0);
b94a50ef 838 read(fc, proc, nproc * sizeof (struct proc));
dc2a22f1 839 lseek(fc, mkphys((off_t)getword(nl[STEXT].n_value)), 0);
b94a50ef 840 read(fc, xtext, ntext * sizeof (struct text));
dc2a22f1 841 lseek(fc, mkphys((off_t)getword(nl[SWAPMAP].n_value)), 0);
69d3d166 842 read(fc, swapmap, nswapmap * sizeof (struct map));
33b2e9da 843 swapmap->m_name = "swap";
e49b41bc 844 swapmap->m_limit = (struct mapent *)&swapmap[nswapmap];
dc2a22f1
KM
845 dmmin = getword(nl[SDMMIN].n_value);
846 dmmax = getword(nl[SDMMAX].n_value);
b94a50ef
SL
847 nswap = 0;
848 for (sw = swdevt; sw < &swdevt[nswdev]; sw++)
491de191
KM
849 if (sw->sw_freed)
850 nswap += sw->sw_nblks;
ceb84881 851 free = 0;
df3e00cc
BJ
852 for (me = (struct mapent *)(swapmap+1);
853 me < (struct mapent *)&swapmap[nswapmap]; me++)
854 free += me->m_size;
ceb84881 855 tused = 0;
69d3d166 856 for (xp = xtext; xp < &xtext[ntext]; xp++)
b94a50ef 857 if (xp->x_iptr!=NULL) {
79877ea5 858 tused += ctod(clrnd(xp->x_size));
b94a50ef 859 if (xp->x_flag & XPAGI)
79877ea5 860 tused += ctod(clrnd(ctopt(xp->x_size)));
b94a50ef 861 }
ceb84881 862 used = tused;
e79dc02e 863 waste = 0;
69d3d166 864 for (pp = proc; pp < &proc[nproc]; pp++) {
ceb84881
BJ
865 if (pp->p_stat == 0 || pp->p_stat == SZOMB)
866 continue;
867 if (pp->p_flag & SSYS)
868 continue;
b94a50ef
SL
869 db = ctod(pp->p_dsize), sb = up(db);
870 used += sb;
871 waste += sb - db;
872 db = ctod(pp->p_ssize), sb = up(db);
873 used += sb;
874 waste += sb - db;
ceb84881 875 if ((pp->p_flag&SLOAD) == 0)
13562341 876 used += ctod(vusize(pp));
ceb84881 877 }
ceb84881 878 if (totflg) {
b94a50ef
SL
879#define btok(x) ((x) / (1024 / DEV_BSIZE))
880 printf("%3d/%3d 00k swap\n",
881 btok(used/100), btok((used+free)/100));
ceb84881
BJ
882 return;
883 }
b94a50ef
SL
884 printf("%dk used (%dk text), %dk free, %dk wasted, %dk missing\n",
885 btok(used), btok(tused), btok(free), btok(waste),
886/* a dmmax/2 block goes to argmap */
887 btok(nswap - dmmax/2 - (used + free)));
e79dc02e
SL
888 printf("avail: ");
889 for (i = dmmax; i >= dmmin; i /= 2) {
890 j = 0;
891 while (rmalloc(swapmap, i) != 0)
892 j++;
b94a50ef 893 if (j) printf("%d*%dk ", j, btok(i));
e79dc02e 894 }
b94a50ef
SL
895 free = 0;
896 for (me = (struct mapent *)(swapmap+1);
897 me < (struct mapent *)&swapmap[nswapmap]; me++)
898 free += me->m_size;
899 printf("%d*1k\n", btok(free));
ceb84881
BJ
900}
901
902up(size)
903 register int size;
904{
905 register int i, block;
906
907 i = 0;
e79dc02e 908 block = dmmin;
ceb84881
BJ
909 while (i < size) {
910 i += block;
e79dc02e 911 if (block < dmmax)
ceb84881
BJ
912 block *= 2;
913 }
914 return (i);
915}
916
b94a50ef
SL
917/*
918 * Compute number of pages to be allocated to the u. area
919 * and data and stack area page tables, which are stored on the
920 * disk immediately after the u. area.
921 */
ceb84881 922vusize(p)
b94a50ef 923 register struct proc *p;
ceb84881
BJ
924{
925 register int tsz = p->p_tsize / NPTEPG;
926
b94a50ef
SL
927 /*
928 * We do not need page table space on the disk for page
929 * table pages wholly containing text.
930 */
931 return (clrnd(UPAGES +
932 clrnd(ctopt(p->p_tsize+p->p_dsize+p->p_ssize+UPAGES)) - tsz));
e79dc02e
SL
933}
934
935/*
936 * Allocate 'size' units from the given
937 * map. Return the base of the allocated space.
938 * In a map, the addresses are increasing and the
939 * list is terminated by a 0 size.
940 *
941 * Algorithm is first-fit.
942 *
943 * This routine knows about the interleaving of the swapmap
944 * and handles that.
945 */
946long
947rmalloc(mp, size)
948 register struct map *mp;
949 long size;
950{
951 register struct mapent *ep = (struct mapent *)(mp+1);
952 register int addr;
953 register struct mapent *bp;
954 swblk_t first, rest;
955
956 if (size <= 0 || size > dmmax)
957 return (0);
958 /*
959 * Search for a piece of the resource map which has enough
960 * free space to accomodate the request.
961 */
962 for (bp = ep; bp->m_size; bp++) {
963 if (bp->m_size >= size) {
964 /*
965 * If allocating from swapmap,
966 * then have to respect interleaving
967 * boundaries.
968 */
969 if (nswdev > 1 &&
970 (first = dmmax - bp->m_addr%dmmax) < bp->m_size) {
971 if (bp->m_size - first < size)
972 continue;
973 addr = bp->m_addr + first;
974 rest = bp->m_size - first - size;
975 bp->m_size = first;
976 if (rest)
977 rmfree(mp, rest, addr+size);
978 return (addr);
979 }
980 /*
981 * Allocate from the map.
982 * If there is no space left of the piece
983 * we allocated from, move the rest of
984 * the pieces to the left.
985 */
986 addr = bp->m_addr;
987 bp->m_addr += size;
988 if ((bp->m_size -= size) == 0) {
989 do {
990 bp++;
991 (bp-1)->m_addr = bp->m_addr;
992 } while ((bp-1)->m_size = bp->m_size);
993 }
994 if (addr % CLSIZE)
995 return (0);
996 return (addr);
997 }
998 }
999 return (0);
1000}
1001
1002/*
1003 * Free the previously allocated space at addr
1004 * of size units into the specified map.
1005 * Sort addr into map and combine on
1006 * one or both ends if possible.
1007 */
1008rmfree(mp, size, addr)
1009 struct map *mp;
1010 long size, addr;
1011{
1012 struct mapent *firstbp;
1013 register struct mapent *bp;
1014 register int t;
1015
1016 /*
1017 * Both address and size must be
1018 * positive, or the protocol has broken down.
1019 */
1020 if (addr <= 0 || size <= 0)
1021 goto badrmfree;
1022 /*
1023 * Locate the piece of the map which starts after the
1024 * returned space (or the end of the map).
1025 */
1026 firstbp = bp = (struct mapent *)(mp + 1);
1027 for (; bp->m_addr <= addr && bp->m_size != 0; bp++)
1028 continue;
1029 /*
1030 * If the piece on the left abuts us,
1031 * then we should combine with it.
1032 */
1033 if (bp > firstbp && (bp-1)->m_addr+(bp-1)->m_size >= addr) {
1034 /*
1035 * Check no overlap (internal error).
1036 */
1037 if ((bp-1)->m_addr+(bp-1)->m_size > addr)
1038 goto badrmfree;
1039 /*
1040 * Add into piece on the left by increasing its size.
1041 */
1042 (bp-1)->m_size += size;
1043 /*
1044 * If the combined piece abuts the piece on
1045 * the right now, compress it in also,
1046 * by shifting the remaining pieces of the map over.
1047 */
1048 if (bp->m_addr && addr+size >= bp->m_addr) {
1049 if (addr+size > bp->m_addr)
1050 goto badrmfree;
1051 (bp-1)->m_size += bp->m_size;
1052 while (bp->m_size) {
1053 bp++;
1054 (bp-1)->m_addr = bp->m_addr;
1055 (bp-1)->m_size = bp->m_size;
1056 }
1057 }
1058 goto done;
1059 }
1060 /*
1061 * Don't abut on the left, check for abutting on
1062 * the right.
1063 */
1064 if (addr+size >= bp->m_addr && bp->m_size) {
1065 if (addr+size > bp->m_addr)
1066 goto badrmfree;
1067 bp->m_addr -= size;
1068 bp->m_size += size;
1069 goto done;
1070 }
1071 /*
1072 * Don't abut at all. Make a new entry
1073 * and check for map overflow.
1074 */
1075 do {
1076 t = bp->m_addr;
1077 bp->m_addr = addr;
1078 addr = t;
1079 t = bp->m_size;
1080 bp->m_size = size;
1081 bp++;
1082 } while (size = t);
1083 /*
1084 * Segment at bp is to be the delimiter;
1085 * If there is not room for it
1086 * then the table is too full
1087 * and we must discard something.
1088 */
1089 if (bp+1 > mp->m_limit) {
1090 /*
1091 * Back bp up to last available segment.
1092 * which contains a segment already and must
1093 * be made into the delimiter.
1094 * Discard second to last entry,
1095 * since it is presumably smaller than the last
1096 * and move the last entry back one.
1097 */
1098 bp--;
1099 printf("%s: rmap ovflo, lost [%d,%d)\n", mp->m_name,
1100 (bp-1)->m_addr, (bp-1)->m_addr+(bp-1)->m_size);
1101 bp[-1] = bp[0];
1102 bp[0].m_size = bp[0].m_addr = 0;
1103 }
1104done:
1105 return;
1106badrmfree:
1107 printf("bad rmfree\n");
ceb84881 1108}
76ea98af
KM
1109/*
1110 * "addr" is a kern virt addr and does not correspond
1111 * To a phys addr after zipping out the high bit..
1112 * since it was valloc'd in the kernel.
1113 *
1114 * We return the phys addr by simulating kernel vm (/dev/kmem)
1115 * when we are reading a crash dump.
1116 */
9ed2dfb9 1117off_t
76ea98af 1118mkphys(addr)
9ed2dfb9 1119 off_t addr;
76ea98af 1120{
9ed2dfb9 1121 register off_t o;
76ea98af
KM
1122
1123 if (!kflg)
1124 return(addr);
f20270fc 1125 addr = clear(addr);
76ea98af
KM
1126 o = addr & PGOFSET;
1127 addr >>= PGSHIFT;
1128 addr &= PG_PFNUM;
1129 addr *= NBPW;
dc2a22f1 1130 addr = getword(nl[SYSMAP].n_value + addr);
76ea98af
KM
1131 addr = ((addr & PG_PFNUM) << PGSHIFT) | o;
1132 return(addr);
1133}