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