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