|
|
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.