|
|
1.1 root 1: #
2: /*
3: ps - show process status - iiasa version (jek)
4: originally from harvard and/or CULC
5:
6: flags are single letters
7: multiple flags can occur in one argument
8: dashes are optional but are needed to delimit lists of things
9: multiple lists are present(???)
10: flags that imply other arguments read the following arguments
11: until the end of the list or until an argument starts with dash
12: certain flags read exactly one argument
13: initialization (i flag) should be done for:
14: new users,
15: new kernel
16: parameters here must change to indicate:
17: new tty devices, max tty lines, tty letter changes
18: max users
19: new things to wait for
20: this program should be changed if:
21: proc structure makes this obsolete
22: etc
23: recompilation should occur if:
24: kernel structures and or paramters (nproc etc.) change
25: any above changes of course
26:
27: flags are:
28: a - show all processes that have pgrps except shells
29: b - show background (not detached)
30: c - show child times instead of process times
31: d - show detached processes inherited by init
32: e - show the environment with the args
33: f - show foreground jobs, connected to tty
34: g - show processes in given pgrps
35: h - unused
36: i - perform initialization (implies 'n')
37: j,k - unused
38: l - print long format. includes most good stuff
39: m - specify different memory file (file is next arg)
40: n - show no processes
41: o - unused
42: p - show only processes whose id's are in list (following args)
43: q - unused
44: r - repeat indefinitely (number of r's = seconds or r#)
45: s - show stopped processes
46: t - show only processes associated with ttys in list (following)
47: u - show only processes (or ancestors of) for users in list
48: v - be verbose - show the most information
49: w - wide format, show entire argument list (up to 512 chars)
50: x - show unattached processes - no pgrp. a+x gives shells also
51: y - unused
52: z - show zombies
53: A - show ALL information possible
54: B - show busy processes
55: F - go fast, avoid swap space.
56: G - print pgrp
57: U - use different UNIX file (next arg)
58: S - show size
59: T - show tty information
60: W - print wait channels in hex
61: */
62:
63: #include <signal.h>
64: #include <h/param.h>
65: #include <h/dir.h>
66: #include <h/user.h>
67: #include <h/proc.h>
68: #include <h/pte.h>
69: #include <h/vm.h>
70: #include <h/inode.h>
71: #include <h/file.h>
72: #include <h/buf.h>
73: #include <h/text.h>
74: #include <h/tty.h>
75: #include <h/conf.h>
76: #include <nlist.h>
77: #include <sys/stat.h>
78: #include <stdio.h>
79: #include <pwd.h>
80:
81:
82: #define TRUE 1
83: #define FALSE 0
84: #define INTPPG (NBPG/sizeof(int))
85: #define MAXARGPG 5
86:
87: #define Usrptmap ((struct pte *)info.kaddr[ausrptmap])
88: #define usrpt ((struct pte *)info.kaddr[ausrpt])
89: #define cswitch ((struct cdevsw *)info.kaddr[acdevsw])
90: struct proc *proc, *kproc;
91: struct text *text, *ktext;
92: struct buf *buf, *swbuf;
93: struct inode *inode;
94: int nproc, ntext, hz, nbuf, ninode, nfile, nswbuf;
95: union {
96: struct user user;
97: char upages[UPAGES][NBPG];
98: } user;
99: int pad1; /* supposedly to aviod hardware problem reading /dev/mem */
100: struct pte pagetable[UPAGES + MAXARGPG]; /* for users page table */
101: int pad2; /* supposedly to aviod hardware problem reading /dev/mem */
102:
103: #define u user.user
104: #define MSPID 2 /* max system pid, not to considered BUSY */
105:
106: #define MAXUSERS 256 /* total different users */
107: #define UNAMELENGTH 8 /* length of a user name */
108: #define NSPEC 15 /* number of specified things (proc, user, tty */
109: #define MAXTTYS 100
110:
111: /* definitions to reuse uninteresting proc table entries for linked lists */
112:
113: struct procinfo { /* structure to use for */
114: char *pi_cmd; /* attaching a time */
115: struct ttyline *pi_tty;
116: long pi_time; /* and an arg string to a proc */
117: };
118:
119: #define p_next p_link /* pointer to next proc in global list */
120: #define p_bro p_rlink /* next process with same parent */
121: #define p_son p_xlink /* first child of this process */
122: #define pinfo(p) (*((struct procinfo **)&p->p_sig))
123: #define procsize(p) ((p)->p_tsize + (p)->p_dsize + (p)->p_ssize)
124: /* size of process */
125: #define ABS(x) ((int)(x) & ~0x80000000) /* clear top bit - type int */
126: #define K 1024
127: #define KSHIFT 10
128:
129: #define msize(x) (x >> (KSHIFT-PGSHIFT))
130:
131: #define USERPAGE 0 /* flag for pread - read user page */
132: #define TOPMEM 1 /* flag for pread - read top of mem */
133:
134: struct proc *plist;
135: int mypid; /* pid of this process */
136:
137: char Aflag, aflag, Bflag, bflag, cflag, dflag, eflag, fflag, Fflag;
138: char Gflag, iflag, lflag, mflag, nflag, rflag, Sflag, sflag, Tflag;
139: char Uflag, uflag, vflag, wflag, xflag, nxflag, Wflag, zflag;
140: int select; /* flag indicating process selection */
141:
142: int ntotal, nbusy, nloaded, nswapped;
143: int ktotal, kbusy, kloaded, kswapped;
144:
145: /* specified users, ttys, pids, pgrps */
146: union numptr {
147: int nm_int;
148: char *nm_ptr;
149: };
150:
151: union ttyptr {
152: struct ttyline *ty_line;
153: char *ty_ptr;
154: };
155:
156: union numptr pids[NSPEC], *ppids = pids; /* specified process ids */
157: union numptr grps[NSPEC], *pgrps = grps; /* specified groups */
158: union numptr uids[NSPEC], *puids = uids; /* specified user ids */
159: union ttyptr ttys[NSPEC], *pttys = ttys; /* specified ttys */
160:
161: /* files needed by ps */
162:
163: char *memf = "/dev/mem"; /* default memory file */
164: int mem; /* memory file descriptor */
165: char *kmemf = "/dev/kmem"; /* virtual memory file */
166: int kmem; /* virtual memory file descriptor */
167: char *symf = "/vmunix"; /* default symbol file */
168: char *swapf = "/dev/swap"; /* default swap file */
169: int swap; /* swap area file descriptor */
170: char *infof = "/etc/spsinfo"; /* default info save file */
171: int infofd; /* info file descriptor */
172:
173: /* variables read from the kernel */
174:
175: struct nlist namelist[] = {
176: #define aproc 0
177: {"_proc"},
178: #define aswapdev 1
179: {"_swapdev"},
180: #define aswplo 2
181: {"_swplo"},
182: #define answbuf 3
183: {"_nswbuf"},
184: #define atext 4
185: {"_text"},
186: #define abuf 5
187: {"_buf"},
188: #define abfreeli 6
189: {"_bfreelist"},
190: #define akl11 7
191: {"_kl11"},
192: #define adh11 8
193: {"_dh11"},
194: #define alpdt 9
195: {"_lp_softc"},
196: #define albolt 10
197: {"_lbolt"},
198: #define atout 11
199: {"_tout"},
200: #define arunin 12
201: {"_runin"},
202: #define arunout 13
203: {"_runout"},
204: #define aipc 14
205: {"_ipc"},
206: #define afile 15
207: {"_file"},
208: #define ainode 16
209: {"_inode"},
210: #define amaplock 17
211: {"_maplock"},
212: #define acoremap 18
213: {"_coremap"},
214: #define aswapmap 19
215: {"_swapmap"},
216: #define au 20
217: {"_u"},
218: #define adz11 21
219: {"_dz_tty"},
220: #define aetext 22
221: {"_etext"},
222: #define ausrptmap 23
223: {"_Usrptmap"},
224: #define ausrpt 24
225: {"_usrpt"},
226: #define achtbuf 25
227: {"_chtbuf"},
228: #define arhtbuf 26
229: {"_rhtbuf"},
230: #define ahpbuf 27
231: {"_hpbuf"},
232: #define aswbuf 28
233: {"_swbuf"},
234: #define arswbuf 29
235: {"_rswbuf"},
236: #define acons 30
237: {"_cons"},
238: #define ark7 31
239: {"_rrk7buf"},
240: #define achrfclist 32
241: {"_Chrfclist"},
242: #define anproc 33
243: {"_nproc"},
244: #define antext 34
245: {"_ntext"},
246: #define anbuf 35
247: {"_nbuf"},
248: #define ahz 36
249: {"_hz"},
250: #define aninode 37
251: {"_ninode"},
252: #define anfile 38
253: {"_nfile"},
254: #define answap 39
255: {"_nswap"},
256: #define acdevsw 40
257: {"_cdevsw"},
258: #define aChconntab 41
259: {"_Chconntab"},
260: #define MAXSYMBOLS 42
261: {"", 0, 0},
262: };
263:
264: /* this structure is read from info file or initialized (iflag) */
265:
266: struct {
267: caddr_t kaddr[MAXSYMBOLS]; /* useful kernel addresses */
268: char unames[MAXUSERS][UNAMELENGTH]; /* user names */
269: struct ttyline {
270: struct tty *l_addr; /* address of ttystruct */
271: unsigned l_pgrp; /* process group */
272: char l_name[2]; /* name */
273: dev_t l_dev; /* device number */
274: } ttyline[MAXTTYS];
275:
276: } info;
277: int swapdev; /* major, minor of swap device */
278: int swplo; /* unix swap disk offset */
279: int nswap; /* unix swap space size */
280:
281: struct ttyline notty = {0, 0, {"- "}};
282:
283: /* flags for once only activities (once per repeat) */
284:
285: int heading;
286: int coreinit, core;
287: char *topmem;
288: int arglength;
289: char *getcore(), *store(), *waitingfor(), *getcmd(), *strcat(), *brk();
290:
291: main(argc,argv)
292: char *argv[];
293: {
294: register char *cp, **ap;
295: register int i;
296: int myuid;
297: extern char _sobuf[];
298:
299: if ((myuid = getuid()) == 0)
300: nice(-100);
301:
302: setbuf(stdout, _sobuf);
303: select = 0;
304: for (ap = &argv[1]; --argc; ap++) {
305: for (cp = *ap; *cp;) {
306: switch (*cp++) {
307: case '-':
308: continue;
309: case 'A': /* EVERYTHING */
310: Aflag++;
311: continue;
312: case 'a': /* all procs attached to ttys */
313: bflag++; /* include background */
314: fflag++; /* include foreground */
315: dflag++; /* include detached */
316: aflag++; /* include shells */
317: select++;
318: continue;
319: case 'b': /* all background processes */
320: bflag++;
321: select++;
322: continue;
323: case 'B': /* all busy processes */
324: Bflag++;
325: select++;
326: lflag++;
327: continue;
328: case 'c':
329: cflag++;
330: lflag++;
331: continue;
332: case 'd': /* detached processes */
333: dflag++;
334: select++;
335: continue;
336: case 'e':
337: eflag++;
338: continue;
339: case 'f': /* foreground only */
340: fflag++;
341: select++;
342: continue;
343: case 'F': /* go fast, don't touch swap */
344: Fflag++;
345: continue;
346: case 'G': /* print pgrp */
347: Gflag++;
348: continue;
349: case 'g': /* specify process gourp */
350: select++;
351: while (argc > 1) {
352: if (**++ap == '-') {
353: ap--;
354: break;
355: }
356: --argc;
357: if (pgrps >= &grps[NSPEC])
358: prexit("%a: too many groups\n");
359: (pgrps++)->nm_int = atoi(*ap);
360: }
361: if (pgrps == grps)
362: (pgrps++)->nm_int = getpgrp();
363: continue;
364: case 'i': /* initialize info file */
365: if (myuid != 0) /* must be super user */
366: goto def;
367: iflag++;
368: nflag++;
369: Uflag++;
370: continue;
371: case 'l': /* long output */
372: lflag++;
373: continue;
374: case 'm': /* use designated memory file */
375: if (myuid != 0) /* must be super user */
376: goto def;
377: if (argc-- < 2 || **++ap == '-')
378: prexit("%a: missing memory file\n");
379: memf = *ap;
380: mflag++;
381: continue;
382: case 'n':
383: select++;
384: nflag++;
385: continue;
386: case 'p': /* only designated processes */
387: select++;
388: while (argc > 1) {
389: if (**++ap == '-') {
390: ap--;
391: break;
392: }
393: --argc;
394: if (ppids >= &pids[NSPEC])
395: prexit("%a: too many pids\n");
396: (ppids++)->nm_int = atoi(*ap);
397: }
398: continue;
399: case 'r': /* repeat every <number> seconds */
400: if (myuid != 0)
401: goto def;
402: rflag++;
403: for (i = 0; *cp >= '0' && *cp <= '9'; cp++)
404: i = i * 10 + *cp - '0';
405: if (i)
406: rflag = i;
407: continue;
408: case 'U': /* use designated symbol file */
409: if (myuid != 0)
410: goto def;
411: if (argc-- < 2 || **++ap == '-')
412: prexit("%a: missing symbol file\n");
413: symf = *ap;
414: Uflag++;
415: continue;
416: case 's':
417: sflag++;
418: select++;
419: continue;
420: case 'S':
421: Sflag++;
422: continue;
423: case 'T':
424: Tflag++;
425: continue;
426: case 't': /* on designated tty(s) */
427: select++;
428: while (argc > 1) {
429: if (**++ap == '-') {
430: ap--;
431: break;
432: }
433: --argc;
434: if (pttys >= &ttys[NSPEC])
435: prexit("%a: too many ttys\n");
436: (pttys++)->ty_ptr = *ap;
437: }
438: if (pttys == ttys) {
439: char *ttyname();
440:
441: if ( (pttys->ty_ptr = ttyname(2)) == 0)
442: prexit("%a: unknown tty\n");
443: else if (strcmp("/dev/console", pttys->ty_ptr) == 0)
444: (pttys++)->ty_ptr = "co";
445: else
446: (pttys++)->ty_ptr +=
447: sizeof("/dev/tty") - 1;
448: }
449: continue;
450: case 'u': /* specific user name */
451: aflag++;
452: select++;
453: puids = &uids[0];
454: while (argc > 1) {
455: if (**++ap == '-') {
456: ap--;
457: break;
458: }
459: --argc;
460: if (puids >= &uids[NSPEC])
461: prexit("%a: too many users\n");
462: (puids++)->nm_ptr = *ap;
463: }
464: if (puids == &uids[0])
465: (puids++)->nm_int = myuid;
466: continue;
467: case 'v': /* most verbose output */
468: vflag++;
469: lflag++;
470: continue;
471: case 'W':
472: Wflag++;
473: continue;
474: case 'w': /* wide form (all arguments) */
475: wflag++;
476: continue;
477: case 'x': /* include un-owned procs */
478: xflag++;
479: select++;
480: continue;
481: case 'z': /* include only zombies */
482: zflag++;
483: select++;
484: continue;
485: def:
486: default:
487: prexit("%a: unknown switch: %c\n", *--cp);
488: }
489: break;
490: }
491: }
492:
493: /* these lengths are kludgely tuned to make things not exceed 79 columns */
494: arglength = 60;
495: if (lflag)
496: arglength -= 28;
497: if (vflag)
498: arglength -= 14;
499: if ((mem = open(memf, 0)) < 0)
500: prexit("%a: cannot read system memory: %s\n", memf);
501: if ((kmem = open(kmemf, 0)) < 0)
502: prexit("%a: cannot read system virtural memory: %s\n", kmemf);
503: if (!Fflag && (swap = open(swapf, 0)) <0)
504: prexit("%a: cannot read swap device: %s\n", swapf);
505:
506: if (!iflag)
507: if ((i = open(infof, 0)) < 0)
508: prexit("%a: cannot open info file\n");
509: else if (read(i, &info, sizeof info) != sizeof info)
510: prexit("%a: cannot read info file\n");
511: else
512: close(i);
513: if (Uflag) {
514: struct nlist *np;
515: if ((i = open(symf, 0)) < 0)
516: prexit("%a: can't read symbol file\n");
517: close(i);
518: nlist(symf, namelist);
519: for (np = namelist; np < &namelist[MAXSYMBOLS]; np++)
520: if (np->n_value == 0)
521: fprintf(stderr, "%a: can't find symbol: %s\n",
522: np->n_name);
523: if (namelist[0].n_value == -1)
524: prexit("%a: cannot read symbol file: %s\n", symf);
525: for (i = 0; i < MAXSYMBOLS; i++)
526: info.kaddr[i] = (caddr_t)namelist[i].n_value;
527: info.kaddr[aetext] = (caddr_t)( ((unsigned)info.kaddr[aetext] + 63) & ~63);
528: }
529: if (iflag) {
530: readusers();
531: ttyinit();
532: if ((infofd = creat(infof, 0600)) < 0)
533: prexit("%a: cannot create info file\n");
534: if ((i = write(infofd, &info, sizeof info)) != sizeof info) {
535: if (i == -1)
536: perror(0);
537: prexit("%a: cannot write info file: %d\n", i);
538: }
539: close(infofd);
540: }
541: lseek(kmem, (long)info.kaddr[aswapdev], 0);
542: read(kmem, &swapdev, sizeof(swapdev) );
543: lseek(kmem, (long)info.kaddr[aswplo], 0);
544: read(kmem, &swplo, sizeof(swplo) );
545: lseek(kmem, (long)info.kaddr[answap], 0);
546: read(kmem, &nswap, sizeof(nswap) );
547: lseek(kmem, (long)info.kaddr[anproc], 0);
548: read(kmem, &nproc, sizeof(nproc) );
549: lseek(kmem, (long)info.kaddr[antext], 0);
550: read(kmem, &ntext, sizeof(ntext) );
551: lseek(kmem, (long)info.kaddr[anbuf], 0);
552: read(kmem, &nbuf, sizeof(nbuf) );
553: lseek(kmem, (long)info.kaddr[abuf], 0);
554: read(kmem, &buf, sizeof(buf) );
555: lseek(kmem, (long)info.kaddr[answbuf], 0);
556: read(kmem, &nswbuf, sizeof(nswbuf) );
557: lseek(kmem, (long)info.kaddr[aswbuf], 0);
558: read(kmem, &swbuf, sizeof(swbuf) );
559: lseek(kmem, (long)info.kaddr[aninode], 0);
560: read(kmem, &ninode, sizeof(ninode) );
561: lseek(kmem, (long)info.kaddr[ainode], 0);
562: read(kmem, &inode, sizeof(inode) );
563: lseek(kmem, (long)info.kaddr[ahz], 0);
564: read(kmem, &hz, sizeof(hz) );
565: lseek(kmem, (long)info.kaddr[aproc], 0);
566: read(kmem, &kproc, sizeof(kproc));
567: lseek(kmem, (long)info.kaddr[atext], 0);
568: read(kmem, &ktext, sizeof(ktext));
569: proc = (struct proc *)getcore(nproc * sizeof(struct proc));
570: text = (struct text *)getcore(ntext * sizeof(struct text));
571: if (puids != &uids[0] && uids[0].nm_int != myuid)
572: usersetup();
573: if (!select) {
574: mypid = getpid();
575: (puids++)->nm_int = myuid;
576: nxflag++;
577: select++;
578: }
579: ttysetup();
580: topmem = 0;
581: do {
582: heading = 0; /* reset heading flag (for repeat) */
583: core = coreinit = 0; /* reset core flag (for repeat) */
584: lseek(kmem, (long)kproc, 0);
585: read(kmem, proc, nproc * sizeof(struct proc));
586: lseek(kmem, (long)ktext, 0);
587: read(kmem, text, ntext * sizeof(struct text));
588: needed();
589: mktree();
590: action (plist, 0);
591: printf("%d processes (%dkb), %d busy (%dkb), %d loaded (%dkb)\n",
592: ntotal, (ctob(ktotal) + 1023) / 1024,
593: nbusy, (ctob(kbusy) + 1023) / 1024,
594: nloaded, (ctob(kloaded) + 1023) / 1024);
595: fflush(stdout);
596: } while (rflag && sleep(rflag) == 0);
597: exit(0);
598: }
599:
600: /* read the passwd file and fill in the user name arrays */
601: readusers()
602: {
603: register struct passwd *pw;
604: struct passwd *getpwent();
605:
606: while((pw = getpwent()) != 0) {
607: if(info.unames[pw->pw_uid][0] == '\0')
608: strcpyn(info.unames[pw->pw_uid], pw->pw_name, UNAMELENGTH);
609: }
610: endpwent();
611: }
612:
613: /* check for specified user names */
614:
615: usersetup()
616: {
617: register int i;
618: register union numptr *ip;
619:
620: for (ip = uids; ip < puids; ip++) {
621: for (i = 0; i < MAXUSERS; i++)
622: if (equalu(ip->nm_ptr, info.unames[i]))
623: goto cont2;
624: prexit("%a: unknown user: %s\n", ip->nm_ptr);
625: cont2:
626: ip->nm_int = i;
627: }
628: }
629:
630: /* compare a fixed length user name */
631:
632: equalu(u1, u2)
633: register char *u1, *u2;
634: {
635: register int i = 0;
636:
637: while (*u1++ == *u2)
638: if (!*u2++ || ++i == UNAMELENGTH)
639: return 1;
640: return 0;
641: }
642:
643: /*
644: * Initialize the tty part of the info structure
645: */
646: ttyinit()
647: {
648: struct direct dir;
649: struct stat sbuf;
650: int fd;
651: register struct ttyline *lp = info.ttyline;
652:
653: if ((fd = open("/dev", 0)) < 0)
654: prexit("%a: can't open /dev\n");
655: chdir("/dev");
656: while (read(fd, (char *)&dir, sizeof(dir)) == sizeof(dir)) {
657: if (dir.d_ino == 0 ||
658: strncmp("tty", dir.d_name, 3) != 0 &&
659: strcmp("console", dir.d_name) != 0)
660: continue;
661: if (dir.d_name[sizeof("tty") - 1] == 'C')
662: continue;
663: if (lp >= &info.ttyline[MAXTTYS])
664: prexit("%a: too many ttys in /dev\n");
665: if (dir.d_name[0] == 'c') {
666: lp->l_name[0] = 'c';
667: lp->l_name[1] = 'o';
668: } else {
669: lp->l_name[0] = dir.d_name[3];
670: lp->l_name[1] = dir.d_name[4];
671: }
672: stat(dir.d_name, &sbuf);
673: lp->l_dev = sbuf.st_rdev;
674: lseek(kmem, (long)&cswitch[major(sbuf.st_rdev)].d_ttys, 0);
675: read(kmem, (char *)&lp->l_addr, sizeof(lp->l_addr));
676: lp->l_addr += minor(sbuf.st_rdev);
677: lp++;
678: }
679: close(fd);
680: }
681: ttysetup()
682: {
683: register struct ttyline *lp;
684: register char *cp;
685: union ttyptr *tp;
686: struct tty tty;
687:
688: for (lp = info.ttyline; lp->l_name[0]; lp++) {
689: lseek(kmem, (long)lp->l_addr, 0);
690: if (read(kmem, &tty, sizeof tty) != sizeof tty)
691: prexit("%a: read error in kmem\n");
692: lp->l_pgrp = tty.t_pgrp;
693: if (Tflag)
694: printf("tty%-.2s: dev:%2d,%2d addr:%6x, rawq:%4d, canq:%d, outq:%4d, pgrp:%5d\n",
695: lp->l_name, major(lp->l_dev), minor(lp->l_dev),
696: ABS(lp->l_addr), tty.t_rawq.c_cc,
697: tty.t_canq.c_cc, tty.t_outq.c_cc,
698: tty.t_pgrp);
699: }
700: #ifdef CHAOS
701: mkchttys(lp);
702: #endif
703: /* now fix up specified ttys */
704:
705: for (tp = &ttys[0]; tp < pttys; tp++) {
706: for (lp = info.ttyline; lp->l_name[0]; lp++)
707: if (strcmpn(tp->ty_ptr, lp->l_name, 2) == 0) {
708: tp->ty_line = lp;
709: goto cont2;
710: }
711: prexit("%a: unknown tty name: %c\n", tp->ty_ptr);
712: cont2:;
713: }
714: }
715:
716: /*
717: * Determine which procs are needed for the printout
718: * and add these to a list of needed processes (plist)
719: */
720: needed()
721: {
722: register struct proc *p, *pp;
723: register struct text *tp;
724: struct ttyline *lp;
725: int ok;
726:
727: plist = 0;
728: nswapped = ntotal = nbusy = nloaded = 0;
729: kswapped = ktotal = kbusy = kloaded = 0;
730:
731: for (tp = text; tp < text + ntext; tp++)
732: if (tp->x_count) {
733: ktotal += tp->x_size;
734: if (!(tp->x_ccount))
735: kswapped += tp->x_size;
736: }
737:
738: for (p = proc; p < proc + nproc; p++) {
739: if (!p->p_stat)
740: continue;
741: if (p->p_textp)
742: p->p_textp = &text[p->p_textp - ktext];
743: if (p->p_pptr) {
744: p->p_pptr = &proc[p->p_pptr - kproc];
745: if (p->p_pptr < proc || p->p_pptr >= &proc[nproc]) {
746: fprintf(stderr, "proc %d bad pptr\n", p->p_pid);
747: p->p_pptr = proc;
748: }
749: } else
750: p->p_pptr = proc;
751: }
752: for (p = &proc[0]; p < &proc[nproc]; p++) {
753: if (!p->p_stat)
754: continue;
755: ntotal++;
756: ktotal += procsize(p);
757: if (p->p_flag != SZOMB)
758: if (p->p_flag & SLOAD) {
759: nloaded++;
760: kloaded += procsize(p);
761: if ((tp = p->p_textp) && tp->x_count) {
762: tp->x_count = 0;
763: kloaded += tp->x_size;
764: }
765: } else {
766: nswapped++;
767: kswapped += procsize(p);
768: }
769: ok = FALSE;
770: if (p->p_stat == SRUN ||
771: p->p_stat == SSLEEP && (p->p_pri < PZERO && p->p_pid > MSPID)) {
772: nbusy++;
773: kbusy += procsize(p);
774: if ((tp = p->p_textp) && tp->x_ccount) {
775: tp->x_ccount = 0;
776: kbusy += tp->x_size;
777: }
778: if (Bflag)
779: ok = TRUE;
780: }
781: if (nflag)
782: continue;
783: if (zflag && p->p_stat == SZOMB)
784: ok = TRUE;
785: if (sflag && p->p_stat == SSTOP)
786: ok = TRUE;
787: if (select == 0 && mypid && p->p_pid == mypid)
788: continue;
789: if (p->p_pgrp == 0)
790: if (xflag)
791: ok = TRUE;
792: else if (nxflag)
793: continue;
794: if (dflag && p->p_pgrp != 0 && (p->p_flag & SDETACH) != 0)
795: ok = TRUE;
796: if (aflag && xflag && p->p_pgrp != 0 && (p->p_flag & SDETACH) == 0 &&
797: p->p_pptr == &proc[1])
798: ok = TRUE;
799: if (puids != uids) {
800: register union numptr *ip;
801:
802: for (pp = p; pp > &proc[1]; pp = pp->p_pptr)
803: for (ip = uids; ip < puids; ip++)
804: if ((pp->p_uid & 0377) == ip->nm_int){
805: ok = TRUE;
806: goto uidok;
807: }
808: }
809: uidok:
810: if (pgrps != grps) {
811: register union numptr *ip;
812:
813: for (pp = p; pp > &proc[1]; pp = pp->p_pptr)
814: for (ip = grps; ip < pgrps; ip++)
815: if (pp->p_pgrp == ip->nm_int) {
816: ok = TRUE;
817: goto pgrpok;
818: }
819: }
820: pgrpok:
821: if (ppids != pids) {
822: register union numptr *ip;
823:
824: for (ip = pids; ip < ppids; ip++)
825: if (ip->nm_int == p->p_pid) {
826: ok = TRUE;
827: goto procok;
828: }
829: }
830: procok:
831: if (select && pttys == ttys && !fflag && !bflag && !ok)
832: continue;
833: if (getu(p) == 0) {
834: static struct procinfo fakep = {"--no upage--", ¬ty, 0};
835:
836: if (select && !ok)
837: continue;
838: pinfo(p) = &fakep;
839: goto putonlist;
840: }
841: if (pttys != ttys && p->p_pgrp != 0) {
842: union ttyptr *ip;
843:
844: for (ip = ttys; ip < pttys; ip++)
845: if (p->p_pgrp && p->p_pgrp == ip->ty_line->l_pgrp ||
846: p->p_stat == SSLEEP &&
847: p->p_wchan >= (char *)ip->ty_line->l_addr &&
848: p->p_wchan < (char *)ip->ty_line->l_addr +
849: sizeof (struct tty) ||
850: u.u_ttyd == ip->ty_line->l_dev) {
851: ok = TRUE;
852: break;
853: }
854: }
855: if (p->p_pgrp == 0)
856: lp = ¬ty;
857: else {
858: for (lp = info.ttyline; lp->l_name[0] != 0; lp++)
859: if (lp->l_dev == u.u_ttyd)
860: break;
861: if (lp->l_name[0] == 0)
862: lp = ¬ty;
863: else if (p->p_pptr != &proc[1]) {
864: if (fflag && p->p_pgrp == lp->l_pgrp)
865: ok = TRUE;
866: if (bflag && p->p_pgrp != lp->l_pgrp &&
867: (p->p_flag & SDETACH) == 0 &&
868: p->p_stat != SSTOP)
869: ok = TRUE;
870: }
871: }
872: if (select && !ok)
873: continue;
874: pinfo(p) = (struct procinfo *)getcore(sizeof (struct procinfo));
875: pinfo(p)->pi_time = u.u_vm.vm_utime + u.u_vm.vm_stime;
876: pinfo(p)->pi_tty = lp;
877: pinfo(p)->pi_cmd = getcmd(p);
878: putonlist:
879: /* we have a needed proc! */
880:
881: p->p_next = plist;
882: plist = p;
883: p->p_son = p->p_bro = 0;
884: }
885: }
886: /*
887: * mktree - sort the needed processes by subtree and at the top by user
888: */
889: mktree()
890: {
891: register struct proc *p, *pp, *lp;
892: struct proc *op;
893: struct proc proot;
894:
895: proot.p_bro = 0;
896:
897: for (p = plist; p; p = p->p_next) { /* for all needed processes */
898: if (p->p_pptr > &proc[1]) {
899: for (pp = plist; pp; pp = pp->p_next)
900: if (pp == p->p_pptr) { /* if my parent */
901: if (lp = pp->p_son) { /* if siblings */
902: for (op = 0; lp && lp->p_pid <
903: p->p_pid;
904: lp = (op = lp)->p_bro)
905: ;
906: if (op) {
907: p->p_bro = lp;
908: op->p_bro = p;
909: break;
910: }
911: }
912: p->p_bro = lp; /* here if first or only */
913: pp->p_son = p;
914: break;
915: }
916: if (pp) /* if we found the parent */
917: continue;
918: }
919:
920: /* we have a top level process, sort into top level list */
921:
922: for (pp = (lp = &proot)->p_bro; pp; pp = (lp = pp)->p_bro)
923: if ((p->p_uid & 0377) < (pp->p_uid & 0377) ||
924: (p->p_uid & 0377) == (pp->p_uid & 0377) &&
925: p->p_pid < pp->p_pid)
926: break;
927: p->p_bro = lp->p_bro;
928: lp->p_bro = p;
929: }
930: plist = proot.p_bro;
931: }
932:
933: action(p, md)
934: register struct proc *p;
935: register int md;
936: {
937:
938: if (p) {
939: printp(p, md);
940: if (p->p_son)
941: action(p->p_son, md+1);
942: if (p->p_bro)
943: action(p->p_bro, md);
944: }
945: }
946:
947: /*
948: * Pretty print the output according to the switches.
949: */
950: printp(p, md)
951: register struct proc *p;
952: {
953: register char *cp, *cp1;
954: char stat[10];
955: static int lastuid;
956: static char *statnames[] = {"Unk ", "Wait", "Wait", "Run ",
957: "Init", "Exit", "Stop"};
958:
959: if (!heading) {
960: heading++;
961: printf("Ty User ");
962: if (lflag) {
963: printf("Stat");
964: if (vflag) printf(" Flgs Nice Pri ");
965: else printf(" ");
966: printf("Memory-kb Time Wait? ");
967: }
968: if (Aflag)
969: printf("Address Proc. Clock Alarm ");
970: if (Sflag)
971: printf("Size ");
972: if (Gflag)
973: printf("Group ");
974: printf("Proc# Command\n");
975: }
976: printf("%.2s%c", pinfo(p)->pi_tty->l_name,
977: p->p_pgrp == 0 ? ' ' :
978: p->p_flag & SDETACH ? '_' :
979: p->p_pgrp == pinfo(p)->pi_tty->l_pgrp ? '.' :
980: ' ');
981:
982: if (md == 0) {
983: lastuid = p->p_uid & 0377;
984: cp = info.unames[lastuid];
985: if (*cp)
986: printf("%-8.8s ", cp);
987: else
988: printf("user%-4.4d ", lastuid);
989: } else {
990: if (md > 8)
991: md = 8;
992: printf("%*s*", md, "");
993: if ((p->p_uid & 0377) != lastuid) { /* setuid process! */
994: lastuid = p->p_uid & 0377;
995: cp = info.unames[lastuid];
996: } else
997: cp = "";
998: md = 8 - md;
999: printf("%-*.*s", md, md, cp);
1000: }
1001: if (lflag) {
1002: cp = statnames[p->p_stat];
1003: if (p->p_flag&SLOAD) {
1004: for (cp1 = stat; *cp1 = *cp; cp1++, cp++)
1005: if (*cp >= 'a' && *cp <= 'z')
1006: *cp1 -= 'a' - 'A';
1007: cp = stat;
1008: }
1009: printf("%-4.4s ", cp);
1010: if (vflag) {
1011: cp = stat;
1012: if (p->p_flag & SSYS) *cp++ = 'U';
1013: if (p->p_flag&SLOCK) *cp++ = 'L';
1014: if (p->p_flag&STRC) *cp++ = 'T';
1015: if (p->p_flag&SWTED) *cp++ = 'W';
1016: if (p->p_flag&SSWAP) *cp++ = 'S';
1017: while(cp < &stat[5]) *cp++ = ' ';
1018: *cp = 0;
1019: printf("%-4.4s ",stat);
1020: if (p->p_nice != NZERO)
1021: printf("%4d", p->p_nice - NZERO);
1022: else
1023: printf(" ");
1024: if (p->p_stat != SZOMB)
1025: printf("%4d ", p->p_pri);
1026: else
1027: printf(" ");
1028: }
1029: if (p->p_stat != SZOMB) {
1030: printf("%4d", msize(procsize(p)) );
1031: if (p->p_textp)
1032: printf("+%4d ", msize(p->p_textp->x_size));
1033: else
1034: printf(" ");
1035: prcpu(pinfo(p)->pi_time);
1036: } else
1037: printf(" ");
1038: if (p->p_stat != SZOMB && p->p_stat != SRUN && p->p_stat != SSTOP)
1039: if (!Wflag && (cp = waitingfor(p)))
1040: printf("%-6.6s ", cp);
1041: else printf("%6x ", ABS((int)p->p_wchan));
1042: else printf(" ");
1043: }
1044: if (Aflag)
1045: printf("%6x %6x %6d%6d ", p->p_addr,
1046: (p - proc) * sizeof (struct proc) + info.kaddr[aproc],
1047: p->p_time, p->p_clktim);
1048: if (Sflag)
1049: printf("%5x ", procsize(p) );
1050: if (Gflag)
1051: printf("%5D ", p->p_pgrp);
1052: printf("%5D ", p->p_pid);
1053: if (wflag)
1054: printf("%s\n", pinfo(p)->pi_cmd);
1055: else
1056: printf("%-.*s\n", arglength, pinfo(p)->pi_cmd);
1057: }
1058:
1059: /* print cpu time */
1060:
1061: prcpu(time)
1062: long time;
1063: {
1064: register unsigned i;
1065:
1066: if (time < 0)
1067: printf(" ---- ");
1068: else if (time < (long)hz * 60 * 10) /* less than 10 minutes */
1069: printf("%3d.%1d ",
1070: (int)(time / hz),
1071: (int)(time % hz / (hz / 10)));
1072: else if (time < (long)hz * 60 * 60 * 10)/* less than 10 hours */
1073: printf("%3d M ",
1074: (int)((time + (hz * 60) / 2) / (hz * 60)));
1075: else {
1076: i = (time + ((long)hz * 60 * 60) / 2) /
1077: ((long)hz * 60 * 60);
1078: if (i < 1000)
1079: printf("%3d H ", i);
1080: else
1081: printf(" ---- ");
1082: }
1083: }
1084: /* Determine what a process is waiting for and describe it. */
1085:
1086: char *
1087: waitingfor(p)
1088: register struct proc *p;
1089: {
1090: register caddr_t w;
1091: register struct ttyline *lp;
1092: register char *cp;
1093:
1094: w = p->p_wchan;
1095: if (w == (caddr_t)0)
1096: return "null";
1097: if (w >= (char *)kproc && w < (char *)(kproc + nproc))
1098: return "child";
1099: if (w >= (char *)swbuf && w < (char *)(swbuf + nswbuf))
1100: return "swap";
1101: if (w == info.kaddr[arswbuf])
1102: return "rswap";
1103: if (w >= (char *)buf && w < (char *)(buf + nbuf))
1104: return "diskio";
1105: if (w >= info.kaddr[afile] && w < info.kaddr[afile] + sizeof(struct file) * nfile)
1106: return "file";
1107: if (w >= (char *)inode && w < (char *)(inode + ninode))
1108: switch((w - (char *)inode) % sizeof(struct inode)) {
1109: case 1:
1110: return "wpipe";
1111: case 2:
1112: return "rpipe";
1113: case 3:
1114: return "mutex";
1115: case (int)&((struct inode *)0)->i_un.i_group.g_datq:
1116: return "rmux";
1117: default:
1118: return "inode";
1119: }
1120: if (w == info.kaddr[achtbuf])
1121: return "tapecn";
1122: if (w == info.kaddr[ahpbuf])
1123: return "rpdisk";
1124: if (w == info.kaddr[ark7])
1125: return "rkdisk";
1126: if (w == info.kaddr[arhtbuf])
1127: return "tapeio";
1128: if (w == info.kaddr[alpdt])
1129: return "printr";
1130: if (w == info.kaddr[albolt])
1131: return "lbolt";
1132: if (w == info.kaddr[arunin])
1133: return "runin";
1134: if (w == info.kaddr[arunout])
1135: return "runout";
1136: if (w == info.kaddr[atout])
1137: return "sleep";
1138: if (w == info.kaddr[aipc])
1139: return "ptrace";
1140: if (w == info.kaddr[abfreeli])
1141: return "buffer";
1142: if (w == info.kaddr[amaplock])
1143: return "ubmap";
1144: if (w == info.kaddr[au])
1145: return "pause";
1146: if (w == info.kaddr[achrfclist])
1147: return "chrfc";
1148: for (lp = info.ttyline; lp->l_name[0]; lp++)
1149: if (w >= (char *)lp->l_addr && w < (char *)lp->l_addr + sizeof (struct tty)) {
1150: #define TTY0 ((struct tty *)0)
1151: switch(w - (char *)lp->l_addr) {
1152: case (int)&TTY0->t_rawq:
1153: cp = "rtty??";
1154: break;
1155: case (int)&TTY0->t_outq:
1156: cp = "wtty??";
1157: break;
1158: case (int)&TTY0->t_state:
1159: cp = "otty??";
1160: break;
1161: default:
1162: cp = "?tty??";
1163: }
1164: cp[4] = lp->l_name[0];
1165: cp[5] = lp->l_name[1];
1166: return cp;
1167: }
1168: return 0;
1169: }
1170:
1171: getu(mproc)
1172: register struct proc *mproc;
1173: {
1174: struct pte *pteaddr, apte;
1175: register int i;
1176: int ncl, size;
1177:
1178: size = Sflag ? ctob(UPAGES) : sizeof (struct user);
1179: if ((mproc->p_flag & SLOAD) == 0) {
1180: lseek(swap, (long)ctob(mproc->p_swaddr), 0);
1181: if (read(swap, (char *)&user.user, size) != size) {
1182: fprintf(stderr, "%a: cant read u for pid %d from %s\n",
1183: mproc->p_pid, swapf);
1184: return (0);
1185: }
1186: return (1);
1187: }
1188: pteaddr = &Usrptmap[btokmx(mproc->p_p0br) + mproc->p_szpt - 1];
1189: lseek(kmem, (long)(mflag ? ABS(pteaddr) : (int)pteaddr), 0);
1190: if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) {
1191: printf("%a: cant read indir pte to get u for pid %d from %s\n",
1192: mproc->p_pid, swapf);
1193: return (0);
1194: }
1195: lseek(mem, (long)
1196: (ctob(apte.pg_pfnum+1) - (UPAGES+MAXARGPG) * sizeof (struct pte)),
1197: 0);
1198: if (read(mem, (char *)pagetable, sizeof(pagetable)) != sizeof(pagetable)) {
1199: printf("%a: cant read page table for u of pid %d from %s\n",
1200: mproc->p_pid, swapf);
1201: return (0);
1202: }
1203: ncl = (size + NBPG*CLSIZE - 1) / (NBPG*CLSIZE);
1204: while (--ncl >= 0) {
1205: i = ncl * CLSIZE;
1206: lseek(mem, (long)ctob(pagetable[MAXARGPG+i].pg_pfnum), 0);
1207: if (read(mem, user.upages[i], CLSIZE*NBPG) != CLSIZE*NBPG) {
1208: printf("%a: cant read page %d of u of pid %d from %s\n",
1209: pagetable[MAXARGPG+i].pg_pfnum, mproc->p_pid, memf);
1210: return(0);
1211: }
1212: }
1213: return (1);
1214: }
1215: char *
1216: getcmd(p)
1217: register struct proc *p;
1218: {
1219: struct pte apte;
1220: char argbuf[MAXARGPG * NBPG], *argptr;
1221: register int *ip;
1222: register char *cp, *cp1;
1223: int cc, nbad, i;
1224:
1225: if (p->p_stat == SZOMB)
1226: return "--Defunct--";
1227: if ((p->p_flag&SLOAD) == 0 && Fflag)
1228: return "--Swapped--";
1229: if (p->p_flag & SSYS)
1230: return p->p_pid == 0 ? "UNIX Swapper" :
1231: p->p_pid == 2 ? "UNIX Pager" : "UNIX";
1232: for (i = 0; i < MAXARGPG; i++) {
1233: argptr = &argbuf[(MAXARGPG - 1 - i) * NBPG];
1234: apte = pagetable[MAXARGPG - 1 - i];
1235: if ((p->p_flag & SLOAD) && apte.pg_fod == 0 && apte.pg_pfnum ) {
1236: lseek(mem, (long)ctob(apte.pg_pfnum), 0);
1237: if (read(mem, argptr, NBPG) != NBPG)
1238: return "---Mem read error (args)---";
1239: } else if (Fflag)
1240: goto cheap;
1241: else {
1242: lseek(swap, (long)ctob(u.u_smap.dm_map[0] + DMMIN - 1 - i), 0);
1243: if (read(swap, argptr, NBPG) != NBPG)
1244: return "---Swap read error (args)---";
1245: }
1246: /* Here block of stack is at argptr */
1247: ip = (int *)&argptr[NBPG];
1248: if (i == 0) {
1249: *--ip = 0;
1250: ip--;
1251: }
1252: while (ip > (int *)argptr && *--ip != 0)
1253: ;
1254: if (ip > (int *)argptr || *ip == 0)
1255: break;
1256: }
1257: if (i >= MAXARGPG) {
1258: cheap:
1259: argbuf[0] = '(';
1260: strncpy(&argbuf[1], u.u_comm, sizeof(u.u_comm));
1261: strcat(argbuf, ")");
1262: return store(argbuf);
1263: }
1264: cp = (char *)(ip + 1);
1265: if (*cp == '\0')
1266: cp++;
1267: nbad = 0;
1268: for (cp1 = cp; cp1 < &argbuf[MAXARGPG*NBPG]; cp1++) {
1269: cc = *cp1 & 0177;
1270: if (cc == 0)
1271: *cp1 = ' ';
1272: else if (cc < ' ' || cc == 0177) {
1273: if (++nbad >= 5) {
1274: *cp1++ = ' ';
1275: break;
1276: }
1277: *cp1 = '?';
1278: } else if (!eflag && cc == '=') {
1279: *cp1 = 0;
1280: while (cp1 > cp && *--cp1 != ' ')
1281: *cp1 = 0;
1282: break;
1283: }
1284: }
1285: while (*--cp1 == ' ')
1286: *cp1 = 0;
1287: if (!wflag && &cp[arglength] < (char *)&argbuf[MAXARGPG*NBPG - 1])
1288: cp[arglength] = 0;
1289: return store(cp);
1290: }
1291:
1292: /*
1293: * Store a string in core for later use.
1294: */
1295: char *
1296: store(cp)
1297: char *cp;
1298: {
1299: register char *src, *dst, *svdst;
1300:
1301: src = cp;
1302: while (*src++);
1303: svdst = getcore(src - cp);
1304: dst = svdst;
1305: src = cp;
1306: while (*dst++ = *src++);
1307: return(svdst);
1308: }
1309:
1310: /*
1311: * Allocate and return a pointer to the asked for amount of core
1312: */
1313: char *
1314: getcore(cnt)
1315: register int cnt;
1316: {
1317: static char *corep;
1318: register char *ip;
1319: register int incr;
1320: char *sbrk();
1321:
1322: if (cnt > core) {
1323: if (coreinit == 0) {
1324: coreinit++;
1325: if (topmem)
1326: brk(topmem); /* after repeat!! */
1327: else
1328: topmem = sbrk(0);
1329: corep = topmem;
1330: }
1331: incr = cnt > 4096 ? cnt : 4096;
1332: if (sbrk(incr) == 0)
1333: prexit("%a: out of memory!\n");
1334: core += incr;
1335: }
1336: ip = corep;
1337: core -= cnt;
1338: corep += cnt;
1339: return(ip);
1340: }
1341: #ifdef CHAOS
1342: #include "chunix/chsys.h"
1343: #include <chaos/chaos.h>
1344:
1345: mkchttys(lp)
1346: register struct ttyline *lp;
1347: {
1348: register struct connection **cnp;
1349: register int i;
1350: struct tty tty;
1351: struct connection *Chconntab[CHNCONNS];
1352: struct connection conn;
1353:
1354: lseek(kmem, (long)info.kaddr[aChconntab], 0);
1355: read(kmem, (char *)Chconntab, sizeof(Chconntab));
1356: for (i = 0, cnp = Chconntab; cnp < &Chconntab[CHNCONNS]; i++, cnp++) {
1357: if (!*cnp)
1358: continue;
1359: lseek(kmem, (long)*cnp, 0);
1360: read(kmem, (char *)&conn, sizeof(conn));
1361: if ((conn.cn_flags & CHTTY) == 0)
1362: continue;
1363: lseek(kmem, (long)conn.cn_ttyp, 0);
1364: read(kmem, (char *)&tty, sizeof(tty));
1365: if (lp >= &info.ttyline[MAXTTYS])
1366: prexit("%a: too many ttys\n");
1367: lp->l_addr = conn.cn_ttyp;
1368: lp->l_pgrp = tty.t_pgrp;
1369: lp->l_dev = tty.t_dev;
1370: lp->l_name[0] = 'C';
1371: lp->l_name[1] = i < 10 ? '0' + i :
1372: i - 10 <= 'z' - 'a' ? i - 10 + 'a' :
1373: i - 10 - ('z' - 'a') + 'A';
1374: if (Tflag)
1375: printf("tty%-.2s: dev:%2d,%2d addr:%6x, rawq:%4d, canq:%d, outq:%4d, pgrp:%5d\n",
1376: lp->l_name, major(lp->l_dev), minor(lp->l_dev),
1377: ABS(lp->l_addr), tty.t_rawq.c_cc,
1378: tty.t_canq.c_cc, tty.t_outq.c_cc,
1379: tty.t_pgrp);
1380: lp++;
1381: }
1382: }
1383: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.