|
|
1.1 root 1: #include <sys/param.h>
2: #include <sys/dir.h>
3: #include <sys/file.h>
4: #include <sys/user.h>
5: #include <sys/inode.h>
6: #include <sys/proc.h>
7: #include <sys/pte.h>
8: #include <sys/text.h>
9: #include <sys/vm.h>
10: #include <stdio.h>
11: #include <ctype.h>
12: #include <nlist.h>
13: #include <pwd.h>
14: #include <sys/stat.h>
15: #include <ftw.h>
16:
17: struct nlist nl[] = {
18: { "_proc" },
19: #define X_PROC 0
20: { "_Usrptmap" },
21: #define X_USRPTMA 1
22: { "_usrpt" },
23: #define X_USRPT 2
24: { "_nswap" },
25: #define X_NSWAP 3
26: { "_nproc" },
27: #define X_NPROC 4
28: { 0 },
29: };
30:
31: #define PROCCHUNK 8 /* a few, for fewer syscalls */
32: struct proc proc[PROCCHUNK];
33: struct proc *mproc;
34:
35:
36: int paduser1; /* avoid hardware mem clobbering botch */
37: union {
38: struct user user;
39: char upages[UPAGES][NBPG];
40: } user;
41: #define u user.user
42: int paduser2; /* avoid hardware mem clobbering botch */
43:
44: #define clear(x) ((int)x & 0xfffff)
45:
46: int nswap;
47: struct pte *Usrptma, *usrpt;
48: int nproc;
49:
50: char *kmemf, *memf, *swapf, *nlistf;
51: int kmem, mem, swap;
52: long lseek();
53:
54: int pcbpf;
55: int argaddr;
56: extern char _sobuf[];
57:
58: main(argc, argv)
59: char **argv;
60: {
61: register int i, j;
62: off_t procp;
63:
64: initialize (argc, argv);
65: setbuf(stdout, _sobuf);
66: openfiles();
67: getkvars();
68: procp = getw((off_t) nl[X_PROC].n_value);
69: nproc = getw((off_t) nl[X_NPROC].n_value);
70: for (i=0; i<nproc; i += PROCCHUNK) {
71: KMlseek(kmem, (long) (char *)procp, 0);
72: j = nproc - i;
73: if (j > PROCCHUNK)
74: j = PROCCHUNK;
75: j *= sizeof (struct proc);
76: if (read(kmem, (char *)proc, j) != j)
77: cantread("proc table", kmemf);
78: procp += j;
79: for (j = j / sizeof (struct proc) - 1; j >= 0; j--) {
80: mproc = &proc[j];
81: if (mproc->p_stat == 0)
82: continue;
83: if (mproc->p_stat == SZOMB || getu() == 0)
84: continue;
85: doproc (mproc, &u);
86: }
87: }
88: return 0;
89: }
90:
91: getw(loc)
92: off_t loc;
93: {
94: long word;
95:
96: KMlseek(kmem, (long) loc, 0);
97: if (read(kmem, (char *) &word, sizeof (word)) != sizeof (word))
98: printf("error reading kmem at %x\n", loc);
99: return (word);
100: }
101:
102: openfiles()
103: {
104:
105: kmemf = "/dev/kmem";
106: kmem = open(kmemf, 0);
107: if (kmem < 0) {
108: perror(kmemf);
109: exit(1);
110: }
111: memf = "/dev/mem";
112: mem = open(memf, 0);
113: if (mem < 0) {
114: perror(memf);
115: exit(1);
116: }
117: swapf = "/dev/drum";
118: swap = open(swapf, 0);
119: if (swap < 0) {
120: perror(swapf);
121: exit(1);
122: }
123: }
124:
125: getkvars()
126: {
127: nlistf = "/unix";
128: nlist(nlistf, nl);
129: if (nl[0].n_type == 0) {
130: fprintf(stderr, "%s: No namelist\n", nlistf);
131: exit(1);
132: }
133: Usrptma = (struct pte *)nl[X_USRPTMA].n_value;
134: usrpt = (struct pte *)nl[X_USRPT].n_value;
135: KMlseek(kmem, (long)nl[X_NSWAP].n_value, 0);
136: if (read(kmem, (char *) &nswap, sizeof (nswap)) != sizeof (nswap)) {
137: cantread("nswap", kmemf);
138: exit(1);
139: }
140: }
141:
142: cantread(what, fromwhat)
143: char *what, *fromwhat;
144: {
145: fprintf(stderr, "ps: error reading %s from %s\n", what, fromwhat);
146: }
147:
148:
149:
150: getu()
151: {
152: struct pte *pteaddr, apte;
153: int pad1; /* avoid hardware botch */
154: struct pte arguutl[UPAGES+CLSIZE];
155: int pad2; /* avoid hardware botch */
156: register int i;
157: int ncl, size;
158:
159: size = sizeof (struct user);
160: if ((mproc->p_flag & SLOAD) == 0) {
161: lseek(swap, (long) ctob(mproc->p_swaddr), 0);
162: if (read(swap, (char *)&user.user, size) != size) {
163: fprintf(stderr, "ps: cant read u for pid %d from %s\n",
164: mproc->p_pid, swapf);
165: return (0);
166: }
167: pcbpf = 0;
168: argaddr = 0;
169: return (1);
170: }
171: pteaddr = &Usrptma[btokmx(mproc->p_p0br) + mproc->p_szpt - 1];
172: KMlseek(kmem, (long)pteaddr, 0);
173: if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) {
174: printf("ps: cant read indir pte to get u for pid %d from %s\n",
175: mproc->p_pid, swapf);
176: return (0);
177: }
178: lseek(mem,
179: (long) (ctob(apte.pg_pfnum+1) - (UPAGES+CLSIZE) * sizeof (struct pte)),
180: 0);
181: if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) {
182: printf("ps: cant read page table for u of pid %d from %s\n",
183: mproc->p_pid, swapf);
184: return (0);
185: }
186: if (arguutl[0].pg_fod == 0 && arguutl[0].pg_pfnum)
187: argaddr = ctob(arguutl[0].pg_pfnum);
188: else
189: argaddr = 0;
190: pcbpf = arguutl[CLSIZE].pg_pfnum;
191: ncl = (size + NBPG*CLSIZE - 1) / (NBPG*CLSIZE);
192: while (--ncl >= 0) {
193: i = ncl * CLSIZE;
194: lseek(mem, (long) ctob(arguutl[CLSIZE+i].pg_pfnum), 0);
195: if (read(mem, user.upages[i], CLSIZE*NBPG) != CLSIZE*NBPG) {
196: printf("ps: cant read page %d of u of pid %d from %s\n",
197: arguutl[CLSIZE+i].pg_pfnum, mproc->p_pid, memf);
198: return(0);
199: }
200: }
201: return (1);
202: }
203:
204: KMlseek(f, a, c)
205: long a;
206: {
207: lseek(f, a, c);
208: }
209:
210: #define NMAX 8
211: #define NUID 2048
212:
213: char names[NUID][NMAX+1];
214:
215: /*
216: * Stolen from ls...
217: */
218: char *
219: getname(uid)
220: {
221: register struct passwd *pw;
222: static init;
223: struct passwd *getpwent();
224:
225: if (uid >= 0 && uid < NUID && names[uid][0])
226: return (&names[uid][0]);
227: if (init == 2)
228: return (0);
229: if (init == 0)
230: setpwent(), init = 1;
231: while (pw = getpwent()) {
232: if (pw->pw_uid >= NUID)
233: continue;
234: if (names[pw->pw_uid][0])
235: continue;
236: strncpy(names[pw->pw_uid], pw->pw_name, NMAX);
237: if (pw->pw_uid == uid)
238: return (&names[uid][0]);
239: }
240: init = 2;
241: endpwent();
242: return (0);
243: }
244:
245: #define new(type) ((type *) alloc (sizeof (type)))
246:
247: char *freebase;
248: int nleft;
249:
250: char *
251: alloc(size)
252: int size;
253: {
254: register char *cp;
255: register int i;
256:
257: if (size > nleft) {
258: freebase = (char *)sbrk(i = size > 2048 ? size : 2048);
259: if (freebase == 0) {
260: fprintf(stderr, "ps: ran out of memory\n");
261: exit(1);
262: }
263: nleft = i - size;
264: } else
265: nleft -= size;
266: cp = freebase;
267: for (i = size; --i >= 0; )
268: *cp++ = 0;
269: freebase = cp;
270: return (cp - size);
271: }
272:
273: char *
274: savestr(cp)
275: char *cp;
276: {
277: register int len;
278: register char *dp;
279:
280: len = strlen(cp);
281: dp = (char *)alloc(len+1);
282: strcpy(dp, cp);
283: return (dp);
284: }
285:
286: /*
287: * read /dev, and record device names, block/character, and
288: * major/minor devices.
289: */
290:
291: #define DEVDIR "/dev"
292:
293: struct devdesc {
294: struct devdesc *next;
295: char *name;
296: int mode;
297: dev_t dev;
298: } *devhead;
299:
300: int
301: tryfile (name, p, code)
302: char *name;
303: register struct stat *p;
304: int code;
305: {
306: if (code == FTW_F) {
307: register int mode = p->st_mode & S_IFMT;
308: if (mode == S_IFBLK || mode == S_IFCHR) {
309: register struct devdesc *dp;
310: dp = new (struct devdesc);
311: dp->name = savestr (name + sizeof (DEVDIR));
312: dp->mode = mode;
313: dp->dev = p->st_rdev;
314: dp->next = devhead;
315: devhead = dp;
316: }
317: }
318: return 0;
319: }
320:
321: struct procdesc {
322: int pid;
323: struct procdesc *next;
324: } *prochead;
325:
326: struct pdevdesc {
327: dev_t dev;
328: int mode;
329: ino_t ino;
330: struct pdevdesc *next;
331: } *pdevhead;
332:
333: initialize(c, v)
334: int c;
335: char **v;
336: {
337: register int n;
338:
339: for (n = 1; n < c; n++) {
340: if (isnumber (v[n])) {
341: register struct procdesc *p;
342: p = new (struct procdesc);
343: p->pid = atoi (v[n]);
344: p->next = prochead;
345: prochead = p;
346: } else {
347: struct stat sb;
348: if (stat (v[n], &sb) < 0)
349: perror (v[n]);
350: else {
351: register int mode;
352: register struct pdevdesc *pd;
353: pd = new (struct pdevdesc);
354: mode = sb.st_mode & S_IFMT;
355: pd->mode = mode;
356: if (mode == S_IFBLK || mode == S_IFCHR) {
357: pd->dev = sb.st_rdev;
358: pd->ino = 0;
359: } else {
360: pd->dev = sb.st_dev;
361: pd->ino = sb.st_ino;
362: }
363: pd->next = pdevhead;
364: pdevhead = pd;
365: }
366: }
367: }
368:
369: if (pdevhead == NULL)
370: ftw (DEVDIR, tryfile, 3);
371: }
372:
373: int
374: isnumber (p)
375: register char *p;
376: {
377: while (isdigit (*p))
378: p++;
379: return *p == '\0';
380: }
381:
382: /*
383: * Here, we handle a process.
384: *
385: * Everything that has come before is essentially independent
386: * of what we are doing with the particular process.
387: *
388: * If pdevhead is set, we are just going to print process numbers.
389: * The global variable "found" will greatly assist us in this:
390: * it will be set nonzero as soon as we decide to print this process.
391: */
392:
393: int found;
394:
395: #undef u
396:
397: void
398: printdev (str, dev, mode, rmode, ino)
399: char *str;
400: dev_t dev;
401: int mode, rmode;
402: ino_t ino;
403: {
404: register struct devdesc *dp;
405: register struct pdevdesc *pd;
406:
407: mode &= IFMT;
408: rmode &= IFMT;
409:
410: if (pdevhead) {
411: if (!found) {
412: for (pd = pdevhead; pd; pd = pd->next) {
413: if (dev == pd->dev && (pd->ino ?
414: (ino == pd->ino && rmode == pd->mode) :
415: (mode == pd->mode))) {
416: found = 1;
417: return;
418: }
419: }
420: }
421: return;
422: }
423:
424: for (dp = devhead; dp; dp = dp->next) {
425: if (mode == dp->mode && dev == dp->dev) {
426: if (*str)
427: printf ("%s ", str);
428: if (ino)
429: printf ("%d ", ino);
430: if (*str)
431: printf ("on ");
432: printf ("%s", dp->name);
433: return;
434: }
435: }
436:
437: printf ("(%d/%d)", major (dev), minor (dev));
438: }
439:
440: struct inode *
441: getinode (ip, pid)
442: struct inode *ip;
443: {
444: static struct inode ibuf;
445: KMlseek (kmem, (long) ip, 0);
446: if (read (kmem, &ibuf, sizeof (ibuf)) != sizeof (ibuf)) {
447: fprintf (stderr, "proc %d: can't read inode at %lx\n", pid, ip);
448: return NULL;
449: }
450: return &ibuf;
451: }
452:
453: void
454: doinode (str, ip, pid)
455: register char *str;
456: register struct inode *ip;
457: {
458: int mode;
459:
460: if (ip && (ip = getinode (ip, pid))) {
461:
462: if (pdevhead) {
463: if (found)
464: return;
465: } else
466: printf ("\t%s: ", str);
467:
468: mode = ip->i_mode & IFMT;
469: switch (mode) {
470:
471: case IFDIR:
472: printdev ("dir", ip->i_dev, IFBLK, mode, ip->i_number);
473: break;
474:
475: case IFREG:
476: printdev ("file", ip->i_dev, IFBLK, mode, ip->i_number);
477: break;
478:
479: case IFLNK:
480: printdev ("slink", ip->i_dev, IFBLK, mode, ip->i_number);
481: break;
482:
483: case IFBLK:
484: case IFCHR:
485: printdev ("", ip->i_un.i_rdev, ip->i_mode, mode, (ino_t) 0);
486: break;
487:
488: default:
489: fprintf (stderr, "??? mode %o", ip->i_mode);
490: break;
491: }
492: if (pdevhead == NULL)
493: printf ("\n");
494: }
495:
496: }
497:
498: void
499: dotext (tp, pid)
500: register struct text *tp;
501: {
502: if (tp) {
503: struct text t;
504: KMlseek (kmem, (long) tp, 0);
505: if (read (kmem, &t, sizeof (t)) != sizeof (t)) {
506: fprintf (stderr, "can't read file at %lx\n", tp);
507: return;
508: }
509: doinode ("prog", t.x_iptr, pid);
510: }
511: }
512:
513: void
514: dofile (n, fp)
515: int n;
516: register struct file *fp;
517: {
518: if (fp) {
519: struct file f;
520: char buf[100];
521:
522: KMlseek (kmem, (long) fp, 0);
523: if (read (kmem, &f, sizeof (f)) != sizeof (f)) {
524: fprintf (stderr, "can't read file at %lx\n", fp);
525: return;
526: }
527: sprintf (buf, "fd %d at %ld", n, f.f_offset);
528: doinode (buf, f.f_inode);
529: }
530: }
531:
532: doproc (p, u)
533: register struct proc *p;
534: register struct user *u;
535: {
536: struct inode *ip;
537: register int i;
538:
539: found = 0;
540:
541: /* handle only selected processes if asked */
542: if (prochead) {
543: register struct procdesc *pd;
544:
545: pd = prochead;
546: while (pd && pd->pid != p->p_pid)
547: pd = pd->next;
548: if (pd == NULL)
549: return;
550: }
551:
552: if (pdevhead == NULL)
553: printf ("process %d, user %s\n", p->p_pid, getname(p->p_uid));
554:
555: dotext (p->p_textp, p->p_pid);
556: doinode ("cdir", u->u_cdir, p->p_pid);
557:
558: if (!found)
559: doinode ("rdir", u->u_rdir, p->p_pid);
560:
561: for (i = 0; i < NOFILE && !found; i++)
562: dofile (i, u->u_ofile[i]);
563:
564: if (pdevhead) {
565: if (found)
566: printf ("%d\n", p->p_pid);
567: } else {
568: printf ("\n");
569: fflush (stdout);
570: }
571: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.