|
|
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[] = "@(#)ps.c 5.15 (Berkeley) 4/13/88";
15: #endif not lint
16:
17: #include <stdio.h>
18: #include <ctype.h>
19: #include <a.out.h>
20: #include <pwd.h>
21: #include <sys/param.h>
22: #include <sys/ioctl.h>
23: #include <sys/tty.h>
24: #include <sys/dir.h>
25: #include <sys/user.h>
26: #include <sys/proc.h>
27: #include <machine/pte.h>
28: #include <sys/vm.h>
29: #include <sys/text.h>
30: #include <sys/stat.h>
31: #include <sys/mbuf.h>
32: #include <math.h>
33: #include <errno.h>
34:
35: char *nl_names[] = {
36: "_proc",
37: #define X_PROC 0
38: "_Usrptmap",
39: #define X_USRPTMAP 1
40: "_usrpt",
41: #define X_USRPT 2
42: "_text",
43: #define X_TEXT 3
44: "_nswap",
45: #define X_NSWAP 4
46: "_maxslp",
47: #define X_MAXSLP 5
48: "_ccpu",
49: #define X_CCPU 6
50: "_ecmx",
51: #define X_ECMX 7
52: "_nproc",
53: #define X_NPROC 8
54: "_ntext",
55: #define X_NTEXT 9
56: "_dmmin",
57: #define X_DMMIN 10
58: "_dmmax",
59: #define X_DMMAX 11
60: "_Sysmap",
61: #define X_SYSMAP 12
62: "_Syssize",
63: #define X_SYSSIZE 13
64: "_inode",
65: #define X_INODE 14
66: "_file",
67: #define X_FILE 15
68: "_cfree",
69: #define X_CFREE 16
70: "_callout",
71: #define X_CALLOUT 17
72: "_swapmap",
73: #define X_SWAPMAP 18
74: "_argmap",
75: #define X_ARGMAP 19
76: "_kernelmap",
77: #define X_KERNELMAP 20
78: "_mbmap",
79: #define X_MBMAP 21
80: "_namecache",
81: #define X_NCH 22
82: "_quota",
83: #define X_QUOTA 23
84: "_dquot",
85: #define X_DQUOT 24
86: "_swbuf",
87: #define X_SWBUF 25
88: "_buf",
89: #define X_BUF 26
90: "_cmap",
91: #define X_CMAP 27
92: "_buffers",
93: #define X_BUFFERS 28
94: ""
95: };
96:
97: struct nlist *nl; /* all because we can't init unions */
98: int nllen; /* # of nlist entries */
99:
100: struct savcom {
101: union {
102: struct lsav *lp;
103: float u_pctcpu;
104: struct vsav *vp;
105: int s_ssiz;
106: } s_un;
107: struct asav *ap;
108: } *savcom;
109:
110: struct asav {
111: char *a_cmdp;
112: int a_flag;
113: short a_stat, a_uid, a_pid, a_nice, a_pri, a_slptime, a_time;
114: size_t a_size, a_rss, a_tsiz, a_txtrss;
115: short a_xccount;
116: char a_tty[MAXNAMLEN+1];
117: dev_t a_ttyd;
118: time_t a_cpu;
119: size_t a_maxrss;
120: };
121:
122: char *lhdr;
123: int wcwidth; /* width of the wchan field for sprintf*/
124: struct lsav {
125: short l_ppid;
126: u_char l_cpu;
127: int l_addr;
128: caddr_t l_wchan;
129: };
130:
131: char *uhdr;
132: char *shdr;
133:
134: char *vhdr;
135: struct vsav {
136: u_int v_majflt;
137: size_t v_swrss, v_txtswrss;
138: float v_pctcpu;
139: };
140:
141: #define NPROC 16
142:
143: struct proc proc[NPROC]; /* a few, for less syscalls */
144: struct proc *mproc;
145: struct text *text;
146:
147: union {
148: struct user user;
149: char upages[UPAGES][NBPG];
150: } user;
151: #define u user.user
152:
153: #ifndef PSFILE
154: char *psdb = "/etc/psdatabase";
155: #else
156: char *psdb = PSFILE;
157: #endif
158:
159: int chkpid = -1;
160: int aflg, cflg, eflg, gflg, kflg, lflg, nflg, sflg,
161: uflg, vflg, xflg, Uflg;
162: int nchans; /* total # of wait channels */
163: char *tptr;
164: char *gettty(), *getcmd(), *getname(), *savestr(), *state();
165: char *rindex(), *calloc(), *sbrk(), *strcpy(), *strcat(), *strncat();
166: char *strncpy(), *index(), *ttyname(), mytty[MAXPATHLEN+1];
167: char *malloc(), *getchan();
168: long lseek();
169: off_t vtophys();
170: double pcpu(), pmem();
171: int wchancomp();
172: int pscomp();
173: int nswap, maxslp;
174: struct text *atext;
175: double ccpu;
176: int ecmx;
177: struct pte *Usrptmap, *usrpt;
178: int nproc, ntext;
179: int dmmin, dmmax;
180: struct pte *Sysmap;
181: int Syssize;
182:
183: int nttys;
184:
185: struct ttys {
186: dev_t ttyd;
187: int cand;
188: char name[MAXNAMLEN+1];
189: } *allttys;
190: int cand[16] = {-1, -1, -1, -1, -1, -1, -1, -1,
191: -1, -1, -1, -1, -1, -1, -1, -1};
192: struct lttys {
193: struct ttys ttys;
194: struct lttys *next;
195: } *lallttys;
196:
197: /*
198: * struct for the symbolic wait channel info
199: *
200: * WNAMESIZ is the max # of chars saved of the symbolic wchan gleaned
201: * from the namelist. Normally, only WSNAMESIZ are printed in the long
202: * format, unless the terminal width is greater than WTSIZ wide.
203: */
204: #define WNAMESIZ 12
205: #define WSNAMESIZ 6
206: #define WTSIZ 95
207:
208: struct wchan {
209: char wc_name[WNAMESIZ+1]; /* symbolic name */
210: caddr_t wc_caddr; /* addr in kmem */
211: } *wchanhd; /* an array sorted by wc_caddr */
212:
213: #define NWCINDEX 10 /* the size of the index array */
214:
215: caddr_t wchan_index[NWCINDEX]; /* used to speed searches */
216: /*
217: * names listed here are not kept as wait channels -- this is used to
218: * remove names that confuse ps, like symbols that define the end of an
219: * array that happen to be equal to the next symbol.
220: */
221: char *wchan_stop_list[] = {
222: "umbabeg",
223: "umbaend",
224: "calimit",
225: NULL
226: };
227:
228: int npr;
229:
230: int cmdstart;
231: int twidth;
232: struct winsize win;
233: char *kmemf, *memf, *swapf, *nlistf;
234: int kmem, mem, swap = -1;
235: int rawcpu, sumcpu;
236:
237: int pcbpf;
238: int argaddr;
239:
240: #define pgtok(a) ((a)/(1024/NBPG))
241:
242: main(argc, argv)
243: char **argv;
244: {
245: register int i, j;
246: register char *ap;
247: int uid;
248: off_t procp;
249: int width;
250:
251: if (ioctl(1, TIOCGWINSZ, &win) == -1)
252: twidth = 80;
253: else
254: twidth = (win.ws_col == 0 ? 80 : win.ws_col);
255: argc--, argv++;
256: if (argc > 0) {
257: ap = argv[0];
258: while (*ap) switch (*ap++) {
259:
260: case 'C':
261: rawcpu++;
262: break;
263: case 'S':
264: sumcpu++;
265: break;
266:
267: case 'U':
268: Uflg++;
269: break;
270:
271: case 'a':
272: aflg++;
273: break;
274: case 'c':
275: cflg = !cflg;
276: break;
277: case 'e':
278: eflg++;
279: break;
280: case 'g':
281: gflg++;
282: break;
283: case 'k':
284: kflg++;
285: break;
286: case 'l':
287: lflg++;
288: break;
289: case 'n':
290: nflg++;
291: break;
292: case 's':
293: sflg++;
294: break;
295: case 't':
296: if (*ap)
297: tptr = ap;
298: else if ((tptr = ttyname(0)) != 0) {
299: tptr = strcpy(mytty, tptr);
300: if (strncmp(tptr, "/dev/", 5) == 0)
301: tptr += 5;
302: }
303: if (strncmp(tptr, "tty", 3) == 0)
304: tptr += 3;
305: aflg++;
306: gflg++;
307: if (tptr && *tptr == '?')
308: xflg++;
309: while (*ap)
310: ap++;
311: break;
312: case 'u':
313: uflg++;
314: break;
315: case 'v':
316: cflg = 1;
317: vflg++;
318: break;
319: case 'w':
320: if (twidth < 132)
321: twidth = 132;
322: else
323: twidth = BUFSIZ;
324: break;
325: case 'x':
326: xflg++;
327: break;
328: default:
329: if (!isdigit(ap[-1]))
330: break;
331: chkpid = atoi(--ap);
332: *ap = 0;
333: aflg++;
334: xflg++;
335: break;
336: }
337: }
338: openfiles(argc, argv);
339: getkvars(argc, argv);
340: uid = getuid();
341: printhdr();
342: procp = getw(nl[X_PROC].n_value);
343: nproc = getw(nl[X_NPROC].n_value);
344: savcom = (struct savcom *)calloc((unsigned) nproc, sizeof (*savcom));
345: for (i=0; i<nproc; i += NPROC) {
346: klseek(kmem, (long)procp, 0);
347: j = nproc - i;
348: if (j > NPROC)
349: j = NPROC;
350: j *= sizeof (struct proc);
351: if (read(kmem, (char *)proc, j) != j) {
352: cantread("proc table", kmemf);
353: exit(1);
354: }
355: procp += j;
356: for (j = j / sizeof (struct proc) - 1; j >= 0; j--) {
357: mproc = &proc[j];
358: if (mproc->p_stat == 0 ||
359: mproc->p_pgrp == 0 && xflg == 0)
360: continue;
361: if (tptr == 0 && gflg == 0 && xflg == 0 &&
362: mproc->p_ppid == 1)
363: continue;
364: if (uid != mproc->p_uid && aflg==0)
365: continue;
366: if (chkpid != -1 && chkpid != mproc->p_pid)
367: continue;
368: if (vflg && gflg == 0 && xflg == 0) {
369: if (mproc->p_stat == SZOMB ||
370: mproc->p_flag&SWEXIT)
371: continue;
372: if (mproc->p_slptime > MAXSLP &&
373: (mproc->p_stat == SSLEEP ||
374: mproc->p_stat == SSTOP))
375: continue;
376: }
377: save();
378: }
379: }
380: width = twidth - cmdstart - 2;
381: if (width < 0)
382: width = 0;
383: qsort((char *) savcom, npr, sizeof(savcom[0]), pscomp);
384: for (i=0; i<npr; i++) {
385: register struct savcom *sp = &savcom[i];
386: if (lflg)
387: lpr(sp);
388: else if (vflg)
389: vpr(sp);
390: else if (uflg)
391: upr(sp);
392: else
393: spr(sp);
394: if (sp->ap->a_stat == SZOMB)
395: printf(" %.*s", twidth - cmdstart - 2, "<defunct>");
396: else if (sp->ap->a_flag & SWEXIT)
397: printf(" %.*s", twidth - cmdstart - 2, "<exiting>");
398: else if (sp->ap->a_pid == 0)
399: printf(" %.*s", twidth - cmdstart - 2, "swapper");
400: else if (sp->ap->a_pid == 2)
401: printf(" %.*s", twidth - cmdstart - 2, "pagedaemon");
402: else
403: printf(" %.*s", twidth - cmdstart - 2, sp->ap->a_cmdp);
404: printf("\n");
405: }
406: exit(npr == 0);
407: }
408:
409: getw(loc)
410: unsigned long loc;
411: {
412: int word;
413:
414: klseek(kmem, (long)loc, 0);
415: if (read(kmem, (char *)&word, sizeof (word)) != sizeof (word))
416: printf("error reading kmem at %x\n", loc);
417: return (word);
418: }
419:
420: klseek(fd, loc, off)
421: int fd;
422: long loc;
423: int off;
424: {
425: if (kflg) {
426: if ((loc = vtophys(loc)) == -1)
427: return;
428: }
429: (void) lseek(fd, (long)loc, off);
430: }
431:
432: /*
433: * Version allows change of db format w/o temporarily bombing ps's
434: */
435: char thisversion[4] = "V2"; /* length must remain 4 */
436:
437: writepsdb(unixname)
438: char *unixname;
439: {
440: register FILE *fp;
441: struct lttys *lt;
442: struct stat stb;
443:
444: setgid(getgid());
445: setuid(getuid());
446: if ((fp = fopen(psdb, "w")) == NULL) {
447: perror(psdb);
448: exit(1);
449: } else
450: fchmod(fileno(fp), 0644);
451:
452: fwrite(thisversion, sizeof thisversion, 1, fp);
453: fwrite(unixname, strlen(unixname) + 1, 1, fp);
454: if (stat(unixname, &stb) < 0)
455: stb.st_mtime = 0;
456: fwrite((char *) &stb.st_mtime, sizeof stb.st_mtime, 1, fp);
457:
458: fwrite((char *) &nllen, sizeof nllen, 1, fp);
459: fwrite((char *) nl, sizeof (struct nlist), nllen, fp);
460: fwrite((char *) cand, sizeof (cand), 1, fp);
461: fwrite((char *) &nttys, sizeof nttys, 1, fp);
462: for (lt = lallttys ; lt ; lt = lt->next)
463: fwrite((char *)<->ttys, sizeof (struct ttys), 1, fp);
464: fwrite((char *) &nchans, sizeof nchans, 1, fp);
465: fwrite((char *) wchanhd, sizeof (struct wchan), nchans, fp);
466: fwrite((char *) wchan_index, sizeof (caddr_t), NWCINDEX, fp);
467: fclose(fp);
468: }
469:
470: readpsdb(unixname)
471: char *unixname;
472: {
473: register i;
474: register FILE *fp;
475: char unamebuf[BUFSIZ];
476: char *p = unamebuf;
477: char dbversion[sizeof thisversion];
478: struct stat stb;
479: time_t dbmtime;
480: extern int errno;
481:
482: if ((fp = fopen(psdb, "r")) == NULL) {
483: if (errno == ENOENT)
484: return (0);
485: perror(psdb);
486: exit(1);
487: }
488:
489: /*
490: * Does the db file match this unix?
491: */
492: fread(dbversion, sizeof dbversion, 1, fp);
493: if (bcmp(thisversion, dbversion, sizeof thisversion))
494: goto bad;
495: while ((*p = getc(fp)) != '\0')
496: p++;
497: if (strcmp(unixname, unamebuf))
498: goto bad;
499: fread((char *) &dbmtime, sizeof dbmtime, 1, fp);
500: if (stat(unixname, &stb) < 0)
501: stb.st_mtime = 0;
502: if (stb.st_mtime != dbmtime)
503: goto bad;
504:
505: fread((char *) &nllen, sizeof nllen, 1, fp);
506: nl = (struct nlist *) malloc (nllen * sizeof (struct nlist));
507: fread((char *) nl, sizeof (struct nlist), nllen, fp);
508: fread((char *) cand, sizeof (cand), 1, fp);
509: fread((char *) &nttys, sizeof nttys, 1, fp);
510: allttys = (struct ttys *)malloc(sizeof(struct ttys)*nttys);
511: if (allttys == NULL) {
512: fprintf(stderr, "ps: Can't malloc space for tty table\n");
513: exit(1);
514: }
515: fread((char *) allttys, sizeof (struct ttys), nttys, fp);
516: fread((char *) &nchans, sizeof nchans, 1, fp);
517: wchanhd = (struct wchan *) malloc(nchans * sizeof (struct wchan));
518: if (wchanhd == NULL) {
519: fprintf(stderr, "ps: Can't malloc space for wait channels\n");
520: nflg++;
521: fseek(fp, (long) nchans * sizeof (struct wchan), 1);
522: } else
523: fread((char *) wchanhd, sizeof (struct wchan), nchans, fp);
524: fread((char *) wchan_index, sizeof (caddr_t), NWCINDEX, fp);
525: fclose(fp);
526: return(1);
527:
528: bad:
529: fclose(fp);
530: return(0);
531: }
532:
533: openfiles(argc, argv)
534: char **argv;
535: {
536:
537: kmemf = "/dev/kmem";
538: if (kflg)
539: kmemf = argc > 2 ? argv[2] : "/vmcore";
540: kmem = open(kmemf, 0);
541: if (kmem < 0) {
542: perror(kmemf);
543: exit(1);
544: }
545: if (kflg) {
546: mem = kmem;
547: memf = kmemf;
548: } else {
549: memf = "/dev/mem";
550: mem = open(memf, 0);
551: if (mem < 0) {
552: perror(memf);
553: exit(1);
554: }
555: }
556: if (kflg == 0 || argc > 3) {
557: swapf = argc>3 ? argv[3]: "/dev/drum";
558: swap = open(swapf, 0);
559: if (swap < 0) {
560: perror(swapf);
561: exit(1);
562: }
563: }
564: }
565:
566: getkvars(argc, argv)
567: char **argv;
568: {
569: int faildb = 0; /* true if psdatabase init failed */
570: int i;
571:
572: nlistf = argc > 1 ? argv[1] : "/vmunix";
573: if (Uflg) {
574: init_nlist();
575: nlist(nlistf, nl);
576: getvchans();
577: getdev();
578: writepsdb(nlistf);
579: exit (0);
580: } else if (!readpsdb(nlistf)) {
581: init_nlist();
582: if (!kflg)
583: nl[X_SYSMAP].n_un.n_name = "";
584: faildb = 1;
585: nlist(nlistf, nl);
586: nttys = 0;
587: getdev();
588: }
589:
590: if (nl[0].n_type == 0) {
591: fprintf(stderr, "%s: No namelist\n", nlistf);
592: exit(1);
593: }
594: if (kflg) {
595: /* We must do the sys map first because klseek uses it */
596: long addr;
597:
598: Syssize = nl[X_SYSSIZE].n_value;
599: Sysmap = (struct pte *)
600: calloc((unsigned) Syssize, sizeof (struct pte));
601: if (Sysmap == NULL) {
602: fprintf(stderr, "Out of space for Sysmap\n");
603: exit(1);
604: }
605: addr = (long) nl[X_SYSMAP].n_value;
606: addr &= ~KERNBASE;
607: (void) lseek(kmem, addr, 0);
608: read(kmem, (char *) Sysmap, Syssize * sizeof (struct pte));
609: }
610: if (faildb)
611: getvchans();
612: usrpt = (struct pte *)nl[X_USRPT].n_value;
613: Usrptmap = (struct pte *)nl[X_USRPTMAP].n_value;
614: klseek(kmem, (long)nl[X_NSWAP].n_value, 0);
615: if (read(kmem, (char *)&nswap, sizeof (nswap)) != sizeof (nswap)) {
616: cantread("nswap", kmemf);
617: exit(1);
618: }
619: klseek(kmem, (long)nl[X_MAXSLP].n_value, 0);
620: if (read(kmem, (char *)&maxslp, sizeof (maxslp)) != sizeof (maxslp)) {
621: cantread("maxslp", kmemf);
622: exit(1);
623: }
624: klseek(kmem, (long)nl[X_CCPU].n_value, 0);
625: if (read(kmem, (char *)&ccpu, sizeof (ccpu)) != sizeof (ccpu)) {
626: cantread("ccpu", kmemf);
627: exit(1);
628: }
629: klseek(kmem, (long)nl[X_ECMX].n_value, 0);
630: if (read(kmem, (char *)&ecmx, sizeof (ecmx)) != sizeof (ecmx)) {
631: cantread("ecmx", kmemf);
632: exit(1);
633: }
634: if (uflg || vflg) {
635: ntext = getw(nl[X_NTEXT].n_value);
636: text = (struct text *)
637: calloc((unsigned) ntext, sizeof (struct text));
638: if (text == 0) {
639: fprintf(stderr, "no room for text table\n");
640: exit(1);
641: }
642: atext = (struct text *)getw(nl[X_TEXT].n_value);
643: klseek(kmem, (long)atext, 0);
644: if (read(kmem, (char *)text, ntext * sizeof (struct text))
645: != ntext * sizeof (struct text)) {
646: cantread("text table", kmemf);
647: exit(1);
648: }
649: }
650: dmmin = getw(nl[X_DMMIN].n_value);
651: dmmax = getw(nl[X_DMMAX].n_value);
652: }
653:
654: /*
655: * get the valloc'ed kernel variables for symbolic wait channels
656: */
657: getvchans()
658: {
659: int i, tmp;
660:
661: if (nflg)
662: return;
663:
664: #define addv(i) addchan(&nl[i].n_un.n_name[1], getw(nl[i].n_value))
665: addv(X_INODE);
666: addv(X_FILE);
667: addv(X_PROC);
668: addv(X_TEXT);
669: addv(X_CFREE);
670: addv(X_CALLOUT);
671: addv(X_SWAPMAP);
672: addv(X_ARGMAP);
673: addv(X_KERNELMAP);
674: addv(X_MBMAP);
675: addv(X_NCH);
676: if (nl[X_QUOTA].n_value != 0) { /* these are #ifdef QUOTA */
677: addv(X_QUOTA);
678: addv(X_DQUOT);
679: }
680: addv(X_SWBUF);
681: addv(X_BUF);
682: addv(X_CMAP);
683: addv(X_BUFFERS);
684: qsort(wchanhd, nchans, sizeof (struct wchan), wchancomp);
685: for (i = 0; i < NWCINDEX; i++) {
686: tmp = i * nchans;
687: wchan_index[i] = wchanhd[tmp / NWCINDEX].wc_caddr;
688: }
689: #undef addv
690: }
691: printhdr()
692: {
693: char *hdr;
694:
695: if (sflg+lflg+vflg+uflg > 1) {
696: fprintf(stderr, "ps: specify only one of s,l,v and u\n");
697: exit(1);
698: }
699: if (lflg) {
700: if (nflg)
701: wcwidth = 6;
702: else if (twidth > WTSIZ)
703: wcwidth = -WNAMESIZ;
704: else
705: wcwidth = -WSNAMESIZ;
706: if ((hdr = malloc(strlen(lhdr) + WNAMESIZ)) == NULL) {
707: fprintf(stderr, "ps: out of memory\n");
708: exit(1);
709: }
710: (void)sprintf(hdr, lhdr, wcwidth, "WCHAN");
711: } else if (vflg)
712: hdr = vhdr;
713: else if (uflg) {
714: /* add enough on so that it can hold the sprintf below */
715: if ((hdr = malloc(strlen(uhdr) + 10)) == NULL) {
716: fprintf(stderr, "ps: out of memory\n");
717: exit(1);
718: }
719: (void)sprintf(hdr, uhdr, nflg ? " UID" : "USER ");
720: } else
721: hdr = shdr;
722: if (lflg+vflg+uflg+sflg == 0)
723: hdr += strlen("SSIZ ");
724: cmdstart = strlen(hdr);
725: printf("%s COMMAND\n", hdr);
726: (void) fflush(stdout);
727: }
728:
729: cantread(what, fromwhat)
730: char *what, *fromwhat;
731: {
732:
733: fprintf(stderr, "ps: error reading %s from %s\n", what, fromwhat);
734: }
735:
736: struct direct *dbuf;
737: int dialbase;
738:
739: getdev()
740: {
741: register DIR *df;
742: struct ttys *t;
743: struct lttys *lt;
744:
745: if (chdir("/dev") < 0) {
746: perror("/dev");
747: exit(1);
748: }
749: dialbase = -1;
750: if ((df = opendir(".")) == NULL) {
751: fprintf(stderr, "Can't open . in /dev\n");
752: exit(1);
753: }
754: while ((dbuf = readdir(df)) != NULL)
755: maybetty();
756: closedir(df);
757: allttys = (struct ttys *)malloc(sizeof(struct ttys)*nttys);
758: if (allttys == NULL) {
759: fprintf(stderr, "ps: Can't malloc space for tty table\n");
760: exit(1);
761: }
762: for (lt = lallttys, t = allttys; lt ; lt = lt->next, t++)
763: *t = lt->ttys;
764: }
765:
766: /*
767: * Attempt to avoid stats by guessing minor device
768: * numbers from tty names. Console is known,
769: * know that r(hp|up|mt) are unlikely as are different mem's,
770: * floppy, null, tty, etc.
771: */
772: maybetty()
773: {
774: register char *cp = dbuf->d_name;
775: static struct lttys *dp;
776: struct lttys *olddp;
777: int x;
778: struct stat stb;
779:
780: switch (cp[0]) {
781:
782: case 'c':
783: if (!strcmp(cp, "console")) {
784: x = 0;
785: goto donecand;
786: }
787: /* cu[la]? are possible!?! don't rule them out */
788: break;
789:
790: case 'd':
791: if (!strcmp(cp, "drum"))
792: return;
793: break;
794:
795: case 'f':
796: if (!strcmp(cp, "floppy"))
797: return;
798: break;
799:
800: case 'k':
801: cp++;
802: if (*cp == 'U')
803: cp++;
804: goto trymem;
805:
806: case 'r':
807: cp++;
808: #define is(a,b) cp[0] == 'a' && cp[1] == 'b'
809: if (is(h,p) || is(r,a) || is(u,p) || is(h,k)
810: || is(r,b) || is(m,t)) {
811: cp += 2;
812: if (isdigit(*cp) && cp[2] == 0)
813: return;
814: }
815: break;
816:
817: case 'm':
818: trymem:
819: if (cp[0] == 'm' && cp[1] == 'e' && cp[2] == 'm' && cp[3] == 0)
820: return;
821: if (cp[0] == 'm' && cp[1] == 't')
822: return;
823: break;
824:
825: case 'n':
826: if (!strcmp(cp, "null"))
827: return;
828: if (!strncmp(cp, "nrmt", 4))
829: return;
830: break;
831:
832: case 'p':
833: if (cp[1] && cp[1] == 't' && cp[2] == 'y')
834: return;
835: break;
836:
837: case 'v':
838: if ((cp[1] == 'a' || cp[1] == 'p') && isdigit(cp[2]) &&
839: cp[3] == 0)
840: return;
841: break;
842: }
843: cp = dbuf->d_name + dbuf->d_namlen - 1;
844: x = 0;
845: if (cp[-1] == 'd') {
846: if (dialbase == -1) {
847: if (stat("ttyd0", &stb) == 0)
848: dialbase = stb.st_rdev & 017;
849: else
850: dialbase = -2;
851: }
852: if (dialbase == -2)
853: x = 0;
854: else
855: x = 11;
856: }
857: if (cp > dbuf->d_name && isdigit(cp[-1]) && isdigit(*cp))
858: x += 10 * (cp[-1] - ' ') + cp[0] - '0';
859: else if (*cp >= 'a' && *cp <= 'f')
860: x += 10 + *cp - 'a';
861: else if (isdigit(*cp))
862: x += *cp - '0';
863: else
864: x = -1;
865: donecand:
866: olddp = dp;
867: dp = (struct lttys *)malloc(sizeof(struct lttys));
868: if (dp == NULL) {
869: fprintf(stderr, "ps: Can't malloc space for tty table\n");
870: exit(1);
871: }
872: if (lallttys == NULL)
873: lallttys = dp;
874: nttys++;
875: if (olddp)
876: olddp->next = dp;
877: dp->next = NULL;
878: (void) strcpy(dp->ttys.name, dbuf->d_name);
879: if (Uflg) {
880: if (stat(dp->ttys.name, &stb) == 0 &&
881: (stb.st_mode&S_IFMT)==S_IFCHR)
882: dp->ttys.ttyd = x = stb.st_rdev;
883: else {
884: nttys--;
885: if (lallttys == dp)
886: lallttys = NULL;
887: free(dp);
888: dp = olddp;
889: if (dp)
890: dp->next = NULL;
891: return;
892: }
893: } else
894: dp->ttys.ttyd = -1;
895: if (x == -1)
896: return;
897: x &= 017;
898: dp->ttys.cand = cand[x];
899: cand[x] = nttys-1;
900: }
901:
902: char *
903: gettty()
904: {
905: register char *p;
906: register struct ttys *dp;
907: struct stat stb;
908: int x;
909:
910: if (u.u_ttyp == 0)
911: return(" ?");
912: x = u.u_ttyd & 017;
913: for (dp = &allttys[cand[x]]; dp != &allttys[-1];
914: dp = &allttys[dp->cand]) {
915: if (dp->ttyd == -1) {
916: if (stat(dp->name, &stb) == 0 &&
917: (stb.st_mode&S_IFMT)==S_IFCHR)
918: dp->ttyd = stb.st_rdev;
919: else
920: dp->ttyd = -2;
921: }
922: if (dp->ttyd == u.u_ttyd)
923: goto found;
924: }
925: /* ick */
926: for (dp = allttys; dp < &allttys[nttys]; dp++) {
927: if (dp->ttyd == -1) {
928: if (stat(dp->name, &stb) == 0 &&
929: (stb.st_mode&S_IFMT)==S_IFCHR)
930: dp->ttyd = stb.st_rdev;
931: else
932: dp->ttyd = -2;
933: }
934: if (dp->ttyd == u.u_ttyd)
935: goto found;
936: }
937: return ("?");
938: found:
939: p = dp->name;
940: if (p[0]=='t' && p[1]=='t' && p[2]=='y')
941: p += 3;
942: return (p);
943: }
944:
945: save()
946: {
947: register struct savcom *sp;
948: register struct asav *ap;
949: register char *cp;
950: register struct text *xp;
951: char *ttyp, *cmdp;
952:
953: if (mproc->p_stat != SZOMB && getu() == 0)
954: return;
955: ttyp = gettty();
956: if (xflg == 0 && ttyp[0] == '?' || tptr && strncmp(tptr, ttyp, 2))
957: return;
958: sp = &savcom[npr];
959: cmdp = getcmd();
960: if (cmdp == 0)
961: return;
962: sp->ap = ap = (struct asav *)calloc(1, sizeof (struct asav));
963: sp->ap->a_cmdp = cmdp;
964: #define e(a,b) ap->a = mproc->b
965: e(a_flag, p_flag); e(a_stat, p_stat); e(a_nice, p_nice);
966: e(a_uid, p_uid); e(a_pid, p_pid); e(a_pri, p_pri);
967: e(a_slptime, p_slptime); e(a_time, p_time);
968: ap->a_tty[0] = ttyp[0];
969: ap->a_tty[1] = ttyp[1] ? ttyp[1] : ' ';
970: if (ap->a_stat == SZOMB) {
971: ap->a_cpu = 0;
972: } else {
973: ap->a_size = mproc->p_dsize + mproc->p_ssize;
974: e(a_rss, p_rssize);
975: ap->a_ttyd = u.u_ttyd;
976: ap->a_cpu = u.u_ru.ru_utime.tv_sec + u.u_ru.ru_stime.tv_sec;
977: if (sumcpu)
978: ap->a_cpu += u.u_cru.ru_utime.tv_sec + u.u_cru.ru_stime.tv_sec;
979: if (mproc->p_textp && text) {
980: xp = &text[mproc->p_textp - atext];
981: ap->a_tsiz = xp->x_size;
982: ap->a_txtrss = xp->x_rssize;
983: ap->a_xccount = xp->x_ccount;
984: }
985: }
986: #undef e
987: ap->a_maxrss = mproc->p_maxrss;
988: if (lflg) {
989: register struct lsav *lp;
990:
991: sp->s_un.lp = lp = (struct lsav *)
992: calloc(1, sizeof (struct lsav));
993: #define e(a,b) lp->a = mproc->b
994: e(l_ppid, p_ppid); e(l_cpu, p_cpu);
995: if (ap->a_stat != SZOMB)
996: e(l_wchan, p_wchan);
997: #undef e
998: lp->l_addr = pcbpf;
999: } else if (vflg) {
1000: register struct vsav *vp;
1001:
1002: sp->s_un.vp = vp = (struct vsav *)
1003: calloc(1, sizeof (struct vsav));
1004: #define e(a,b) vp->a = mproc->b
1005: if (ap->a_stat != SZOMB) {
1006: e(v_swrss, p_swrss);
1007: vp->v_majflt = u.u_ru.ru_majflt;
1008: if (mproc->p_textp)
1009: vp->v_txtswrss = xp->x_swrss;
1010: }
1011: vp->v_pctcpu = pcpu();
1012: #undef e
1013: } else if (uflg)
1014: sp->s_un.u_pctcpu = pcpu();
1015: else if (sflg) {
1016: if (ap->a_stat != SZOMB) {
1017: for (cp = (char *)u.u_stack;
1018: cp < &user.upages[UPAGES][0]; )
1019: if (*cp++)
1020: break;
1021: sp->s_un.s_ssiz = (&user.upages[UPAGES][0] - cp);
1022: }
1023: }
1024:
1025: npr++;
1026: }
1027:
1028: double
1029: pmem(ap)
1030: register struct asav *ap;
1031: {
1032: double fracmem;
1033: int szptudot;
1034:
1035: if ((ap->a_flag&SLOAD) == 0)
1036: fracmem = 0.0;
1037: else {
1038: szptudot = UPAGES + clrnd(ctopt(ap->a_size+ap->a_tsiz));
1039: fracmem = ((float)ap->a_rss+szptudot)/CLSIZE/ecmx;
1040: if (ap->a_xccount)
1041: fracmem += ((float)ap->a_txtrss)/CLSIZE/
1042: ap->a_xccount/ecmx;
1043: }
1044: return (100.0 * fracmem);
1045: }
1046:
1047: double
1048: pcpu()
1049: {
1050: time_t time;
1051:
1052: time = mproc->p_time;
1053: if (time == 0 || (mproc->p_flag&SLOAD) == 0)
1054: return (0.0);
1055: if (rawcpu)
1056: return (100.0 * mproc->p_pctcpu);
1057: return (100.0 * mproc->p_pctcpu / (1.0 - exp(time * log(ccpu))));
1058: }
1059:
1060: getu()
1061: {
1062: struct pte *pteaddr, apte;
1063: struct pte arguutl[UPAGES+CLSIZE];
1064: register int i;
1065: int ncl, size;
1066:
1067: size = sflg ? ctob(UPAGES) : sizeof (struct user);
1068: if ((mproc->p_flag & SLOAD) == 0) {
1069: if (swap < 0)
1070: return (0);
1071: (void) lseek(swap, (long)dtob(mproc->p_swaddr), 0);
1072: if (read(swap, (char *)&user.user, size) != size) {
1073: fprintf(stderr, "ps: cant read u for pid %d from %s\n",
1074: mproc->p_pid, swapf);
1075: return (0);
1076: }
1077: pcbpf = 0;
1078: argaddr = 0;
1079: return (1);
1080: }
1081: pteaddr = &Usrptmap[btokmx(mproc->p_p0br) + mproc->p_szpt - 1];
1082: klseek(kmem, (long)pteaddr, 0);
1083: if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) {
1084: printf("ps: cant read indir pte to get u for pid %d from %s\n",
1085: mproc->p_pid, kmemf);
1086: return (0);
1087: }
1088: lseek(mem,
1089: (long)ctob(apte.pg_pfnum+1) - (UPAGES+CLSIZE) * sizeof (struct pte),
1090: 0);
1091: if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) {
1092: printf("ps: cant read page table for u of pid %d from %s\n",
1093: mproc->p_pid, memf);
1094: return (0);
1095: }
1096: if (arguutl[0].pg_fod == 0 && arguutl[0].pg_pfnum)
1097: argaddr = ctob(arguutl[0].pg_pfnum);
1098: else
1099: argaddr = 0;
1100: pcbpf = arguutl[CLSIZE].pg_pfnum;
1101: ncl = (size + NBPG*CLSIZE - 1) / (NBPG*CLSIZE);
1102: while (--ncl >= 0) {
1103: i = ncl * CLSIZE;
1104: lseek(mem, (long)ctob(arguutl[CLSIZE+i].pg_pfnum), 0);
1105: if (read(mem, user.upages[i], CLSIZE*NBPG) != CLSIZE*NBPG) {
1106: printf("ps: cant read page %d of u of pid %d from %s\n",
1107: arguutl[CLSIZE+i].pg_pfnum, mproc->p_pid, memf);
1108: return(0);
1109: }
1110: }
1111: return (1);
1112: }
1113:
1114: char *
1115: getcmd()
1116: {
1117: char cmdbuf[CLSIZE*NBPG];
1118: union {
1119: char argc[CLSIZE*NBPG];
1120: int argi[CLSIZE*NBPG/sizeof (int)];
1121: } argspac;
1122: register char *cp;
1123: register int *ip;
1124: char c;
1125: int nbad;
1126: struct dblock db;
1127: char *file;
1128:
1129: if (mproc->p_stat == SZOMB || mproc->p_flag&(SSYS|SWEXIT))
1130: return ("");
1131: if (cflg) {
1132: (void) strncpy(cmdbuf, u.u_comm, sizeof (u.u_comm));
1133: return (savestr(cmdbuf));
1134: }
1135: if ((mproc->p_flag & SLOAD) == 0 || argaddr == 0) {
1136: if (swap < 0)
1137: goto retucomm;
1138: vstodb(0, CLSIZE, &u.u_smap, &db, 1);
1139: (void) lseek(swap, (long)dtob(db.db_base), 0);
1140: if (read(swap, (char *)&argspac, sizeof(argspac))
1141: != sizeof(argspac))
1142: goto bad;
1143: file = swapf;
1144: } else {
1145: lseek(mem, (long)argaddr, 0);
1146: if (read(mem, (char *)&argspac, sizeof (argspac))
1147: != sizeof (argspac))
1148: goto bad;
1149: file = memf;
1150: }
1151: ip = &argspac.argi[CLSIZE*NBPG/sizeof (int)];
1152: ip -= 2; /* last arg word and .long 0 */
1153: while (*--ip)
1154: if (ip == argspac.argi)
1155: goto retucomm;
1156: *(char *)ip = ' ';
1157: ip++;
1158: nbad = 0;
1159: for (cp = (char *)ip; cp < &argspac.argc[CLSIZE*NBPG]; cp++) {
1160: c = *cp & 0177;
1161: if (c == 0)
1162: *cp = ' ';
1163: else if (c < ' ' || c > 0176) {
1164: if (++nbad >= 5*(eflg+1)) {
1165: *cp++ = ' ';
1166: break;
1167: }
1168: *cp = '?';
1169: } else if (eflg == 0 && c == '=') {
1170: while (*--cp != ' ')
1171: if (cp <= (char *)ip)
1172: break;
1173: break;
1174: }
1175: }
1176: *cp = 0;
1177: while (*--cp == ' ')
1178: *cp = 0;
1179: cp = (char *)ip;
1180: (void) strncpy(cmdbuf, cp, &argspac.argc[CLSIZE*NBPG] - cp);
1181: if (cp[0] == '-' || cp[0] == '?' || cp[0] <= ' ') {
1182: (void) strcat(cmdbuf, " (");
1183: (void) strncat(cmdbuf, u.u_comm, sizeof(u.u_comm));
1184: (void) strcat(cmdbuf, ")");
1185: }
1186: return (savestr(cmdbuf));
1187:
1188: bad:
1189: fprintf(stderr, "ps: error locating command name for pid %d from %s\n",
1190: mproc->p_pid, file);
1191: retucomm:
1192: (void) strcpy(cmdbuf, " (");
1193: (void) strncat(cmdbuf, u.u_comm, sizeof (u.u_comm));
1194: (void) strcat(cmdbuf, ")");
1195: return (savestr(cmdbuf));
1196: }
1197:
1198: char *lhdr =
1199: " F UID PID PPID CP PRI NI ADDR SZ RSS %*sSTAT TT TIME";
1200: lpr(sp)
1201: struct savcom *sp;
1202: {
1203: register struct asav *ap = sp->ap;
1204: register struct lsav *lp = sp->s_un.lp;
1205:
1206: printf("%6x %4d %5u %5u %2d %3d %2d %4x %5d %4d",
1207: (ap->a_flag &~ SPTECHG), /* XXX */
1208: ap->a_uid, ap->a_pid, lp->l_ppid,
1209: lp->l_cpu > 99 ? 99 : lp->l_cpu, ap->a_pri-PZERO,
1210: ap->a_nice, lp->l_addr, pgtok(ap->a_size), pgtok(ap->a_rss));
1211: if (lp->l_wchan == 0)
1212: printf(" %*s", wcwidth, "");
1213: else if (nflg)
1214: printf(" %*x", wcwidth, (int)lp->l_wchan&~KERNBASE);
1215: else
1216: printf(" %*.*s", wcwidth, abs(wcwidth), getchan(lp->l_wchan));
1217: printf(" %-2.3s ", state(ap));
1218: ptty(ap->a_tty);
1219: ptime(ap);
1220: }
1221:
1222: ptty(tp)
1223: char *tp;
1224: {
1225:
1226: printf("%-2.2s", tp);
1227: }
1228:
1229: ptime(ap)
1230: struct asav *ap;
1231: {
1232:
1233: printf(" %3ld:%02ld", ap->a_cpu / 60, ap->a_cpu % 60);
1234: }
1235:
1236: char *uhdr =
1237: "%s PID %%CPU %%MEM SZ RSS TT STAT TIME";
1238: upr(sp)
1239: struct savcom *sp;
1240: {
1241: register struct asav *ap = sp->ap;
1242: int vmsize, rmsize;
1243:
1244: vmsize = pgtok((ap->a_size + ap->a_tsiz));
1245: rmsize = pgtok(ap->a_rss);
1246: if (ap->a_xccount)
1247: rmsize += pgtok(ap->a_txtrss/ap->a_xccount);
1248: if (nflg)
1249: printf("%4d ", ap->a_uid);
1250: else
1251: printf("%-8.8s ", getname(ap->a_uid));
1252: printf("%5d %4.1f %4.1f %5d %5d",
1253: ap->a_pid, sp->s_un.u_pctcpu, pmem(ap), vmsize, rmsize);
1254: putchar(' ');
1255: ptty(ap->a_tty);
1256: printf(" %-2.3s", state(ap));
1257: ptime(ap);
1258: }
1259:
1260: char *vhdr =
1261: " SIZE PID TT STAT TIME SL RE PAGEIN SIZE RSS LIM TSIZ TRS %CPU %MEM"+5;
1262: vpr(sp)
1263: struct savcom *sp;
1264: {
1265: register struct vsav *vp = sp->s_un.vp;
1266: register struct asav *ap = sp->ap;
1267:
1268: printf("%5u ", ap->a_pid);
1269: ptty(ap->a_tty);
1270: printf(" %-2.3s", state(ap));
1271: ptime(ap);
1272: printf(" %2d %2d %6d %5d %5d",
1273: ap->a_slptime > 99 ? 99 : ap-> a_slptime,
1274: ap->a_time > 99 ? 99 : ap->a_time, vp->v_majflt,
1275: pgtok(ap->a_size), pgtok(ap->a_rss));
1276: if (ap->a_maxrss == (RLIM_INFINITY/NBPG))
1277: printf(" xx");
1278: else
1279: printf(" %5d", pgtok(ap->a_maxrss));
1280: printf(" %4d %3d %4.1f %4.1f",
1281: pgtok(ap->a_tsiz), pgtok(ap->a_txtrss), vp->v_pctcpu, pmem(ap));
1282: }
1283:
1284: char *shdr =
1285: "SSIZ PID TT STAT TIME";
1286: spr(sp)
1287: struct savcom *sp;
1288: {
1289: register struct asav *ap = sp->ap;
1290:
1291: if (sflg)
1292: printf("%4d ", sp->s_un.s_ssiz);
1293: printf("%5u", ap->a_pid);
1294: putchar(' ');
1295: ptty(ap->a_tty);
1296: printf(" %-2.3s", state(ap));
1297: ptime(ap);
1298: }
1299:
1300: char *
1301: state(ap)
1302: register struct asav *ap;
1303: {
1304: static char res[5];
1305: char *cp = res;
1306:
1307: switch (ap->a_stat) {
1308:
1309: case SSTOP:
1310: *cp = 'T';
1311: break;
1312:
1313: case SSLEEP:
1314: if (ap->a_pri >= PZERO)
1315: if (ap->a_slptime >= MAXSLP)
1316: *cp = 'I';
1317: else
1318: *cp = 'S';
1319: else if (ap->a_flag & SPAGE)
1320: *cp = 'P';
1321: else
1322: *cp = 'D';
1323: break;
1324:
1325: case SWAIT:
1326: case SRUN:
1327: case SIDL:
1328: *cp = 'R';
1329: break;
1330:
1331: case SZOMB:
1332: *cp = 'Z';
1333: break;
1334:
1335: default:
1336: *cp = '?';
1337: }
1338: cp++;
1339: if (ap->a_flag & SLOAD) {
1340: if (ap->a_rss > ap->a_maxrss)
1341: *cp++ = '>';
1342: } else
1343: *cp++ = 'W';
1344: if (ap->a_nice < NZERO)
1345: *cp++ = '<';
1346: else if (ap->a_nice > NZERO)
1347: *cp++ = 'N';
1348: if (ap->a_flag & SUANOM)
1349: *cp++ = 'A';
1350: else if (ap->a_flag & SSEQL)
1351: *cp++ = 'S';
1352: *cp = '\0';
1353: return (res);
1354: }
1355:
1356: /*
1357: * Given a base/size pair in virtual swap area,
1358: * return a physical base/size pair which is the
1359: * (largest) initial, physically contiguous block.
1360: */
1361: vstodb(vsbase, vssize, dmp, dbp, rev)
1362: register int vsbase;
1363: int vssize;
1364: struct dmap *dmp;
1365: register struct dblock *dbp;
1366: {
1367: register int blk = dmmin;
1368: register swblk_t *ip = dmp->dm_map;
1369:
1370: vsbase = ctod(vsbase);
1371: vssize = ctod(vssize);
1372: if (vsbase < 0 || vsbase + vssize > dmp->dm_size)
1373: panic("vstodb");
1374: while (vsbase >= blk) {
1375: vsbase -= blk;
1376: if (blk < dmmax)
1377: blk *= 2;
1378: ip++;
1379: }
1380: if (*ip <= 0 || *ip + blk > nswap)
1381: panic("vstodb *ip");
1382: dbp->db_size = min(vssize, blk - vsbase);
1383: dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase);
1384: }
1385:
1386: /*ARGSUSED*/
1387: panic(cp)
1388: char *cp;
1389: {
1390:
1391: #ifdef DEBUG
1392: printf("%s\n", cp);
1393: #endif
1394: }
1395:
1396: min(a, b)
1397: {
1398:
1399: return (a < b ? a : b);
1400: }
1401:
1402: pscomp(s1, s2)
1403: struct savcom *s1, *s2;
1404: {
1405: register int i;
1406:
1407: if (uflg)
1408: return (s2->s_un.u_pctcpu > s1->s_un.u_pctcpu ? 1 : -1);
1409: if (vflg)
1410: return (vsize(s2) - vsize(s1));
1411: i = s1->ap->a_ttyd - s2->ap->a_ttyd;
1412: if (i == 0)
1413: i = s1->ap->a_pid - s2->ap->a_pid;
1414: return (i);
1415: }
1416:
1417: vsize(sp)
1418: struct savcom *sp;
1419: {
1420: register struct asav *ap = sp->ap;
1421: register struct vsav *vp = sp->s_un.vp;
1422:
1423: if (ap->a_flag & SLOAD)
1424: return (ap->a_rss +
1425: ap->a_txtrss / (ap->a_xccount ? ap->a_xccount : 1));
1426: return (vp->v_swrss + (ap->a_xccount ? 0 : vp->v_txtswrss));
1427: }
1428:
1429: #include <utmp.h>
1430:
1431: struct utmp utmp;
1432: #define NMAX (sizeof (utmp.ut_name))
1433: #define SCPYN(a, b) strncpy(a, b, NMAX)
1434:
1435: #define NUID 64
1436:
1437: struct ncache {
1438: int uid;
1439: char name[NMAX+1];
1440: } nc[NUID];
1441:
1442: /*
1443: * This function assumes that the password file is hashed
1444: * (or some such) to allow fast access based on a uid key.
1445: */
1446: char *
1447: getname(uid)
1448: {
1449: register struct passwd *pw;
1450: struct passwd *getpwent();
1451: register int cp;
1452: extern int _pw_stayopen;
1453:
1454: _pw_stayopen = 1;
1455:
1456: #if (((NUID) & ((NUID) - 1)) != 0)
1457: cp = uid % (NUID);
1458: #else
1459: cp = uid & ((NUID) - 1);
1460: #endif
1461: if (uid >= 0 && nc[cp].uid == uid && nc[cp].name[0])
1462: return (nc[cp].name);
1463: pw = getpwuid(uid);
1464: if (!pw)
1465: return (0);
1466: nc[cp].uid = uid;
1467: SCPYN(nc[cp].name, pw->pw_name);
1468: return (nc[cp].name);
1469: }
1470:
1471: char *
1472: savestr(cp)
1473: char *cp;
1474: {
1475: register unsigned len;
1476: register char *dp;
1477:
1478: len = strlen(cp);
1479: dp = (char *)calloc(len+1, sizeof (char));
1480: (void) strcpy(dp, cp);
1481: return (dp);
1482: }
1483:
1484: /*
1485: * This routine was stolen from adb to simulate memory management
1486: * on the VAX.
1487: */
1488: off_t
1489: vtophys(loc)
1490: long loc;
1491: {
1492: register p;
1493: off_t newloc;
1494:
1495: newloc = loc & ~KERNBASE;
1496: p = btop(newloc);
1497: if ((loc & KERNBASE) == 0) {
1498: fprintf(stderr, "Vtophys: translating non-kernel address\n");
1499: return((off_t) -1);
1500: }
1501: if (p >= Syssize) {
1502: fprintf(stderr, "Vtophys: page out of bound (%d>=%d)\n",
1503: p, Syssize);
1504: return((off_t) -1);
1505: }
1506: if (Sysmap[p].pg_v == 0
1507: && (Sysmap[p].pg_fod || Sysmap[p].pg_pfnum == 0)) {
1508: fprintf(stderr, "Vtophys: page not valid\n");
1509: return((off_t) -1);
1510: }
1511: loc = (long) (ptob(Sysmap[p].pg_pfnum) + (loc & PGOFSET));
1512: return(loc);
1513: }
1514:
1515: /*
1516: * since we can't init unions, the cleanest way to use a.out.h instead
1517: * of nlist.h (required since nlist() uses some defines) is to do a
1518: * runtime copy into the nl array -- sigh
1519: */
1520: init_nlist()
1521: {
1522: register struct nlist *np;
1523: register char **namep;
1524:
1525: nllen = sizeof nl_names / sizeof (char *);
1526: np = nl = (struct nlist *) malloc(nllen * sizeof (struct nlist));
1527: if (np == NULL) {
1528: fprintf(stderr, "ps: out of memory allocating namelist\n");
1529: exit(1);
1530: }
1531: namep = &nl_names[0];
1532: while (nllen > 0) {
1533: np->n_un.n_name = *namep;
1534: if (**namep == '\0')
1535: break;
1536: namep++;
1537: np++;
1538: }
1539: }
1540:
1541: /*
1542: * nlist - retreive attributes from name list (string table version)
1543: * modified to add wait channels - Charles R. LaBrec 8/85
1544: */
1545: nlist(name, list)
1546: char *name;
1547: struct nlist *list;
1548: {
1549: register struct nlist *p, *q;
1550: register char *s1, *s2;
1551: register n, m;
1552: int maxlen, nreq;
1553: FILE *f;
1554: FILE *sf;
1555: off_t sa; /* symbol address */
1556: off_t ss; /* start of strings */
1557: int type;
1558: struct exec buf;
1559: struct nlist space[BUFSIZ/sizeof (struct nlist)];
1560: char nambuf[BUFSIZ];
1561:
1562: maxlen = 0;
1563: for (q = list, nreq = 0; q->n_un.n_name && q->n_un.n_name[0]; q++, nreq++) {
1564: q->n_type = 0;
1565: q->n_value = 0;
1566: q->n_desc = 0;
1567: q->n_other = 0;
1568: n = strlen(q->n_un.n_name);
1569: if (n > maxlen)
1570: maxlen = n;
1571: }
1572: f = fopen(name, "r");
1573: if (f == NULL)
1574: return (-1);
1575: fread((char *)&buf, sizeof buf, 1, f);
1576: if (N_BADMAG(buf)) {
1577: fclose(f);
1578: return (-1);
1579: }
1580: sf = fopen(name, "r");
1581: if (sf == NULL) {
1582: /* ??? */
1583: fclose(f);
1584: return(-1);
1585: }
1586: sa = N_SYMOFF(buf);
1587: ss = sa + buf.a_syms;
1588: n = buf.a_syms;
1589: fseek(f, sa, 0);
1590: while (n) {
1591: m = sizeof (space);
1592: if (n < m)
1593: m = n;
1594: if (fread((char *)space, m, 1, f) != 1)
1595: break;
1596: n -= m;
1597: for (q = space; (m -= sizeof(struct nlist)) >= 0; q++) {
1598: if (q->n_un.n_strx == 0 || q->n_type & N_STAB)
1599: continue;
1600: /*
1601: * since we know what type of symbols we will get,
1602: * we can make a quick check here -- crl
1603: */
1604: type = q->n_type & (N_TYPE | N_EXT);
1605: if ((q->n_type & N_TYPE) != N_ABS
1606: && type != (N_EXT | N_DATA)
1607: && type != (N_EXT | N_BSS))
1608: continue;
1609: fseek(sf, ss+q->n_un.n_strx, 0);
1610: fread(nambuf, maxlen+1, 1, sf);
1611: /* if using wchans, add it to the list of channels */
1612: if (!nflg)
1613: addchan(&nambuf[1], (caddr_t) q->n_value);
1614: for (p = list; p->n_un.n_name && p->n_un.n_name[0]; p++) {
1615: s1 = p->n_un.n_name;
1616: s2 = nambuf;
1617: if (strcmp(p->n_un.n_name, nambuf) == 0) {
1618: p->n_value = q->n_value;
1619: p->n_type = q->n_type;
1620: p->n_desc = q->n_desc;
1621: p->n_other = q->n_other;
1622: --nreq;
1623: break;
1624: }
1625: }
1626: }
1627: }
1628: alldone:
1629: fclose(f);
1630: fclose(sf);
1631: return (nreq);
1632: }
1633:
1634: /*
1635: * add the given channel to the channel list
1636: */
1637: addchan(name, caddr)
1638: char *name;
1639: caddr_t caddr;
1640: {
1641: static int left = 0;
1642: register struct wchan *wp;
1643: register char **p;
1644:
1645: for (p = wchan_stop_list; *p; p++) {
1646: if (**p != *name) /* quick check first */
1647: continue;
1648: if (strncmp(name, *p, WNAMESIZ) == 0)
1649: return; /* if found, don't add */
1650: }
1651: if (left == 0) {
1652: if (wchanhd) {
1653: left = 100;
1654: wchanhd = (struct wchan *) realloc(wchanhd,
1655: (nchans + left) * sizeof (struct wchan));
1656: } else {
1657: left = 600;
1658: wchanhd = (struct wchan *) malloc(left
1659: * sizeof (struct wchan));
1660: }
1661: if (wchanhd == NULL) {
1662: fprintf(stderr, "ps: out of memory allocating wait channels\n");
1663: nflg++;
1664: return;
1665: }
1666: }
1667: left--;
1668: wp = &wchanhd[nchans++];
1669: strncpy(wp->wc_name, name, WNAMESIZ);
1670: wp->wc_name[WNAMESIZ] = '\0';
1671: wp->wc_caddr = caddr;
1672: }
1673:
1674: /*
1675: * returns the symbolic wait channel corresponding to chan
1676: */
1677: char *
1678: getchan(chan)
1679: register caddr_t chan;
1680: {
1681: register i, iend;
1682: register char *prevsym;
1683: register struct wchan *wp;
1684:
1685: prevsym = "???"; /* nothing, to begin with */
1686: if (chan) {
1687: for (i = 0; i < NWCINDEX; i++)
1688: if ((unsigned) chan < (unsigned) wchan_index[i])
1689: break;
1690: iend = i--;
1691: if (i < 0) /* can't be found */
1692: return prevsym;
1693: iend *= nchans;
1694: iend /= NWCINDEX;
1695: i *= nchans;
1696: i /= NWCINDEX;
1697: wp = &wchanhd[i];
1698: for ( ; i < iend; i++, wp++) {
1699: if ((unsigned) wp->wc_caddr > (unsigned) chan)
1700: break;
1701: prevsym = wp->wc_name;
1702: }
1703: }
1704: return prevsym;
1705: }
1706:
1707: /*
1708: * used in sorting the wait channel array
1709: */
1710: int
1711: wchancomp (w1, w2)
1712: struct wchan *w1, *w2;
1713: {
1714: register unsigned c1, c2;
1715:
1716: c1 = (unsigned) w1->wc_caddr;
1717: c2 = (unsigned) w2->wc_caddr;
1718: if (c1 > c2)
1719: return 1;
1720: else if (c1 == c2)
1721: return 0;
1722: else
1723: return -1;
1724: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.