|
|
1.1 root 1: /*
2: * ps - process status
3: * This is the augmented UCB ps for UCB/VM Unix (9/79)
4: * examine and print certain things about processes
5: * usage: ps [acgklrt#uvwx] [corefile] [swapfile] [system]
6: */
7:
8: #include <stdio.h>
9: #include <a.out.h>
10: #include <pwd.h>
11: #include <sys/param.h>
12: #include <sys/proc.h>
13: #include <sys/tty.h>
14: #include <sys/dir.h>
15: #include <sys/user.h>
16: #include <sys/pte.h>
17: #include <sys/vm.h>
18: #include <sys/text.h>
19: #include <psout.h>
20:
21: struct nlist nl[] = {
22: { "_proc" },
23: #define X_PROC 0
24: { "_swapdev" },
25: #define X_SWAPDEV 1
26: { "_swplo" },
27: #define X_SWPLO 2
28: { "_Usrptma" },
29: #define X_USRPTMA 3
30: { "_usrpt" },
31: #define X_USRPT 4
32: { "_text" },
33: #define X_TEXT 5
34: { "_nswap" },
35: #define X_NSWAP 6
36: { 0 },
37: };
38:
39: struct proc mproc;
40: struct text text[NTEXT];
41:
42: #define INTPPG (NBPG/sizeof(int)) /* ints per page */
43: union {
44: struct user yy;
45: int xx[INTPPG][UPAGES];
46: } zz;
47: #define clear(x) ((int)x & 0x7fffffff)
48: #define u zz.yy
49: int chkpid = 0;
50: int aflg; /* -a: all processes, not just mine */
51: int cflg; /* -c: complete listing of args, not just comm. */
52: int gflg; /* -g: complete listing including group headers, etc */
53: int kflg; /* -k: read from core file instead of real memory */
54: int lflg; /* -l: long listing form */
55: int rflg; /* -r: raw output in style <psout.h> */
56: int sflg; /* -s: stack depth */
57: int uflg; /* -u: user name */
58: int vflg; /* -v: virtual memory statistics */
59: int wflg; /* -w[w]: wide terminal */
60: int xflg; /* -x: ALL processes, even those without ttys */
61: int login; /* -: this is a login shell */
62: char *tptr;
63: char *gettty();
64: int pscomp();
65: struct pte pagetbl[NPTEPG];
66: int kmem;
67: int mem;
68: int swap;
69: daddr_t swplo;
70: int nswap;
71: int Usrptma;
72: int usrpt;
73:
74: int ndev;
75: struct devl {
76: char dname[DIRSIZ];
77: dev_t dev;
78: } devl[256];
79:
80: struct psout outargs[NPROC]; /* info for first npr processes */
81: int npr; /* number of processes found so far */
82: int argwidth; /* number of chars of args to print */
83:
84: char *coref;
85:
86: main(argc, argv)
87: char **argv;
88: {
89: int i;
90: char *ap;
91: int uid, puid;
92: char obuf[BUFSIZ];
93: register struct nlist *nlp;
94:
95: setbuf(stdout, obuf);
96: argc--, argv++;
97: if (argc>0) {
98: ap = argv[0];
99: while (*ap) switch (*ap++) {
100: case '-':
101: break;
102:
103: case 'a':
104: aflg++;
105: break;
106:
107: case 'c':
108: cflg++;
109: break;
110:
111: case 'g':
112: gflg++;
113: break;
114:
115: case 'k':
116: kflg++;
117: break;
118:
119: case 'l':
120: lflg++;
121: break;
122:
123: case 'r':
124: rflg++;
125: break;
126:
127: case 's':
128: sflg++;
129: break;
130:
131: case 't':
132: if(*ap)
133: tptr = ap;
134: aflg++;
135: gflg++;
136: if (*tptr == '?')
137: xflg++;
138: while (*ap)
139: ap++;
140: break;
141:
142: case 'u':
143: uflg++;
144: break;
145:
146: case 'v':
147: vflg++;
148: break;
149:
150: case 'w':
151: wflg++;
152: break;
153:
154: case 'x':
155: xflg++;
156: break;
157:
158: default:
159: chkpid=atoi(--ap);
160: *ap = '\0';
161: aflg++;
162: xflg++;
163: break;
164: }
165: }
166: coref = "/dev/kmem";
167: if(kflg)
168: coref = argc > 1 ? argv[1] : "/vmcore";
169:
170: if ((kmem = open(coref, 0)) < 0) {
171: perror(coref);
172: done(1);
173: }
174: if ((mem = open("/dev/mem", 0)) < 0) {
175: fprintf(stderr, "No mem\n");
176: done(1);
177: }
178: if (kflg)
179: mem = kmem;
180:
181: if ((swap = open(argc>2 ? argv[2]: "/dev/drum", 0)) < 0) {
182: fprintf(stderr, "Can't open /dev/drum\n");
183: done(1);
184: }
185:
186: nlist(argc>3 ? argv[3] : "/vmunix", nl);
187: if (nl[0].n_type==0) {
188: fprintf(stderr, "No namelist\n");
189: done(1);
190: }
191:
192: if(chdir("/dev") < 0) {
193: fprintf(stderr, "Can't change to /dev\n");
194: done(1);
195: }
196: if (kflg)
197: for (nlp= nl; nlp < &nl[sizeof (nl)/sizeof (nl[0])]; nlp++)
198: nlp->n_value &= 0x7ffffffff;
199: Usrptma = nl[X_USRPTMA].n_value;
200: usrpt = nl[X_USRPT].n_value;
201: /*
202: * read kmem to find swap dev.
203: */
204: lseek(kmem, (long)nl[X_SWAPDEV].n_value, 0);
205: read(kmem, &nl[X_SWAPDEV].n_value, sizeof(nl[X_SWAPDEV].n_value));
206: /*
207: * Find base and size of swap
208: */
209: lseek(kmem, (long)nl[X_SWPLO].n_value, 0);
210: read(kmem, &swplo, sizeof(swplo));
211: lseek(kmem, (long)nl[X_NSWAP].n_value, 0);
212: read(kmem, &nswap, sizeof (nswap));
213: /*
214: * If v flag get text table
215: */
216: if (vflg) {
217: lseek(kmem, (long)nl[X_TEXT].n_value, 0);
218: read(kmem, text, sizeof (text));
219: }
220: if (kflg)
221: swplo = 0;
222: getdev();
223: uid = getuid();
224: if (sflg + lflg + vflg + uflg > 1) {
225: printf("Cannot combine s, l, v, and/or u.\n");
226: exit(1);
227: }
228: /* different psout widths depending on how much printed & w flag */
229: if (wflg <= 1) {
230: argwidth = 63;
231: if (wflg) argwidth += 52; /* 132 col term */
232: if (lflg) argwidth -= 49; /* extra junk printed */
233: if (vflg) argwidth -= 48; /* extra junk for -v */
234: if (sflg) argwidth -= 4; /* 4 cols of stack size */
235: if (uflg) argwidth -= 27; /* user name */
236: } else argwidth = 127;
237: if (rflg)
238: ; /* No heading for raw output */
239: else if (lflg)
240: printf(" F S UID PID PPID CPU PRI NICE ADDR SZ RSS WCHAN TTY TIME COMMAND\n");
241: else if (vflg)
242: printf("F PID TT TIME TIM SL MINFLT MAJFLT SIZE RSS SRS TSIZ TRS PF COMMAND\n");
243: else if (uflg)
244: printf("USER PID %%CPU NICE SZ RSS TTY TIME COMMAND\n");
245: else if (chkpid==0) {
246: if (sflg)
247: printf(" SSIZ");
248: printf(" PID TTY TIME COMMAND\n");
249: }
250: fflush(stdout);
251: for (i=0; i<NPROC; i++) {
252: lseek(kmem, (long)(nl[X_PROC].n_value+i*(sizeof mproc)), 0);
253: read(kmem, &mproc, sizeof mproc);
254: /* skip processes that don't exist */
255: if (mproc.p_stat==0)
256: continue;
257: /* skip those without a tty unless -x */
258: if (mproc.p_pgrp==0 && xflg==0)
259: continue;
260: /* skip group leaders on a tty unless -g, -x, or -t.. */
261: if (!gflg && !xflg && !tptr && mproc.p_pid == mproc.p_pgrp)
262: continue;
263: /* -g also skips those where **argv is "-" - see savcom */
264: puid = mproc.p_uid;
265: /* skip other peoples processes unless -a or a specific pid */
266: if ((uid != puid && aflg==0) ||
267: (chkpid!=0 && chkpid!=mproc.p_pid))
268: continue;
269: if (savcom(puid))
270: npr++;
271: }
272: fixup(npr);
273: for (i=0; i<npr; i++)
274: if (prcom(&outargs[i])) {
275: putchar('\n');
276: fflush(stdout);
277: }
278: done(!npr);
279: }
280:
281: getdev()
282: {
283: #include <sys/stat.h>
284: register FILE *df;
285: struct stat sbuf;
286: struct direct dbuf;
287:
288: if ((df = fopen("/dev", "r")) == NULL) {
289: fprintf(stderr, "Can't open /dev\n");
290: done(1);
291: }
292: ndev = 0;
293: while (fread(&dbuf, sizeof(dbuf), 1, df) == 1) {
294: if(dbuf.d_ino == 0)
295: continue;
296: if(stat(dbuf.d_name, &sbuf) < 0)
297: continue;
298: if ((sbuf.st_mode&S_IFMT) != S_IFCHR)
299: continue;
300: strcpy(devl[ndev].dname, dbuf.d_name);
301: devl[ndev].dev = sbuf.st_rdev;
302: ndev++;
303: }
304: fclose(df);
305: }
306:
307: savcom(puid)
308: {
309: int abuf[INTPPG];
310: long addr;
311: register int *ip;
312: register struct psout *a;
313: register char *cp, *cp1;
314: long tm;
315: int cc, nbad;
316: int szpt, p0br;
317: register char *tp;
318: struct dblock db;
319: struct pte apte;
320:
321: /* skip long sleeping or dead processes if -v unless -g or -x */
322: if (!gflg && vflg && !xflg) {
323: switch (mproc.p_stat) {
324:
325: case SSLEEP:
326: case SSTOP:
327: if (mproc.p_slptime > MAXSLP)
328: return (0);
329: break;
330:
331: case SRUN:
332: case SIDL:
333: break;
334:
335: case SZOMB:
336: return (0);
337: }
338: }
339: /* read in the user structure */
340: if ((mproc.p_flag& SLOAD ) == 0) {
341: /* not loaded - get from swap */
342: addr = (mproc.p_swaddr+swplo)<<9;
343: lseek(swap, addr, 0);
344: if (read(swap, &u, sizeof(u)) != sizeof(u))
345: return(0);
346: } else {
347: /* loaded, get each page from memory separately */
348: for(cc=0; cc<UPAGES; cc++) { /* get u area */
349: int upage = ctob(mproc.p_addr[cc]);
350: lseek(mem,upage,0);
351: if (read(mem,((int *)&u)+INTPPG*cc,NBPG) != NBPG)
352: return(0);
353: }
354: }
355: tp = gettty();
356: if (tptr && strcmpn(tptr, tp, 2))
357: return(0);
358: a = &outargs[npr];
359: /* saving com starts here */
360: a->o_uid = puid;
361: a->o_pid = mproc.p_pid;
362: a->o_flag = mproc.p_flag;
363: a->o_ppid = mproc.p_ppid;
364: a->o_cpu = mproc.p_cpu;
365: a->o_pctcpu = 0.0; /* This needs to be fixed later */
366: a->o_pri = mproc.p_pri;
367: a->o_nice = mproc.p_nice;
368: a->o_addr0 = mproc.p_addr[0];
369: a->o_dsize = mproc.p_dsize;
370: a->o_ssize = mproc.p_ssize;
371: a->o_rssize = mproc.p_rssize;
372: a->o_swrss = mproc.p_swrss;
373: a->o_wchan = mproc.p_wchan;
374: a->o_pgrp = mproc.p_pgrp;
375: a->o_tty[0] = tp[0];
376: a->o_tty[1] = tp[1] ? tp[1] : ' ';
377: a->o_ttyd = u.u_ttyd;
378: a->o_stat = mproc.p_stat;
379: a->o_flag = mproc.p_flag;
380: if (a->o_stat==SZOMB) return(1);
381: a->o_utime = u.u_utime;
382: a->o_stime = u.u_stime;
383: a->o_cutime = u.u_cutime;
384: a->o_cstime = u.u_cstime;
385: a->o_sigs = u.u_signal[SIGINT] + u.u_signal[SIGQUIT];
386: a->o_time = mproc.p_time;
387: a->o_slptime = mproc.p_slptime;
388: a->o_uname[0] = 0;
389: if (sflg) {
390: for (cp = (char *)u.u_stack; cp < (char *)&u + ctob(UPAGES); cp++)
391: if (*cp)
392: break;
393: a->o_stksize = (int) ((char *)&u + ctob(UPAGES) - cp);
394: }
395: if (mproc.p_stat==SZOMB) return(1);
396: if (vflg) {
397: register struct text *xp;
398:
399: if (mproc.p_textp) {
400: xp = &text[mproc.p_textp - (struct text *)nl[5].n_value];
401: a->o_xsize = xp->x_size;
402: a->o_xrssize = xp->x_rssize;
403: } else {
404: a->o_xsize = 0;
405: a->o_xrssize = 0;
406: }
407: a->o_aveflt = mproc.p_aveflt;
408: a->o_minorflt = u.u_minorflt;
409: a->o_majorflt = u.u_majorflt;
410: }
411: strcpy(a->o_comm, u.u_comm);
412: if (cflg)
413: return (1);
414: a->o_args[0] = 0; /* in case of early return */
415: if ((mproc.p_flag & SLOAD) == 0) {
416: vstodb(0, 1, &u.u_smap, &db, 1);
417: addr = ctob(swplo + db.db_base);
418: lseek(swap, addr, 0);
419: if (read(swap, abuf, sizeof(abuf)) != sizeof(abuf))
420: goto garbage;
421: } else {
422: szpt = u.u_pcb.pcb_szpt;
423: p0br = kflg ? clear((int)mproc.p_p0br) : (int)mproc.p_p0br;
424: cc = Usrptma + (p0br + NBPG*(szpt-1) - usrpt)/NPTEPG;
425: lseek(kmem, cc, 0);
426: if (read(kmem, &apte, sizeof(apte)) != sizeof(apte))
427: goto garbage;
428: lseek(mem, ctob(apte.pg_pfnum), 0);
429: if (read(mem,pagetbl,sizeof(pagetbl)) != sizeof(pagetbl))
430: goto garbage;
431: if (pagetbl[NPTEPG-1].pg_fod == 0 && pagetbl[NPTEPG-1].pg_pfnum) {
432: lseek(mem,ctob((pagetbl[NPTEPG-1].pg_pfnum)),0);
433: if (read(mem,abuf,sizeof(abuf)) != sizeof(abuf))
434: goto garbage;
435: } else {
436: vstodb(0, 1, &u.u_smap, &db, 1);
437: addr = ctob(swplo + db.db_base);
438: lseek(swap, addr, 0);
439: if (read(swap, abuf, sizeof(abuf)) != sizeof(abuf))
440: goto garbage;
441: }
442: }
443: abuf[INTPPG] = 0;
444: for (ip = &abuf[INTPPG-2]; ip > abuf;) {
445: if (*--ip == -1 || *ip == 0) {
446: cp = (char *)(ip+1);
447: if (*cp==0)
448: cp++;
449: nbad = 0;
450: for (cp1 = cp; cp1 < (char *)&abuf[INTPPG]; cp1++) {
451: cc = *cp1&0177;
452: if (cc==0)
453: *cp1 = ' ';
454: else if (cc < ' ' || cc > 0176) {
455: if (++nbad >= 5) {
456: *cp1++ = ' ';
457: break;
458: }
459: *cp1 = '?';
460: } else if (cc=='=') {
461: *cp1 = 0;
462: while (cp1>cp && *--cp1!=' ')
463: *cp1 = 0;
464: break;
465: }
466: }
467: while (*--cp1==' ')
468: *cp1 = 0;
469: strcpy(a->o_args, cp);
470: garbage:
471: cp = a->o_args;
472: if (cp[0]=='-'&&cp[1]<=' ' || cp[0]=='?' || cp[0]<=' ') {
473: strcat(cp, " (");
474: strcat(cp, u.u_comm);
475: strcat(cp, ")");
476: }
477: cp[127] = 0; /* max room in psout is 128 chars */
478: if (xflg || gflg || tptr || cp[0]!='-')
479: return(1);
480: return(0);
481: }
482: }
483: goto garbage;
484: }
485:
486: prcom(a)
487: register struct psout *a;
488: {
489: long tm;
490:
491: if (rflg) {
492: write(1, a, sizeof (*a));
493: return(0);
494: }
495: if (lflg) {
496: printf("%4x %c", 0xffff & a->o_flag,
497: "0SWRIZT"[a->o_stat]);
498: printf("%4d", a->o_uid);
499: } else if (vflg) {
500: switch (a->o_stat) {
501:
502: case SSLEEP:
503: case SSTOP:
504: if ((a->o_flag & SLOAD) == 0)
505: printf("W");
506: else if (a->o_pri >= PZERO)
507: printf("S");
508: else if (a->o_flag & SPAGE)
509: printf("P");
510: else
511: printf("D");
512: break;
513:
514: case SRUN:
515: case SIDL:
516: if (a->o_flag & SLOAD)
517: printf("R");
518: else
519: printf("W");
520: break;
521: }
522: if (a->o_nice > NZERO)
523: printf("N");
524: else
525: printf(" ");
526: } else if (uflg) {
527: printf("%-8.8s", a->o_uname);
528: }
529: if (sflg) {
530: printf("%5d", a->o_stksize);
531: }
532: printf("%6u", a->o_pid);
533: if (lflg)
534: printf("%6u%4d%4d%4d%6x", a->o_ppid, a->o_cpu&0377,
535: a->o_pri, a->o_nice, a->o_addr0);
536: else if (uflg)
537: printf("%5.1f%4d ", a->o_pctcpu, a->o_nice);
538: if (lflg || uflg)
539: printf("%4d%5d", a->o_dsize+a->o_ssize, a->o_rssize);
540: if (lflg)
541: if (a->o_wchan)
542: printf("%6x", clear(a->o_wchan));
543: else
544: printf(" ");
545: printf(" %-2.2s", a->o_tty);
546: if (a->o_stat==SZOMB) {
547: printf(" <defunct>");
548: return(1);
549: }
550: tm = (a->o_utime + a->o_stime + 30)/60;
551: printf("%3ld:", tm/60);
552: tm %= 60;
553: printf(tm<10?"0%ld":"%ld", tm);
554: if (vflg) {
555: /*
556: tm = (a->o_stime + 30) / 60;
557: printf(" %2ld:", tm/60);
558: tm %= 60;
559: printf(tm<10?"0%ld":"%ld", tm);
560: */
561: printf("%4d%3d", a->o_time, a->o_slptime);
562: }
563: #ifdef notdef
564: if (0 && lflg==0) { /* 0 == old tflg (print long times) */
565: tm = (a->o_cstime + 30)/60;
566: printf(" %2ld:", tm/60);
567: tm %= 60;
568: printf(tm<10?"0%ld":"%ld", tm);
569: tm = (a->o_cutime + 30)/60;
570: printf(" %2ld:", tm/60);
571: tm %= 60;
572: printf(tm<10?"0%ld":"%ld", tm);
573: }
574: #endif
575: if (vflg) {
576: printf("%7d%7d",a->o_minorflt,a->o_majorflt);
577: printf("%5d%4d%4d", a->o_dsize+a->o_ssize, a->o_rssize, a->o_swrss);
578: printf("%5d%4d", a->o_xsize, a->o_xrssize);
579: printf("%3d", a->o_aveflt);
580: }
581: if (a->o_pid == 0) {
582: printf(" swapper");
583: return(1);
584: }
585: if (a->o_pid == 2) {
586: printf(" pagedaemon");
587: return(1);
588: }
589: if (cflg) {
590: printf(" %s", a->o_comm);
591: return(1);
592: }
593: a -> o_args[argwidth] = 0; /* force it to quit early */
594: printf(" %s", a->o_args);
595: return (1);
596: }
597:
598: char *
599: gettty()
600: {
601: register i;
602: register char *p;
603:
604: if (u.u_ttyp==0)
605: return("?");
606: for (i=0; i<ndev; i++) {
607: if (devl[i].dev == u.u_ttyd) {
608: p = devl[i].dname;
609: if (p[0]=='t' && p[1]=='t' && p[2]=='y')
610: p += 3;
611: return(p);
612: }
613: }
614: return("?");
615: }
616:
617: /*
618: * Given a base/size pair in virtual swap area,
619: * return a physical base/size pair which is the
620: * (largest) initial, physically contiguous block.
621: */
622: vstodb(vsbase, vssize, dmp, dbp, rev)
623: register int vsbase;
624: int vssize;
625: struct dmap *dmp;
626: register struct dblock *dbp;
627: {
628: register int blk = DMMIN;
629: register swblk_t *ip = dmp->dm_map;
630:
631: if (vsbase < 0 || vsbase + vssize > dmp->dm_size)
632: panic("vstodb");
633: while (vsbase >= blk) {
634: vsbase -= blk;
635: if (blk < DMMAX)
636: blk *= 2;
637: ip++;
638: }
639: if (*ip <= 0 || *ip + blk > nswap)
640: panic("vstodb *ip");
641: dbp->db_size = min(vssize, blk - vsbase);
642: dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase);
643: }
644:
645: panic(cp)
646: char *cp;
647: {
648:
649: #ifdef DEBUG
650: printf("%s\n", cp);
651: #endif
652: }
653:
654: min(a, b)
655: {
656:
657: return (a < b ? a : b);
658: }
659:
660: done(exitno)
661: {
662: if (login) {
663: printf("Press return when done: ");
664: getchar();
665: }
666: exit(exitno);
667: }
668:
669: /*
670: * fixup figures out everybodys name and sorts into a nice order.
671: */
672: fixup(np) int np; {
673: register int i;
674: register struct passwd *pw;
675: struct passwd *getpwent();
676:
677: if (uflg) {
678: /*
679: * If we want names, traverse the password file. For each
680: * passwd entry, look for it in the processes.
681: * In case of multiple entries in /etc/passwd, we believe
682: * the first one (same thing ls does).
683: */
684: while ((pw=getpwent()) != NULL) {
685: for (i=0; i<np; i++)
686: if (outargs[i].o_uid == pw -> pw_uid) {
687: if (outargs[i].o_uname[0] == 0)
688: strcpy(outargs[i].o_uname, pw -> pw_name);
689: }
690: }
691: }
692:
693: qsort(outargs, np, sizeof(outargs[0]), pscomp);
694: }
695:
696: pscomp(x1, x2) struct psout *x1, *x2; {
697: register int c;
698:
699: c = (x1)->o_ttyd - (x2)->o_ttyd;
700: if (c==0) c = (x1)->o_pid - (x2)->o_pid;
701: return(c);
702: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.