|
|
1.1 root 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:
7: #ifndef lint
8: char 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
14: static char sccsid[] = "@(#)pstat.c 5.26 (Berkeley) 6/29/90";
15: #endif /* not lint */
16:
17: /*
18: * Print system stuff
19: */
20: #include <sys/param.h>
21: #include <sys/user.h>
22: #include <sys/proc.h>
23: #include <sys/text.h>
24: #include <sys/time.h>
25: #include <sys/vnode.h>
26: #include <sys/map.h>
27: #define KERNEL
28: #define NFS
29: #include <sys/file.h>
30: #include <sys/mount.h>
31: #include <ufs/quota.h>
32: #include <ufs/inode.h>
33: #include <sys/stat.h>
34: #include <nfs/nfsv2.h>
35: #include <nfs/nfs.h>
36: #include <nfs/nfsnode.h>
37: #include <sys/ioctl.h>
38: #include <sys/tty.h>
39: #undef KERNEL
40: #include <sys/conf.h>
41: #include <sys/vm.h>
42: #include <machine/pte.h>
43:
44: #include <kvm.h>
45: #include <nlist.h>
46: #include <stdio.h>
47: #include "pathnames.h"
48:
49: #define mask(x) (x&0377)
50: #define clear(x) ((int)x &~ KERNBASE)
51:
52: char *fnlist = NULL;
53: char *fcore = NULL;
54:
55: struct nlist nl[] = {
56: #define STEXT 0
57: { "_text" },
58: #define SCONS 1
59: { "_cons" },
60: #define SPROC 2
61: { "_proc" },
62: #define SFIL 3
63: { "_file" },
64: #define SWAPMAP 4
65: { "_swapmap" },
66: #define SNPROC 5
67: { "_nproc" },
68: #define SNTEXT 6
69: { "_ntext" },
70: #define SNFILE 7
71: { "_nfile" },
72: #define SNSWAPMAP 8
73: { "_nswapmap" },
74: #define SPTY 9
75: { "_pt_tty" },
76: #define SDMMIN 10
77: { "_dmmin" },
78: #define SDMMAX 11
79: { "_dmmax" },
80: #define SNSWDEV 12
81: { "_nswdev" },
82: #define SSWDEVT 13
83: { "_swdevt" },
84: #define SNPTY 14
85: { "_npty" },
86: #ifdef vax
87: #define SDZ (SNPTY+1)
88: { "_dz_tty" },
89: #define SNDZ (SNPTY+2)
90: { "_dz_cnt" },
91: #define SDMF (SNPTY+3)
92: { "_dmf_tty" },
93: #define SNDMF (SNPTY+4)
94: { "_ndmf" },
95: #define SDH (SNPTY+5)
96: { "_dh11" },
97: #define SNDH (SNPTY+6)
98: { "_ndh11" },
99: #define SDHU (SNPTY+7)
100: { "_dhu_tty" },
101: #define SNDHU (SNPTY+8)
102: { "_ndhu" },
103: #define SDMZ (SNPTY+9)
104: { "_dmz_tty" },
105: #define SNDMZ (SNPTY+10)
106: { "_ndmz" },
107: #define SQD (SNPTY+11)
108: { "_qd_tty" },
109: #define SNQD (SNPTY+12)
110: { "_nNQD" },
111: #endif
112: #ifdef tahoe
113: #define SVX (SNPTY+1)
114: { "_vx_tty" },
115: #define SNVX (SNPTY+2)
116: { "_nvx" },
117: #define SMP (SNPTY+3)
118: { "_mp_tty" },
119: #define SNMP (SNPTY+4)
120: { "_nmp" },
121: #endif
122: { "" }
123: };
124:
125: int vnof;
126: int txtf;
127: int prcf;
128: int ttyf;
129: int usrf;
130: int upid;
131: int filf;
132: int swpf;
133: int totflg;
134: char partab[1];
135: struct cdevsw cdevsw[1];
136: struct bdevsw bdevsw[1];
137: int allflg;
138: int nflg;
139: u_long getword();
140: off_t mkphys();
141:
142: char *Program;
143:
144: main(argc, argv)
145: int argc;
146: char **argv;
147: {
148: extern char *optarg;
149: extern int optind;
150: int ch;
151:
152: Program = argv[0];
153: while ((ch = getopt(argc, argv, "Tafvikptu:sxn")) != EOF)
154: switch((char)ch) {
155: case 'T':
156: totflg++;
157: break;
158: case 'a':
159: allflg++;
160: /*FALLTHROUGH*/
161: case 'p':
162: prcf++;
163: break;
164: case 'f':
165: filf++;
166: break;
167: case 'v':
168: case 'i':
169: vnof++;
170: break;
171: case 't':
172: ttyf++;
173: break;
174: case 'u':
175: usrf++;
176: sscanf(optarg, "%d", &upid);
177: break;
178: case 's':
179: swpf++;
180: break;
181: case 'x':
182: txtf++;
183: break;
184: case 'n':
185: nflg++;
186: break;
187: case '?':
188: default:
189: printf("usage: pstat -[Tafiptsx] [-u [pid]] [system] [core]\n");
190: exit(1);
191: }
192: argc -= optind;
193: argv += optind;
194:
195: if (argc > 1)
196: fcore = argv[1];
197: if (argc > 0)
198: fnlist = argv[0];
199: if (kvm_openfiles(fnlist, fcore, NULL) == -1) {
200: syserror("kvm_openfiles: %s", kvm_geterr());
201: exit(1);
202: }
203: if (kvm_nlist(nl) != 0) {
204: syserror("kvm_nlist: %s", kvm_geterr());
205: exit(1);
206: }
207: if (!(filf | totflg | vnof | prcf | txtf | ttyf | usrf | swpf)) {
208: printf("pstat: one or more of -[aivxptfsu] is required\n");
209: exit(1);
210: }
211: if (filf||totflg)
212: dofile();
213: if (vnof||totflg)
214: dovnode();
215: if (prcf||totflg)
216: doproc();
217: if (txtf||totflg)
218: dotext();
219: if (ttyf)
220: dotty();
221: if (usrf)
222: dousr();
223: if (swpf||totflg)
224: doswap();
225: }
226:
227: struct e_vnode {
228: struct vnode *avnode;
229: struct vnode vnode;
230: };
231:
232: dovnode()
233: {
234: register struct e_vnode *e_vnodebase, *endvnode, *evp;
235: register struct vnode *vp;
236: register struct mount *maddr = NULL, *mp;
237: register struct inode *ip;
238: int numvnodes;
239: struct e_vnode *loadvnodes();
240: struct mount *getmnt();
241:
242: e_vnodebase = loadvnodes(&numvnodes);
243: if (totflg) {
244: printf("%7d vnodes\n", numvnodes);
245: return;
246: }
247: endvnode = e_vnodebase + numvnodes;
248: printf("%d active vnodes\n", numvnodes);
249:
250:
251: #define ST mp->mnt_stat
252: for (evp = e_vnodebase; evp < endvnode; evp++) {
253: vp = &evp->vnode;
254: if (vp->v_mount != maddr) {
255: /*
256: * New filesystem
257: */
258: if ((mp = getmnt(vp->v_mount)) == NULL)
259: continue;
260: maddr = vp->v_mount;
261: mount_print(mp);
262: vnode_header();
263: switch(ST.f_type) {
264: case MOUNT_UFS:
265: case MOUNT_MFS:
266: ufs_header();
267: break;
268: case MOUNT_NFS:
269: nfs_header();
270: break;
271: case MOUNT_NONE:
272: case MOUNT_PC:
273: default:
274: break;
275: }
276: printf("\n");
277: }
278: vnode_print(evp->avnode, vp);
279: switch(ST.f_type) {
280: case MOUNT_UFS:
281: case MOUNT_MFS:
282: ufs_print(vp);
283: break;
284: case MOUNT_NFS:
285: nfs_print(vp);
286: break;
287: case MOUNT_NONE:
288: case MOUNT_PC:
289: default:
290: break;
291: }
292: printf("\n");
293: }
294: free(e_vnodebase);
295: }
296:
297: vnode_header()
298: {
299: printf("ADDR TYP VFLAG USE REF");
300: }
301:
302: vnode_print(avnode, vp)
303: struct vnode *avnode;
304: struct vnode *vp;
305: {
306: char *type, flags[16];
307: char *fp = flags;
308: register flag;
309:
310: /*
311: * set type
312: */
313: switch(vp->v_type) {
314: case VNON:
315: type = "non"; break;
316: case VREG:
317: type = "reg"; break;
318: case VDIR:
319: type = "dir"; break;
320: case VBLK:
321: type = "blk"; break;
322: case VCHR:
323: type = "chr"; break;
324: case VLNK:
325: type = "lnk"; break;
326: case VSOCK:
327: type = "soc"; break;
328: case VFIFO:
329: type = "fif"; break;
330: case VBAD:
331: type = "bad"; break;
332: default:
333: type = "unk"; break;
334: }
335: /*
336: * gather flags
337: */
338: flag = vp->v_flag;
339: if (flag & VROOT)
340: *fp++ = 'R';
341: if (flag & VTEXT)
342: *fp++ = 'T';
343: if (flag & VXLOCK)
344: *fp++ = 'L';
345: if (flag & VXWANT)
346: *fp++ = 'W';
347: if (flag & VEXLOCK)
348: *fp++ = 'E';
349: if (flag & VSHLOCK)
350: *fp++ = 'S';
351: if (flag & VLWAIT)
352: *fp++ = 'T';
353: if (flag & VALIASED)
354: *fp++ = 'A';
355: if (flag & VBWAIT)
356: *fp++ = 'B';
357: if (flag == 0)
358: *fp++ = '-';
359: *fp = '\0';
360: /*
361: * print it
362: */
363: printf("%8x %s %5s %4d %4d",
364: avnode, type, flags, vp->v_usecount, vp->v_holdcnt);
365: }
366:
367: ufs_header()
368: {
369: printf(" FILEID IFLAG RDEV|SZ");
370: }
371:
372: ufs_print(vp)
373: struct vnode *vp;
374: {
375: struct inode *ip = VTOI(vp);
376: char flagbuf[16], *flags = flagbuf;
377: register flag;
378: char *name;
379: mode_t type;
380: extern char *devname();
381:
382: flag = ip->i_flag;
383: if (flag & ILOCKED)
384: *flags++ = 'L';
385: if (flag & IWANT)
386: *flags++ = 'W';
387: if (flag & IRENAME)
388: *flags++ = 'R';
389: if (flag & IUPD)
390: *flags++ = 'U';
391: if (flag & IACC)
392: *flags++ = 'A';
393: if (flag & ICHG)
394: *flags++ = 'C';
395: if (flag & IMOD)
396: *flags++ = 'M';
397: if (flag & ISHLOCK)
398: *flags++ = 'S';
399: if (flag & IEXLOCK)
400: *flags++ = 'E';
401: if (flag & ILWAIT)
402: *flags++ = 'Z';
403: if (flag == 0)
404: *flags++ = '-';
405: *flags = '\0';
406:
407: printf(" %6d %5s", ip->i_number, flagbuf);
408: type = ip->i_mode & S_IFMT;
409: if (type == S_IFCHR || type == S_IFBLK)
410: if (nflg || ((name = devname(ip->i_rdev, type)) == NULL))
411: printf(" %2d,%-2d",
412: major(ip->i_rdev), minor(ip->i_rdev));
413: else
414: printf(" %7s", name);
415: else
416: printf(" %7d", ip->i_size);
417: }
418:
419: nfs_header()
420: {
421: printf(" FILEID NFLAG RDEV|SZ");
422: }
423:
424: nfs_print(vp)
425: struct vnode *vp;
426: {
427: struct nfsnode *np = VTONFS(vp);
428: char flagbuf[16], *flags = flagbuf;
429: register flag;
430: char *name;
431: mode_t type;
432: extern char *devname();
433:
434: flag = np->n_flag;
435: if (flag & NLOCKED)
436: *flags++ = 'L';
437: if (flag & NWANT)
438: *flags++ = 'W';
439: if (flag & NMODIFIED)
440: *flags++ = 'M';
441: if (flag & NWRITEERR)
442: *flags++ = 'E';
443: if (flag == 0)
444: *flags++ = '-';
445: *flags = '\0';
446:
447: #define VT np->n_vattr
448: printf(" %6d %5s", VT.va_fileid, flagbuf);
449: type = VT.va_mode & S_IFMT;
450: if (type == S_IFCHR || type == S_IFBLK)
451: if (nflg || ((name = devname(VT.va_rdev, type)) == NULL))
452: printf(" %2d,%-2d",
453: major(VT.va_rdev), minor(VT.va_rdev));
454: else
455: printf(" %7s", name);
456: else
457: printf(" %7d", np->n_size);
458: }
459:
460: /*
461: * Given a pointer to a mount structure in kernel space,
462: * read it in and return a usable pointer to it.
463: */
464: struct mount *
465: getmnt(maddr)
466: struct mount *maddr;
467: {
468: static struct mtab {
469: struct mtab *next;
470: struct mount *maddr;
471: struct mount mount;
472: } *mhead = NULL;
473: register struct mtab *mt;
474:
475: for (mt = mhead; mt != NULL; mt = mt->next)
476: if (maddr == mt->maddr)
477: return (&mt->mount);
478: if ((mt = (struct mtab *)malloc(sizeof (struct mtab))) == NULL) {
479: error("out of memory");
480: exit(1);
481: }
482: if (kvm_read((off_t)maddr, &mt->mount, sizeof(struct mount)) !=
483: sizeof(struct mount)) {
484: error("can't read mount table at %x", maddr);
485: return (NULL);
486: }
487: mt->maddr = maddr;
488: mt->next = mhead;
489: mhead = mt;
490: return (&mt->mount);
491: }
492:
493: mount_print(mp)
494: struct mount *mp;
495: {
496: char *type = "unknown";
497: register flags;
498:
499: #define ST mp->mnt_stat
500: printf("*** MOUNT ");
501: switch (ST.f_type) {
502: case MOUNT_NONE:
503: type = "none";
504: break;
505: case MOUNT_UFS:
506: type = "ufs";
507: break;
508: case MOUNT_NFS:
509: type = "nfs";
510: break;
511: case MOUNT_MFS:
512: type = "mfs";
513: break;
514: case MOUNT_PC:
515: type = "pc";
516: break;
517: }
518: printf("%s %s on %s", type, ST.f_mntfromname, ST.f_mntonname);
519: if (flags = mp->mnt_flag) {
520: char *comma = "(";
521:
522: putchar(' ');
523: /* user visable flags */
524: if (flags & MNT_RDONLY) {
525: printf("%srdonly", comma);
526: flags &= ~MNT_RDONLY;
527: comma = ",";
528: }
529: if (flags & MNT_SYNCHRONOUS) {
530: printf("%ssynchronous", comma);
531: flags &= ~MNT_SYNCHRONOUS;
532: comma = ",";
533: }
534: if (flags & MNT_NOEXEC) {
535: printf("%snoexec", comma);
536: flags &= ~MNT_NOEXEC;
537: comma = ",";
538: }
539: if (flags & MNT_NOSUID) {
540: printf("%snosuid", comma);
541: flags &= ~MNT_NOSUID;
542: comma = ",";
543: }
544: if (flags & MNT_NODEV) {
545: printf("%snodev", comma);
546: flags &= ~MNT_NODEV;
547: comma = ",";
548: }
549: if (flags & MNT_EXPORTED) {
550: printf("%sexport", comma);
551: flags &= ~MNT_EXPORTED;
552: comma = ",";
553: }
554: if (flags & MNT_EXRDONLY) {
555: printf("%sexrdonly", comma);
556: flags &= ~MNT_EXRDONLY;
557: comma = ",";
558: }
559: if (flags & MNT_LOCAL) {
560: printf("%slocal", comma);
561: flags &= ~MNT_LOCAL;
562: comma = ",";
563: }
564: if (flags & MNT_QUOTA) {
565: printf("%squota", comma);
566: flags &= ~MNT_QUOTA;
567: comma = ",";
568: }
569: /* filesystem control flags */
570: if (flags & MNT_UPDATE) {
571: printf("%supdate", comma);
572: flags &= ~MNT_UPDATE;
573: comma = ",";
574: }
575: if (flags & MNT_MLOCK) {
576: printf("%slock", comma);
577: flags &= ~MNT_MLOCK;
578: comma = ",";
579: }
580: if (flags & MNT_MWAIT) {
581: printf("%swait", comma);
582: flags &= ~MNT_MWAIT;
583: comma = ",";
584: }
585: if (flags & MNT_MPBUSY) {
586: printf("%sbusy", comma);
587: flags &= ~MNT_MPBUSY;
588: comma = ",";
589: }
590: if (flags & MNT_MPWANT) {
591: printf("%swant", comma);
592: flags &= ~MNT_MPWANT;
593: comma = ",";
594: }
595: if (flags & MNT_UNMOUNT) {
596: printf("%sunmount", comma);
597: flags &= ~MNT_UNMOUNT;
598: comma = ",";
599: }
600: if (flags)
601: printf("%sunknown_flags:%x", flags);
602: printf(")");
603: }
604: printf("\n");
605: #undef ST
606: }
607:
608: struct e_vnode *
609: loadvnodes(avnodes)
610: int *avnodes;
611: {
612: int ret, copysize, i;
613: struct e_vnode *vnodebase;
614:
615: if (fcore != NULL) {
616: error("vnodes on dead kernel, not impl yet\n");
617: exit(1);
618: }
619: if ((ret = getkerninfo(KINFO_VNODE, NULL, NULL, 0)) == -1) {
620: syserror("can't get estimate for kerninfo");
621: exit(1);
622: }
623: copysize = ret;
624: if ((vnodebase = (struct e_vnode *)malloc(copysize))
625: == NULL) {
626: error("out of memory");
627: exit(1);
628: }
629: if ((ret = getkerninfo(KINFO_VNODE, vnodebase, ©size, 0))
630: == -1) {
631: syserror("can't get vnode list");
632: exit(1);
633: }
634: if (copysize % sizeof (struct e_vnode)) {
635: error("vnode size mismatch");
636: error(1);
637: }
638: *avnodes = copysize / sizeof (struct e_vnode);
639:
640: return (vnodebase);
641: }
642:
643: u_long
644: getword(loc)
645: off_t loc;
646: {
647: u_long word;
648:
649: kvm_read(loc, &word, sizeof (word));
650: return (word);
651: }
652:
653: putf(v, n)
654: {
655: if (v)
656: printf("%c", n);
657: else
658: printf(" ");
659: }
660:
661: dotext()
662: {
663: register struct text *xp;
664: int ntext;
665: struct text *xtext, *atext;
666: int ntx, ntxca;
667:
668: ntx = ntxca = 0;
669: ntext = getword(nl[SNTEXT].n_value);
670: xtext = (struct text *)calloc(ntext, sizeof (struct text));
671: atext = (struct text *)getword(nl[STEXT].n_value);
672: if (ntext < 0 || ntext > 10000) {
673: fprintf(stderr, "number of texts is preposterous (%d)\n",
674: ntext);
675: return;
676: }
677: if (xtext == NULL) {
678: fprintf(stderr, "can't allocate memory for text table\n");
679: return;
680: }
681: kvm_read(atext, xtext, ntext * sizeof (struct text));
682: for (xp = xtext; xp < &xtext[ntext]; xp++) {
683: if (xp->x_vptr != NULL)
684: ntxca++;
685: if (xp->x_count != 0)
686: ntx++;
687: }
688: if (totflg) {
689: printf("%3d/%3d texts active, %3d used\n", ntx, ntext, ntxca);
690: return;
691: }
692: printf("%d/%d active texts, %d used\n", ntx, ntext, ntxca);
693: printf("\
694: LOC FLAGS DADDR CADDR RSS SIZE VPTR CNT CCNT FORW BACK\n");
695: for (xp = xtext; xp < &xtext[ntext]; xp++) {
696: if (xp->x_vptr == NULL)
697: continue;
698: printf("%8.1x", atext + (xp - xtext));
699: printf(" ");
700: putf(xp->x_flag&XPAGV, 'P');
701: putf(xp->x_flag&XTRC, 'T');
702: putf(xp->x_flag&XWRIT, 'W');
703: putf(xp->x_flag&XLOAD, 'L');
704: putf(xp->x_flag&XLOCK, 'K');
705: putf(xp->x_flag&XWANT, 'w');
706: printf("%5x", xp->x_daddr[0]);
707: printf("%10x", xp->x_caddr);
708: printf("%5d", xp->x_rssize);
709: printf("%5d", xp->x_size);
710: printf("%10.1x", xp->x_vptr);
711: printf("%5d", xp->x_count&0377);
712: printf("%5d", xp->x_ccount);
713: printf("%10x", xp->x_forw);
714: printf("%9x", xp->x_back);
715: printf("\n");
716: }
717: free(xtext);
718: }
719:
720: doproc()
721: {
722: struct proc *xproc, *aproc;
723: int nproc;
724: register struct proc *pp;
725: register loc, np;
726: struct pte apte;
727:
728: nproc = getword(nl[SNPROC].n_value);
729: xproc = (struct proc *)calloc(nproc, sizeof (struct proc));
730: aproc = (struct proc *)getword(nl[SPROC].n_value);
731: if (nproc < 0 || nproc > 10000) {
732: fprintf(stderr, "number of procs is preposterous (%d)\n",
733: nproc);
734: return;
735: }
736: if (xproc == NULL) {
737: fprintf(stderr, "can't allocate memory for proc table\n");
738: return;
739: }
740: kvm_read(aproc, xproc, nproc * sizeof (struct proc));
741: np = 0;
742: for (pp=xproc; pp < &xproc[nproc]; pp++)
743: if (pp->p_stat)
744: np++;
745: if (totflg) {
746: printf("%3d/%3d processes\n", np, nproc);
747: return;
748: }
749: printf("%d/%d processes\n", np, nproc);
750: printf(" LOC S F POIP PRI SIG UID SLP TIM CPU NI PID PPID ADDR RSS SRSS SIZE WCHAN LINK TEXTP\n");
751: for (pp=xproc; pp<&xproc[nproc]; pp++) {
752: if (pp->p_stat==0 && allflg==0)
753: continue;
754: printf("%8x", aproc + (pp - xproc));
755: printf(" %2d", pp->p_stat);
756: printf(" %8x", pp->p_flag);
757: printf(" %4d", pp->p_poip);
758: printf(" %3d", pp->p_pri);
759: printf(" %8x", pp->p_sig);
760: printf(" %4d", pp->p_uid);
761: printf(" %3d", pp->p_slptime);
762: printf(" %3d", pp->p_time);
763: printf(" %4d", pp->p_cpu&0377);
764: printf(" %3d", pp->p_nice);
765: printf(" %6d", pp->p_pid);
766: printf(" %6d", pp->p_ppid);
767: /*
768: if (pp->p_flag & SLOAD) {
769: kvm_read(pp->p_addr, &apte, sizeof(apte));
770: printf(" %8x", apte.pg_pfnum);
771: } else
772: printf(" %8x", pp->p_swaddr);
773: */
774: printf(" %4x", pp->p_rssize);
775: printf(" %4x", pp->p_swrss);
776: printf(" %5x", pp->p_dsize+pp->p_ssize);
777: printf(" %7x", clear(pp->p_wchan));
778: printf(" %7x", clear(pp->p_link));
779: printf(" %7x", clear(pp->p_textp));
780: printf("\n");
781: }
782: free(xproc);
783: }
784:
785: char mesg[] = "LINE RAW CAN OUT RCC CCC OCC HWT LWT ADDR COL STATE PGID DISC\n";
786: int ttyspace = 128;
787: struct tty *tty;
788:
789: dotty()
790: {
791:
792: if ((tty = (struct tty *)malloc(ttyspace * sizeof(*tty))) == 0) {
793: printf("pstat: out of memory\n");
794: return;
795: }
796: printf("1 cons\n");
797: kvm_read((long)nl[SCONS].n_value, tty, sizeof(*tty));
798: printf(mesg);
799: ttyprt(&tty[0], 0);
800: #ifdef vax
801: if (nl[SNQD].n_type != 0)
802: doqdss();
803: if (nl[SNDZ].n_type != 0)
804: dottytype("dz", SDZ, SNDZ);
805: if (nl[SNDH].n_type != 0)
806: dottytype("dh", SDH, SNDH);
807: if (nl[SNDMF].n_type != 0)
808: dottytype("dmf", SDMF, SNDMF);
809: if (nl[SNDHU].n_type != 0)
810: dottytype("dhu", SDHU, SNDHU);
811: if (nl[SNDMZ].n_type != 0)
812: dottytype("dmz", SDMZ, SNDMZ);
813: #endif
814: #ifdef tahoe
815: if (nl[SNVX].n_type != 0)
816: dottytype("vx", SVX, SNVX);
817: if (nl[SNMP].n_type != 0)
818: dottytype("mp", SMP, SNMP);
819: #endif
820: if (nl[SNPTY].n_type != 0)
821: dottytype("pty", SPTY, SNPTY);
822: }
823:
824: /*
825: * Special case the qdss: there are 4 ttys per qdss,
826: * but only the first of each is used as a tty.
827: */
828: #ifdef vax
829: doqdss()
830: {
831: int nqd;
832: register struct tty *tp;
833:
834: kvm_read((long)nl[SNQD].n_value, &nqd, sizeof(nqd));
835: printf("%d qd\n", nqd);
836: kvm_read((long)nl[SQD].n_value, tty, nqd * sizeof(struct tty) * 4);
837: printf(mesg);
838: for (tp = tty; tp < &tty[nqd * 4]; tp += 4)
839: ttyprt(tp, tp - tty);
840: }
841: #endif
842:
843: dottytype(name, type, number)
844: char *name;
845: {
846: int ntty;
847: register struct tty *tp;
848: extern char *realloc();
849:
850: if (tty == (struct tty *)0)
851: return;
852: kvm_read((long)nl[number].n_value, &ntty, sizeof(ntty));
853: printf("%d %s lines\n", ntty, name);
854: if (ntty > ttyspace) {
855: ttyspace = ntty;
856: if ((tty = (struct tty *)realloc(tty, ttyspace * sizeof(*tty))) == 0) {
857: printf("pstat: out of memory\n");
858: return;
859: }
860: }
861: kvm_read((long)nl[type].n_value, tty, ntty * sizeof(struct tty));
862: printf(mesg);
863: for (tp = tty; tp < &tty[ntty]; tp++)
864: ttyprt(tp, tp - tty);
865: }
866:
867: struct {
868: int flag;
869: char val;
870: } ttystates[] = {
871: TS_WOPEN, 'W',
872: TS_ISOPEN, 'O',
873: TS_CARR_ON, 'C',
874: TS_TIMEOUT, 'T',
875: TS_FLUSH, 'F',
876: TS_BUSY, 'B',
877: TS_ASLEEP, 'A',
878: TS_XCLUDE, 'X',
879: TS_TTSTOP, 'S',
880: TS_HUPCLS, 'H',
881: TS_TBLOCK, 'K',
882: TS_RCOLL, 'R',
883: TS_WCOLL, 'I', /* running short on letters ! */
884: TS_ASYNC, 'Y',
885: TS_BKSL, 'D',
886: TS_ERASE, 'E',
887: TS_LNCH, 'L',
888: TS_TYPEN, 'P',
889: TS_CNTTB, 'N',
890: 0, 0
891: };
892:
893: ttyprt(atp, line)
894: struct tty *atp;
895: {
896: register struct tty *tp;
897: char state[20];
898: register i, j;
899: char *name;
900: extern char *devname();
901: pid_t pgid;
902:
903: tp = atp;
904: if (nflg || tp->t_dev == 0 || /* XXX */
905: (name = devname(tp->t_dev, S_IFCHR)) == NULL)
906: printf("%7d ", line);
907: else
908: printf("%7s ", name);
909: printf("%2d %3d ", tp->t_rawq.c_cc, tp->t_canq.c_cc);
910: printf("%3d %6d %6d %6d %4d %3d %8x %3d ", tp->t_outq.c_cc,
911: tp->t_rawcc, tp->t_cancc, tp->t_outcc,
912: tp->t_hiwat, tp->t_lowat, tp->t_addr, tp->t_col);
913: for (i = j = 0; ttystates[i].flag; i++)
914: if (tp->t_state&ttystates[i].flag)
915: state[j++] = ttystates[i].val;
916: state[j] = '\0';
917: printf("%-4s ", state);
918: if (tp->t_pgrp == NULL || kvm_read(&tp->t_pgrp->pg_id, &pgid,
919: sizeof (pid_t)) != sizeof (pid_t))
920: pgid = 0;
921: printf("%6d ", pgid);
922: switch (tp->t_line) {
923:
924: case 0:
925: printf("term\n");
926: break;
927:
928: case TABLDISC:
929: printf("tab\n");
930: break;
931:
932: case SLIPDISC:
933: printf("slip\n");
934: break;
935:
936: default:
937: printf("%d\n", tp->t_line);
938: }
939: }
940:
941: dousr()
942: {
943: #ifdef notyet
944: register struct user *up;
945: register i, j, *ip;
946: register struct nameidata *nd = &U.u_nd;
947: struct proc *p;
948:
949: /* This wins only if CLBYTES >= sizeof (struct user) */
950: /* (WHICH IT ISN'T, but u. is going away - so who cares */
951: if (kvm_getprocs(KINFO_PROC_PID, upid) != 0) {
952: error("kvm_getproc: %s", kvm_geterr());
953: return (1);
954: }
955: if ((p = kvm_nextproc()); == NULL) {
956: error("kvm_nextproc: %s", kvm_geterr());
957: return (1);
958: }
959: if (up = kvm_getu(p)) == NULL) {
960: error("kvm_getu: %s", kvm_geterr());
961: return (1);
962: }
963: printf("pcb");
964: ip = (int *)&up->u_pcb;
965: while (ip < &up->u_arg[0]) {
966: if ((ip - (int *)&up->u_pcb) % 4 == 0)
967: printf("\t");
968: printf("%x ", *ip++);
969: if ((ip - (int *)&up->u_pcb) % 4 == 0)
970: printf("\n");
971: }
972: if ((ip - (int *)&up->u_pcb) % 4 != 0)
973: printf("\n");
974: printf("arg");
975: for (i=0; i<sizeof(up->u_arg)/sizeof(up->u_arg[0]); i++) {
976: if (i%5==0)
977: printf("\t");
978: printf(" %.1x", up->u_arg[i]);
979: if (i%5==4)
980: printf("\n");
981: }
982: if (i%5)
983: printf("\n");
984: printf("segflg\t%d\nerror %d\n", nd->ni_segflg, up->u_error);
985: printf("uids\t%d,%d,%d,%d\n", up->u_uid,up->u_gid,up->u_ruid,up->u_rgid);
986: printf("procp\t%.1x\n", up->u_procp);
987: printf("ap\t%.1x\n", up->u_ap);
988: printf("r_val?\t%.1x %.1x\n", up->u_r.r_val1, up->u_r.r_val2);
989: printf("base, count, offset %.1x %.1x %ld\n", nd->ni_base,
990: nd->ni_count, nd->ni_offset);
991: printf("cdir rdir %.1x %.1x\n", up->u_cdir, up->u_rdir);
992: printf("dirp %.1x\n", nd->ni_dirp);
993: printf("dent %d %.14s\n", nd->ni_dent.d_ino, nd->ni_dent.d_name);
994: printf("dvp vp %.1x %.1x\n", nd->ni_dvp, nd->ni_vp);
995: printf("file");
996: for (i=0; i<NOFILE; i++) {
997: if (i % 8 == 0)
998: printf("\t");
999: printf("%9.1x", up->u_ofile[i]);
1000: if (i % 8 == 7)
1001: printf("\n");
1002: }
1003: if (i % 8)
1004: printf("\n");
1005: printf("pofile");
1006: for (i=0; i<NOFILE; i++) {
1007: if (i % 8 == 0)
1008: printf("\t");
1009: printf("%9.1x", up->u_pofile[i]);
1010: if (i % 8 == 7)
1011: printf("\n");
1012: }
1013: if (i % 8)
1014: printf("\n");
1015: printf("ssave");
1016: for (i=0; i<sizeof(label_t)/sizeof(int); i++) {
1017: if (i%5==0)
1018: printf("\t");
1019: printf("%9.1x", up->u_ssave.val[i]);
1020: if (i%5==4)
1021: printf("\n");
1022: }
1023: if (i%5)
1024: printf("\n");
1025: printf("sigs");
1026: for (i=0; i<NSIG; i++) {
1027: if (i % 8 == 0)
1028: printf("\t");
1029: printf("%.1x ", up->u_signal[i]);
1030: if (i % 8 == 7)
1031: printf("\n");
1032: }
1033: if (i % 8)
1034: printf("\n");
1035: printf("code\t%.1x\n", up->u_code);
1036: printf("ar0\t%.1x\n", up->u_ar0);
1037: printf("prof\t%x %x %x %x\n", up->u_prof.pr_base, up->u_prof.pr_size,
1038: up->u_prof.pr_off, up->u_prof.pr_scale);
1039: printf("start\t%ld\n", up->u_start.tv_sec);
1040: printf("acflag\t%ld\n", up->u_acflag);
1041: printf("cmask\t%ld\n", up->u_cmask);
1042: printf("sizes\t%.1x %.1x %.1x\n", up->u_tsize, up->u_dsize, up->u_ssize);
1043: printf("ru\t");
1044: ip = (int *)&up->u_ru;
1045: for (i = 0; i < sizeof(up->u_ru)/sizeof(int); i++)
1046: printf("%ld ", ip[i]);
1047: printf("\n");
1048: ip = (int *)&up->u_cru;
1049: printf("cru\t");
1050: for (i = 0; i < sizeof(up->u_cru)/sizeof(int); i++)
1051: printf("%ld ", ip[i]);
1052: printf("\n");
1053: #ifdef notdef
1054: i = up->u_stack - &U;
1055: while (U[++i] == 0);
1056: i &= ~07;
1057: while (i < 512) {
1058: printf("%x ", 0140000+2*i);
1059: for (j=0; j<8; j++)
1060: printf("%9x", U[i++]);
1061: printf("\n");
1062: }
1063: #endif
1064: #endif
1065: }
1066:
1067: oatoi(s)
1068: char *s;
1069: {
1070: register v;
1071:
1072: v = 0;
1073: while (*s)
1074: v = (v<<3) + *s++ - '0';
1075: return(v);
1076: }
1077:
1078: dofile()
1079: {
1080: int nfile;
1081: struct file *xfile, *afile;
1082: register struct file *fp;
1083: register nf;
1084: int loc;
1085: static char *dtypes[] = { "???", "inode", "socket" };
1086:
1087: nf = 0;
1088: nfile = getword(nl[SNFILE].n_value);
1089: xfile = (struct file *)calloc(nfile, sizeof (struct file));
1090: afile = (struct file *)getword(nl[SFIL].n_value);
1091: if (nfile < 0 || nfile > 10000) {
1092: fprintf(stderr, "number of files is preposterous (%d)\n",
1093: nfile);
1094: return;
1095: }
1096: if (xfile == NULL) {
1097: fprintf(stderr, "can't allocate memory for file table\n");
1098: return;
1099: }
1100: kvm_read(afile, xfile, nfile * sizeof (struct file));
1101: for (fp=xfile; fp < &xfile[nfile]; fp++)
1102: if (fp->f_count)
1103: nf++;
1104: if (totflg) {
1105: printf("%3d/%3d files\n", nf, nfile);
1106: return;
1107: }
1108: printf("%d/%d open files\n", nf, nfile);
1109: printf(" LOC TYPE FLG CNT MSG DATA OFFSET\n");
1110: for (fp=xfile,loc=(int)afile; fp < &xfile[nfile]; fp++,loc+=sizeof(xfile[0])) {
1111: if (fp->f_count==0)
1112: continue;
1113: printf("%8x ", loc);
1114: if (fp->f_type <= DTYPE_SOCKET)
1115: printf("%-8.8s", dtypes[fp->f_type]);
1116: else
1117: printf("%8d", fp->f_type);
1118: putf(fp->f_flag&FREAD, 'R');
1119: putf(fp->f_flag&FWRITE, 'W');
1120: putf(fp->f_flag&FAPPEND, 'A');
1121: putf(fp->f_flag&FSHLOCK, 'S');
1122: putf(fp->f_flag&FEXLOCK, 'X');
1123: putf(fp->f_flag&FASYNC, 'I');
1124: printf(" %3d", mask(fp->f_count));
1125: printf(" %3d", mask(fp->f_msgcount));
1126: printf(" %8.1x", fp->f_data);
1127: if (fp->f_offset < 0)
1128: printf(" %x\n", fp->f_offset);
1129: else
1130: printf(" %ld\n", fp->f_offset);
1131: }
1132: free(xfile);
1133: }
1134:
1135: int dmmin, dmmax, nswdev;
1136:
1137: doswap()
1138: {
1139: struct proc *proc;
1140: int nproc;
1141: struct text *xtext;
1142: int ntext;
1143: struct map *swapmap;
1144: int nswapmap;
1145: struct swdevt *swdevt, *sw;
1146: register struct proc *pp;
1147: int nswap, used, tused, free, waste;
1148: int db, sb;
1149: register struct mapent *me;
1150: register struct text *xp;
1151: int i, j;
1152: long rmalloc();
1153:
1154: nproc = getword(nl[SNPROC].n_value);
1155: ntext = getword(nl[SNTEXT].n_value);
1156: if (nproc < 0 || nproc > 10000 || ntext < 0 || ntext > 10000) {
1157: fprintf(stderr, "number of procs/texts is preposterous (%d, %d)\n",
1158: nproc, ntext);
1159: return;
1160: }
1161: proc = (struct proc *)calloc(nproc, sizeof (struct proc));
1162: if (proc == NULL) {
1163: fprintf(stderr, "can't allocate memory for proc table\n");
1164: exit(1);
1165: }
1166: xtext = (struct text *)calloc(ntext, sizeof (struct text));
1167: if (xtext == NULL) {
1168: fprintf(stderr, "can't allocate memory for text table\n");
1169: exit(1);
1170: }
1171: nswapmap = getword(nl[SNSWAPMAP].n_value);
1172: swapmap = (struct map *)calloc(nswapmap, sizeof (struct map));
1173: if (swapmap == NULL) {
1174: fprintf(stderr, "can't allocate memory for swapmap\n");
1175: exit(1);
1176: }
1177: nswdev = getword(nl[SNSWDEV].n_value);
1178: swdevt = (struct swdevt *)calloc(nswdev, sizeof (struct swdevt));
1179: if (swdevt == NULL) {
1180: fprintf(stderr, "can't allocate memory for swdevt table\n");
1181: exit(1);
1182: }
1183: kvm_read(nl[SSWDEVT].n_value, swdevt, nswdev * sizeof (struct swdevt));
1184: kvm_read(nl[SPROC].n_value, proc, nproc * sizeof (struct proc));
1185: kvm_read(nl[STEXT].n_value, xtext, ntext * sizeof (struct text));
1186: kvm_read(nl[SWAPMAP].n_value, swapmap, nswapmap * sizeof (struct map));
1187:
1188: swapmap->m_name = "swap";
1189: swapmap->m_limit = (struct mapent *)&swapmap[nswapmap];
1190: dmmin = getword(nl[SDMMIN].n_value);
1191: dmmax = getword(nl[SDMMAX].n_value);
1192: nswap = 0;
1193: for (sw = swdevt; sw < &swdevt[nswdev]; sw++)
1194: if (sw->sw_freed)
1195: nswap += sw->sw_nblks;
1196: free = 0;
1197: for (me = (struct mapent *)(swapmap+1);
1198: me < (struct mapent *)&swapmap[nswapmap]; me++)
1199: free += me->m_size;
1200: tused = 0;
1201: for (xp = xtext; xp < &xtext[ntext]; xp++)
1202: if (xp->x_vptr!=NULL) {
1203: tused += ctod(clrnd(xp->x_size));
1204: if (xp->x_flag & XPAGV)
1205: tused += ctod(clrnd(ctopt(xp->x_size)));
1206: }
1207: used = tused;
1208: waste = 0;
1209: for (pp = proc; pp < &proc[nproc]; pp++) {
1210: if (pp->p_stat == 0 || pp->p_stat == SZOMB)
1211: continue;
1212: if (pp->p_flag & SSYS)
1213: continue;
1214: db = ctod(pp->p_dsize), sb = up(db);
1215: used += sb;
1216: waste += sb - db;
1217: db = ctod(pp->p_ssize), sb = up(db);
1218: used += sb;
1219: waste += sb - db;
1220: if ((pp->p_flag&SLOAD) == 0)
1221: used += ctod(vusize(pp));
1222: }
1223: if (totflg) {
1224: #define btok(x) ((x) / (1024 / DEV_BSIZE))
1225: printf("%3d/%3d 00k swap\n",
1226: btok(used/100), btok((used+free)/100));
1227: return;
1228: }
1229: printf("%dk used (%dk text), %dk free, %dk wasted, %dk missing\n",
1230: btok(used), btok(tused), btok(free), btok(waste),
1231: /* a dmmax/2 block goes to argmap */
1232: btok(nswap - dmmax/2 - (used + free)));
1233: printf("avail: ");
1234: for (i = dmmax; i >= dmmin; i /= 2) {
1235: j = 0;
1236: while (rmalloc(swapmap, i) != 0)
1237: j++;
1238: if (j) printf("%d*%dk ", j, btok(i));
1239: }
1240: free = 0;
1241: for (me = (struct mapent *)(swapmap+1);
1242: me < (struct mapent *)&swapmap[nswapmap]; me++)
1243: free += me->m_size;
1244: printf("%d*1k\n", btok(free));
1245: }
1246:
1247: up(size)
1248: register int size;
1249: {
1250: register int i, block;
1251:
1252: i = 0;
1253: block = dmmin;
1254: while (i < size) {
1255: i += block;
1256: if (block < dmmax)
1257: block *= 2;
1258: }
1259: return (i);
1260: }
1261:
1262: /*
1263: * Compute number of pages to be allocated to the u. area
1264: * and data and stack area page tables, which are stored on the
1265: * disk immediately after the u. area.
1266: */
1267: vusize(p)
1268: register struct proc *p;
1269: {
1270: register int tsz = p->p_tsize / NPTEPG;
1271:
1272: /*
1273: * We do not need page table space on the disk for page
1274: * table pages wholly containing text.
1275: */
1276: return (clrnd(UPAGES +
1277: clrnd(ctopt(p->p_tsize+p->p_dsize+p->p_ssize+UPAGES)) - tsz));
1278: }
1279:
1280: /*
1281: * Allocate 'size' units from the given
1282: * map. Return the base of the allocated space.
1283: * In a map, the addresses are increasing and the
1284: * list is terminated by a 0 size.
1285: *
1286: * Algorithm is first-fit.
1287: *
1288: * This routine knows about the interleaving of the swapmap
1289: * and handles that.
1290: */
1291: long
1292: rmalloc(mp, size)
1293: register struct map *mp;
1294: long size;
1295: {
1296: register struct mapent *ep = (struct mapent *)(mp+1);
1297: register int addr;
1298: register struct mapent *bp;
1299: swblk_t first, rest;
1300:
1301: if (size <= 0 || size > dmmax)
1302: return (0);
1303: /*
1304: * Search for a piece of the resource map which has enough
1305: * free space to accomodate the request.
1306: */
1307: for (bp = ep; bp->m_size; bp++) {
1308: if (bp->m_size >= size) {
1309: /*
1310: * If allocating from swapmap,
1311: * then have to respect interleaving
1312: * boundaries.
1313: */
1314: if (nswdev > 1 &&
1315: (first = dmmax - bp->m_addr%dmmax) < bp->m_size) {
1316: if (bp->m_size - first < size)
1317: continue;
1318: addr = bp->m_addr + first;
1319: rest = bp->m_size - first - size;
1320: bp->m_size = first;
1321: if (rest)
1322: rmfree(mp, rest, addr+size);
1323: return (addr);
1324: }
1325: /*
1326: * Allocate from the map.
1327: * If there is no space left of the piece
1328: * we allocated from, move the rest of
1329: * the pieces to the left.
1330: */
1331: addr = bp->m_addr;
1332: bp->m_addr += size;
1333: if ((bp->m_size -= size) == 0) {
1334: do {
1335: bp++;
1336: (bp-1)->m_addr = bp->m_addr;
1337: } while ((bp-1)->m_size = bp->m_size);
1338: }
1339: if (addr % CLSIZE)
1340: return (0);
1341: return (addr);
1342: }
1343: }
1344: return (0);
1345: }
1346:
1347: /*
1348: * Free the previously allocated space at addr
1349: * of size units into the specified map.
1350: * Sort addr into map and combine on
1351: * one or both ends if possible.
1352: */
1353: rmfree(mp, size, addr)
1354: struct map *mp;
1355: long size, addr;
1356: {
1357: struct mapent *firstbp;
1358: register struct mapent *bp;
1359: register int t;
1360:
1361: /*
1362: * Both address and size must be
1363: * positive, or the protocol has broken down.
1364: */
1365: if (addr <= 0 || size <= 0)
1366: goto badrmfree;
1367: /*
1368: * Locate the piece of the map which starts after the
1369: * returned space (or the end of the map).
1370: */
1371: firstbp = bp = (struct mapent *)(mp + 1);
1372: for (; bp->m_addr <= addr && bp->m_size != 0; bp++)
1373: continue;
1374: /*
1375: * If the piece on the left abuts us,
1376: * then we should combine with it.
1377: */
1378: if (bp > firstbp && (bp-1)->m_addr+(bp-1)->m_size >= addr) {
1379: /*
1380: * Check no overlap (internal error).
1381: */
1382: if ((bp-1)->m_addr+(bp-1)->m_size > addr)
1383: goto badrmfree;
1384: /*
1385: * Add into piece on the left by increasing its size.
1386: */
1387: (bp-1)->m_size += size;
1388: /*
1389: * If the combined piece abuts the piece on
1390: * the right now, compress it in also,
1391: * by shifting the remaining pieces of the map over.
1392: */
1393: if (bp->m_addr && addr+size >= bp->m_addr) {
1394: if (addr+size > bp->m_addr)
1395: goto badrmfree;
1396: (bp-1)->m_size += bp->m_size;
1397: while (bp->m_size) {
1398: bp++;
1399: (bp-1)->m_addr = bp->m_addr;
1400: (bp-1)->m_size = bp->m_size;
1401: }
1402: }
1403: goto done;
1404: }
1405: /*
1406: * Don't abut on the left, check for abutting on
1407: * the right.
1408: */
1409: if (addr+size >= bp->m_addr && bp->m_size) {
1410: if (addr+size > bp->m_addr)
1411: goto badrmfree;
1412: bp->m_addr -= size;
1413: bp->m_size += size;
1414: goto done;
1415: }
1416: /*
1417: * Don't abut at all. Make a new entry
1418: * and check for map overflow.
1419: */
1420: do {
1421: t = bp->m_addr;
1422: bp->m_addr = addr;
1423: addr = t;
1424: t = bp->m_size;
1425: bp->m_size = size;
1426: bp++;
1427: } while (size = t);
1428: /*
1429: * Segment at bp is to be the delimiter;
1430: * If there is not room for it
1431: * then the table is too full
1432: * and we must discard something.
1433: */
1434: if (bp+1 > mp->m_limit) {
1435: /*
1436: * Back bp up to last available segment.
1437: * which contains a segment already and must
1438: * be made into the delimiter.
1439: * Discard second to last entry,
1440: * since it is presumably smaller than the last
1441: * and move the last entry back one.
1442: */
1443: bp--;
1444: printf("%s: rmap ovflo, lost [%d,%d)\n", mp->m_name,
1445: (bp-1)->m_addr, (bp-1)->m_addr+(bp-1)->m_size);
1446: bp[-1] = bp[0];
1447: bp[0].m_size = bp[0].m_addr = 0;
1448: }
1449: done:
1450: return;
1451: badrmfree:
1452: printf("bad rmfree\n");
1453: }
1454:
1455: #include <varargs.h>
1456:
1457: error(va_alist)
1458: va_dcl
1459: {
1460: char *fmt;
1461: va_list ap;
1462: extern errno;
1463:
1464: fprintf(stderr, "%s: ", Program);
1465: va_start(ap);
1466: fmt = va_arg(ap, char *);
1467: (void) vfprintf(stderr, fmt, ap);
1468: va_end(ap);
1469: fprintf(stderr, "\n");
1470: }
1471:
1472: syserror(va_alist)
1473: va_dcl
1474: {
1475: char *fmt;
1476: va_list ap;
1477: extern errno;
1478:
1479: fprintf(stderr, "%s: ", Program);
1480: va_start(ap);
1481: fmt = va_arg(ap, char *);
1482: (void) vfprintf(stderr, fmt, ap);
1483: va_end(ap);
1484: fprintf(stderr, ": %s\n", strerror(errno));
1485: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.