1: char *sccsid = "%W%"; 2: 3: /* 4: * ps - process status 5: * This is the augmented UCB ps for 2.9BSD PDP-11 Unix (11/82). 6: * It is not very portable, using the phys sys call and 7: * knowing the format of an a.out symbol table. 8: * Examine and print certain things about processes 9: * Usage: ps [ acgklnrtuwxU# ] [ corefile [ swapfile [ system ] ] ] 10: */ 11: 12: #include "whoami.h" 13: #include <sys/param.h> 14: #include <stdio.h> 15: #include <pwd.h> 16: #include <a.out.h> 17: #include <core.h> 18: #include <ctype.h> 19: #include <sys/proc.h> 20: #include <sys/stat.h> 21: #include <sys/tty.h> 22: #include <sys/dir.h> 23: #include <sys/user.h> 24: #include <psout.h> 25: 26: #define equal !strcmp 27: #define exists(x) (stat ((x), &stbuf) == 0) 28: #define within(x,y,z) (((unsigned)(x) >= (y)) && ((unsigned)(x) < (z))) 29: #define round(x,y) ((long) ((((long) (x) + (long) (y) - 1L) / (long) (y)) * (long) (y))) 30: 31: struct nlist nl[] = { 32: { "_proc" , 0, 0}, 33: #define X_PROC 0 34: { "_swplo" , 0, 0}, 35: #define X_SWPLO 1 36: { "_nproc", 0, 0}, 37: #define X_NPROC 2 38: { "_hz", 0, 0}, 39: #define X_HZ 3 40: 0 41: }; 42: #define NNAMESIZ (sizeof nl[0].n_name) 43: 44: struct proc *mproc, proc [8]; 45: struct user u; 46: struct stat stbuf; 47: 48: int hz; 49: int chkpid = 0; 50: int aflg; /* -a: all processes, not just mine */ 51: int cflg; /* -c: not complete listing of args, 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 nflg; /* -n: numeric wchans */ 56: int rflg; /* -r: raw output in style <psout.h> */ 57: int uflg; /* -u: user name */ 58: int wflg; /* -w[w]: wide terminal */ 59: int xflg; /* -x: ALL processes, even those without ttys */ 60: int Uflg; /* -U: update the private list */ 61: char *tptr, *mytty; 62: char *nlistf, *uname; 63: int file; 64: off_t swplo; 65: int nproc; 66: off_t tell; 67: int nchans; 68: int ndev; 69: int nsyms; 70: int ismem; 71: #ifndef PSFILE 72: char *psdb = "/etc/psdatabase"; 73: #else 74: char *psdb = PSFILE; 75: #endif 76: 77: /* 78: * Structure for the unix wchan table 79: */ 80: struct wchan { 81: char cname [NNAMESIZ]; 82: unsigned caddr; 83: }; 84: struct wchan *wchanhd; 85: 86: char *calloc (), *malloc (), *realloc (); 87: char *gettty (), *getptr (), *getchan (); 88: char *ttyname (); 89: int pscomp (); 90: int wchancomp (); 91: off_t lseek (); 92: 93: #ifndef NUMDEV 94: #define NUMDEV 256 95: #endif 96: struct devl { 97: char dname[DIRSIZ]; 98: dev_t dev; 99: } devl[NUMDEV]; 100: 101: struct map { 102: off_t b1, e1; off_t f1; 103: off_t b2, e2; off_t f2; 104: }; 105: struct map datmap; 106: 107: struct psout *outargs; /* info for first npr processes */ 108: int npr; /* number of processes found so far */ 109: int twidth; /* terminal width */ 110: int cmdstart; /* starting position for command field */ 111: 112: char *memf; /* name of kernel memory file to use */ 113: char *kmemf; /* name of physical memory file to use */ 114: char *swapf; /* name of swap file to use */ 115: char *nlistf; /* name of symbol table file to use */ 116: int kmem, mem, swap; 117: extern char _sobuf[]; 118: #ifdef TERMCAP 119: char *getenv (); 120: #endif 121: 122: main (argc, argv) 123: char **argv; 124: { 125: int uid, euid, puid, nread; 126: register i, j; 127: char *ap; 128: register struct proc *procp; 129: #ifdef TERMCAP 130: char *termp, capbuf [1024]; 131: #endif 132: 133: #ifdef TERMCAP 134: if ((termp = getenv ("TERM")) != (char *) NULL) 135: if (tgetent (capbuf, termp) == 1) 136: twidth = tgetnum ("co"); 137: else ; 138: else 139: #endif 140: twidth = 80; 141: 142: setbuf (stdout, _sobuf); 143: argc--, argv++; 144: if (argc > 0) { 145: ap = argv [0]; 146: while (*ap) switch (*ap++) { 147: case '-': 148: break; 149: 150: case 'a': 151: aflg++; 152: break; 153: 154: case 'c': 155: cflg++; 156: break; 157: 158: case 'g': 159: gflg++; 160: break; 161: 162: case 'k': 163: kflg++; 164: break; 165: 166: case 'l': 167: lflg = 1; 168: break; 169: 170: case 'n': 171: nflg++; 172: lflg = 1; 173: break; 174: 175: case 'r': 176: rflg++; 177: break; 178: 179: case 't': 180: if (*ap) 181: tptr = ap; 182: aflg++; 183: gflg++; 184: if (*tptr == '?') 185: xflg++; 186: while (*ap) 187: ap++; 188: break; 189: 190: case 'u': 191: uflg = 1; 192: break; 193: 194: case 'U': 195: Uflg++; 196: break; 197: 198: case 'w': 199: if (twidth == 80) 200: twidth = 132; 201: else twidth = BUFSIZ; 202: wflg++; 203: break; 204: 205: case 'x': 206: xflg++; 207: break; 208: 209: default: 210: if (!isdigit (ap[-1])) 211: break; 212: chkpid = atoi (--ap); 213: *ap = '\0'; 214: aflg++; 215: xflg++; 216: break; 217: } 218: } 219: 220: openfiles (argc, argv); 221: getkvars (argc, argv); 222: if (kflg) 223: swplo = (off_t) 0; 224: uid = getuid (); 225: euid = geteuid (); 226: mytty = ttyname (0); 227: printhdr (); 228: for (i = 0; i < nproc; i += 8) { 229: j = nproc - i; 230: if (j > 8) 231: j = 8; 232: j *= sizeof (struct proc); 233: if ((nread = read (kmem, (char *) proc, j)) != j) { 234: cantread ("proc table", kmemf); 235: if (nread == -1) 236: break; 237: } 238: for (j = nread / sizeof (struct proc) - 1; j >= 0; j--) { 239: mproc = &proc[j]; 240: procp = mproc; 241: /* skip processes that don't exist */ 242: if (procp->p_stat == 0) 243: continue; 244: /* skip those without a tty unless -x */ 245: if (procp->p_pgrp == 0 && xflg == 0) 246: continue; 247: /* skip group leaders on a tty unless -g, -x, or -t.. */ 248: #ifdef MENLO_JCL 249: if (!tptr && !gflg && !xflg && procp->p_ppid == 1 && (procp->p_flag & SDETACH) == 0) 250: #else 251: if (!tptr && !gflg && !xflg && procp->p_pid == procp->p_pgrp) 252: #endif 253: continue; 254: /* -g also skips those where **argv is "-" - see savcom */ 255: puid = procp->p_uid; 256: /* skip other peoples processes unless -a or a specific pid */ 257: if ((uid != puid && euid != puid && aflg == 0) || 258: (chkpid != 0 && chkpid != procp->p_pid)) 259: continue; 260: if (savcom (puid)) 261: npr++; 262: } 263: } 264: fixup (npr); 265: for (i = 0; i < npr; i++) { 266: #ifdef TERMCAP 267: register cmdwidth = twidth - cmdstart - 2; 268: #endif 269: register struct psout *a = &outargs[i]; 270: 271: if (rflg) { 272: if (write (1, (char *) a, sizeof (struct psout)) != sizeof (struct psout)) 273: perror ("write"); 274: continue; 275: } 276: else if (lflg) 277: lpr (a); 278: else if (uflg) 279: upr (a); 280: else spr (a); 281: #ifdef TERMCAP 282: if (cmdwidth < 0) 283: cmdwidth = 80 - cmdstart - 2; 284: #endif 285: if (a->o_stat == SZOMB) 286: #ifdef TERMCAP 287: printf ("%.*s", cmdwidth, " <defunct>"); 288: #else 289: printf (" <defunct>"); 290: #endif 291: else if (a->o_pid == 0) 292: #ifdef TERMCAP 293: printf ("%.*s", cmdwidth, " swapper"); 294: #else 295: printf (" swapper"); 296: #endif 297: else printf (" %.*s", twidth - cmdstart - 2, cflg ? a->o_comm : a->o_args); 298: putchar ('\n'); 299: } 300: exit (!npr); 301: } 302: 303: /* 304: * Getdev() changes directories so it should be 305: * called only after other necessary files have 306: * been opened. 307: */ 308: getdev () 309: { 310: register FILE *df; 311: struct direct dbuf; 312: register struct direct *dirp = &dbuf; 313: 314: if ((chdir ("/dev") < 0) || ((df = fopen (".", "r")) == NULL)) 315: perrexit ("/dev"); 316: while (fread ((char *) &dbuf, sizeof (dbuf), 1, df) == 1) { 317: if (dirp->d_ino == 0) 318: continue; 319: if (!exists (dirp->d_name)) 320: continue; 321: if ((stbuf.st_mode&S_IFMT) != S_IFCHR) 322: continue; 323: strncpy (devl[ndev].dname, dirp->d_name, sizeof devl[ndev].dname); 324: devl[ndev].dev = stbuf.st_rdev; 325: ndev++; 326: } 327: fclose (df); 328: } 329: 330: savcom (puid) 331: { 332: char *tp; 333: off_t addr; 334: #ifdef VIRUS_VFORK 335: off_t daddr, saddr; 336: #endif 337: register struct psout *a; 338: register struct proc *procp = mproc; 339: register struct user *up = &u; 340: long txtsiz, datsiz, stksiz; 341: int septxt; 342: 343: if (procp->p_flag & SLOAD) { 344: addr = ctob ((off_t) procp->p_addr); 345: #ifdef VIRUS_VFORK 346: daddr = ctob ((off_t) procp->p_daddr); 347: saddr = ctob ((off_t) procp->p_saddr); 348: #endif 349: file = mem; 350: } else { 351: addr = (procp->p_addr + swplo) << 9; 352: #ifdef VIRUS_VFORK 353: daddr = (procp->p_daddr + swplo) << 9; 354: saddr = (procp->p_saddr + swplo) << 9; 355: #endif 356: file = swap; 357: } 358: if (pread (file, (char *) up, sizeof (u), addr) != sizeof (u)) 359: return (0); 360: 361: /* set up address maps for user pcs */ 362: txtsiz = ctob (up->u_tsize); 363: datsiz = ctob (up->u_dsize); 364: stksiz = ctob (up->u_ssize); 365: septxt = up->u_sep; 366: datmap.b1 = (septxt ? 0 : round (txtsiz, TXTRNDSIZ)); 367: datmap.e1 = datmap.b1 + datsiz; 368: #ifdef VIRUS_VFORK 369: datmap.f1 = daddr; 370: #else 371: datmap.f1 = ctob (USIZE) + addr; 372: #endif 373: datmap.b2 = stackbas (stksiz); 374: datmap.e2 = stacktop (stksiz); 375: #ifdef VIRUS_VFORK 376: datmap.f2 = saddr; 377: #else 378: datmap.f2 = ctob (USIZE) + (datmap.e1 - datmap.b1) + addr; 379: #endif 380: 381: tp = gettty (); 382: if ((tptr && strcmp (tptr, tp)) || (strcmp (mytty, tp) && !aflg)) 383: return (0); 384: 385: a = &outargs[npr]; 386: /* saving com starts here */ 387: a->o_uid = puid; 388: a->o_pid = procp->p_pid; 389: a->o_flag = procp->p_flag; 390: a->o_ppid = procp->p_ppid; 391: a->o_cpu = procp->p_cpu; 392: a->o_pri = procp->p_pri; 393: a->o_nice = procp->p_nice; 394: a->o_addr0 = procp->p_addr; 395: #ifdef VIRUS_VFORK 396: a->o_size = ctod(procp->p_dsize + procp->p_ssize + USIZE); 397: #else 398: a->o_size = (procp->p_size + 7) >> 3; 399: #endif 400: a->o_wchan = procp->p_wchan; 401: a->o_pgrp = procp->p_pgrp; 402: strncpy (a->o_tty, tp, 8); 403: a->o_ttyd = tp[0] == '?' ? -1 : up->u_ttyd; 404: a->o_stat = procp->p_stat; 405: a->o_flag = procp->p_flag; 406: 407: if (a->o_stat == SZOMB) 408: return (1); 409: a->o_utime = up->u_utime; 410: a->o_stime = up->u_stime; 411: a->o_cutime = up->u_cutime; 412: a->o_cstime = up->u_cstime; 413: a->o_sigs = (int)up->u_signal[SIGINT] + (int)up->u_signal[SIGQUIT]; 414: a->o_uname[0] = 0; 415: strncpy (a->o_comm, up->u_comm, 14); 416: 417: if (cflg) 418: return (1); 419: #ifdef VIRUS_VFORK 420: else return (getcmd (a, saddr)); 421: #else 422: else return (getcmd (a, addr)); 423: #endif 424: } 425: 426: 427: char * 428: gettty () 429: { 430: register i; 431: register char *p; 432: 433: if (u.u_ttyp == 0) 434: return ("?"); 435: for (i = 0; i < ndev; i++) { 436: if (devl[i].dev == u.u_ttyd) { 437: p = devl[i].dname; 438: if (p[0] == 't' && p[1] == 't' && p[2] == 'y') 439: p += 3; 440: return (p); 441: } 442: } 443: return ("?"); 444: } 445: 446: char * 447: ttyname (fd) 448: { 449: register i; 450: register char *p; 451: struct stat statb; 452: 453: if (fstat (fd, &statb)) 454: return ("?"); 455: for (i = 0; i < ndev; i++) { 456: if (devl[i].dev == statb.st_rdev) { 457: p = devl[i].dname; 458: if (p[0] == 't' && p[1] == 't' && p[2] == 'y') 459: p += 3; 460: return (p); 461: } 462: } 463: return ("?"); 464: } 465: 466: /* 467: * fixup figures out everybodys name and sorts into a nice order. 468: */ 469: fixup (np) 470: register np; 471: { 472: register i; 473: register struct passwd *pw; 474: struct passwd *getpwent (); 475: 476: if (uflg) { 477: /* 478: * If we want names, traverse the password file. For each 479: * passwd entry, look for it in the processes. 480: * In case of multiple entries in /etc/passwd, we believe 481: * the first one (same thing ls does). 482: */ 483: while ((pw = getpwent ()) != (struct passwd *) NULL) { 484: for (i = 0; i < np; i++) 485: if (outargs[i].o_uid == pw->pw_uid) { 486: if (outargs[i].o_uname[0] == 0) 487: strcpy (outargs[i].o_uname, pw->pw_name); 488: } 489: } 490: } 491: 492: qsort (outargs, np, sizeof (outargs[0]), pscomp); 493: } 494: 495: pscomp (x1, x2) 496: register struct psout *x1, *x2; 497: { 498: register c; 499: 500: c = (x1)->o_ttyd - (x2)->o_ttyd; 501: if (c == 0) 502: c = (x1)->o_pid - (x2)->o_pid; 503: return (c); 504: } 505: 506: wchancomp (x1, x2) 507: register struct wchan *x1, *x2; 508: { 509: if (x1->caddr > x2->caddr) 510: return (1); 511: else if (x1->caddr == x2->caddr) 512: return (0); 513: else return (-1); 514: } 515: 516: char * 517: getptr (adr) 518: char **adr; 519: { 520: char *ptr; 521: register char *p, *pa; 522: register i; 523: 524: ptr = 0; 525: pa = (char *)adr; 526: p = (char *)&ptr; 527: for (i = 0; i < sizeof (ptr); i++) 528: *p++ = getbyte (pa++); 529: return (ptr); 530: } 531: 532: getbyte (adr) 533: register char *adr; 534: { 535: register struct map *amap = &datmap; 536: char b; 537: off_t saddr; 538: 539: if (!within (adr, amap->b1, amap->e1)) 540: if (within (adr, amap->b2, amap->e2)) 541: saddr = (unsigned) adr + amap->f2 - amap->b2; 542: else return (0); 543: else saddr = (unsigned) adr + amap->f1 - amap->b1; 544: if (lseek (file, saddr, 0) == (off_t) -1 || read (file, &b, 1) < 1) 545: return (0); 546: return ((unsigned) b); 547: } 548: 549: /* 550: * pread is like read, but if it's /dev/mem we use the phys 551: * system call for speed. On systems without phys we have 552: * to use regular read. 553: */ 554: pread (fd, ptr, nbytes, loc) 555: char *ptr; 556: off_t loc; 557: { 558: register rc; 559: 560: if (fd == mem && ismem) { 561: rc = phys (6, nbytes / 64 + 1, (short) (loc / 64)); 562: if (rc >= 0) { 563: bmove (0140000, ptr, nbytes); 564: return (nbytes); 565: } 566: } 567: lseek (fd, loc, 0); 568: return (read (fd, ptr, nbytes)); 569: } 570: 571: addchan (name, caddr) 572: char *name; 573: unsigned caddr; 574: { 575: register nc = nchans; 576: register struct wchan *wp = wchanhd; 577: 578: if (nc == 0) 579: wp = (struct wchan *) malloc (sizeof (struct wchan)); 580: else wp = (struct wchan *) realloc (wp, sizeof (struct wchan) * (nc + 1)); 581: if (wp == (struct wchan *) NULL) 582: err ("Too many symbols"); 583: strncpy (wp[nc].cname, name, NNAMESIZ - 1); 584: wp[nc].cname[NNAMESIZ-1] = '\0'; 585: wp[nc].caddr = caddr; 586: wchanhd = wp; 587: nchans++; 588: } 589: 590: char * 591: getchan (chan) 592: register unsigned chan; 593: { 594: register i; 595: register char *prevsym; 596: 597: prevsym = ""; 598: if (chan) 599: for (i = 0; i < nchans; i++) { 600: if (wchanhd[i].caddr > chan) 601: return (prevsym); 602: prevsym = wchanhd[i].cname; 603: } 604: return (prevsym); 605: } 606: 607: nlist (aout, tgt) 608: char *aout; 609: struct nlist *tgt; 610: { 611: register i; 612: register FILE *aaa; 613: register struct nlist *nnn; 614: int iii, nllen; 615: struct ovlhdr ovlbuf; 616: static struct nlist nbuf; 617: static struct exec hbuf; 618: off_t sa = (off_t) 0; 619: 620: nllen = sizeof nl / sizeof (struct nlist); 621: if ((aaa = fopen (aout, "r")) == 0 ) 622: perrexit (aout); 623: if (fread (&hbuf, sizeof hbuf, 1, aaa) != 1 ) 624: err ("Invalid symbol table"); 625: if (N_BADMAG (hbuf)) { 626: fprintf (stderr, "%s: not in object file format\n", aout); 627: exit (1); 628: } 629: if (hbuf.a_magic == A_MAGIC5 || hbuf.a_magic == A_MAGIC6) { 630: fread ((char *) &ovlbuf, 1, sizeof ovlbuf, aaa); 631: for (i = 0; i < NOVL; i++) 632: sa += (off_t) (ovlbuf.ov_siz)[i]; 633: fseek (aaa, sa, 1); 634: } 635: sa = (off_t) hbuf.a_text + hbuf.a_data; 636: if ((hbuf.a_flag & 01) == 0) 637: sa *= (off_t) 2; 638: fseek (aaa, sa, 1); 639: nsyms = hbuf.a_syms / sizeof nbuf; 640: if (nsyms == 0) { 641: fprintf (stderr, "%s: no symbol table\n", aout); 642: exit (1); 643: } 644: while (--nsyms >= 0 && fread (&nbuf, sizeof (nbuf), 1, aaa) == 1 ) { 645: if (nbuf.n_name[0] != '_' ) 646: continue; 647: iii = nbuf.n_type&(N_TYPE|N_EXT); 648: if ((nbuf.n_type&N_TYPE) != N_ABS && iii != (N_EXT|N_DATA) && iii != (N_EXT|N_BSS) ) 649: continue; 650: if (!nflg) 651: addchan (nbuf.n_name+1, (unsigned) (nbuf.n_value)); 652: if (nllen) 653: for (nnn = tgt; nnn->n_name[0] != '\0'; nnn++ ) 654: if (!strncmp (nnn->n_name, nbuf.n_name, NNAMESIZ)) { 655: nnn->n_value = nbuf.n_value; 656: nnn->n_type = nbuf.n_type; 657: nllen--; 658: break; 659: } 660: } 661: fclose (aaa); 662: if (!nflg) 663: qsort (wchanhd, nchans, sizeof (struct wchan), wchancomp); 664: return (nllen == 0 ? 0 : -1); 665: } 666: 667: err (msg) 668: char *msg; 669: { 670: fprintf (stderr, "%s\n", msg); 671: exit (1); 672: } 673: 674: perrexit (msg) 675: char *msg; 676: { 677: perror (msg); 678: exit (1); 679: } 680: 681: writepsdb (unixname) 682: char *unixname; 683: { 684: int nllen; 685: register FILE *fp; 686: 687: setuid (getuid ()); 688: if ((fp = fopen (psdb, "w")) == NULL) 689: perrexit (psdb); 690: else chmod (psdb, 0644); 691: nllen = sizeof nl / sizeof (struct nlist); 692: fwrite (unixname, strlen (unixname) + 1, 1, fp); 693: fwrite ((char *) &nllen, sizeof nllen, 1, fp); 694: fwrite ((char *) &ndev, sizeof ndev, 1, fp); 695: fwrite ((char *) &nchans, sizeof nchans, 1, fp); 696: fwrite ((char *) nl, sizeof (struct nlist), nllen, fp); 697: fwrite ((char *) devl, sizeof (struct devl), ndev, fp); 698: fwrite ((char *) wchanhd, sizeof (struct wchan), nchans, fp); 699: fclose (fp); 700: } 701: 702: char * 703: readpsdb () 704: { 705: int nllen; 706: register i; 707: register FILE *fp; 708: static char unamebuf [BUFSIZ]; 709: char *p = unamebuf; 710: register struct wchan *ccc; 711: 712: if ((fp = fopen (psdb, "r")) == NULL) 713: perrexit (psdb); 714: 715: while ((*p= getc (fp)) != '\0') 716: p++; 717: fread (&nllen, sizeof nllen, 1, fp); 718: fread (&ndev, sizeof ndev, 1, fp); 719: fread (&nchans, sizeof nchans, 1, fp); 720: fread (nl, sizeof (struct nlist), nllen, fp); 721: fread (devl, sizeof (struct devl), ndev, fp); 722: if (!nflg) 723: if ((wchanhd = calloc (nchans, sizeof (struct wchan))) == (struct wchan *) NULL) 724: err ("Too many symbols"); 725: else for (i = 0, ccc = wchanhd; i < nchans; i++) { 726: fread ((char *) ccc, sizeof (struct wchan), 1, fp); 727: ccc++; 728: } 729: return (unamebuf); 730: } 731: 732: openfiles (argc, argv) 733: char **argv; 734: { 735: kmemf = "/dev/kmem"; 736: 737: if (kflg) 738: kmemf = argc > 1 ? argv[1] : "/usr/sys/core"; 739: kmem = open (kmemf, 0); 740: if (kmem < 0) 741: perrexit (kmemf); 742: if (!kflg) { 743: memf = "/dev/mem"; 744: ismem++; 745: } 746: else memf = kmemf; 747: mem = open (memf, 0); 748: if (mem < 0) 749: perrexit (memf); 750: swapf = argc > 2 ? argv[2] : "/dev/swap"; 751: swap = open (swapf, 0); 752: if (swap < 0) 753: perrexit (swapf); 754: } 755: 756: getkvars (argc, argv) 757: char **argv; 758: { 759: nlistf = argc > 3 ? argv[3] : "/unix"; 760: if (Uflg) { 761: nlist (nlistf, nl); 762: getdev (); 763: writepsdb (nlistf); 764: exit (0); 765: } 766: else if (exists (psdb)) { 767: uname = readpsdb (); 768: if (!equal (uname, nlistf)) { 769: /* 770: * Let addchan() do the work. 771: */ 772: nchans = 0; 773: free ((char *) wchanhd); 774: nlist (nlistf, nl); 775: } 776: } 777: else nlist (nlistf, nl), getdev (); 778: 779: /* 780: * Find base of swap 781: */ 782: lseek (kmem, (off_t) nl[X_SWPLO].n_value, 0); 783: if (read (kmem, (char *) &swplo, sizeof (swplo)) != sizeof (swplo)) 784: cantread ("swplo", kmemf); 785: 786: /* 787: * Find number of procs 788: */ 789: if (nl[X_NPROC].n_value) { 790: lseek (kmem, (off_t) nl[X_NPROC].n_value, 0); 791: if (read(kmem, (char *)&nproc, sizeof(nproc)) != sizeof(nproc)){ 792: perror(kmemf); 793: exit(1); 794: } 795: } else { 796: fprintf(stderr, "nproc not in namelist\n"); 797: exit(1); 798: } 799: 800: outargs = (struct psout *)calloc(nproc, sizeof(struct psout)); 801: if (outargs == (struct psout *)NULL) { 802: fprintf(stderr, "ps: not enough memory for saving info\n"); 803: exit(1); 804: } 805: /* 806: * Find value of hz 807: */ 808: lseek (kmem, (off_t) nl[X_HZ].n_value, 0); 809: read (kmem, (char *) &hz, sizeof hz); 810: 811: /* 812: * Locate proc table 813: */ 814: lseek (kmem, (off_t) nl[X_PROC].n_value, 0); 815: tell = (off_t) nl[X_PROC].n_value; 816: } 817: 818: 819: char *uhdr = 820: "USER PID NICE SZ TTY TIME"; 821: upr (a) 822: register struct psout *a; 823: { 824: printf ("%-8.8s", a->o_uname); 825: printf ("%6u", a->o_pid); 826: printf ("%4d ", a->o_nice); 827: printf ("%4d", a->o_size); 828: ptty (a->o_tty); 829: ptime (a); 830: } 831: 832: char *shdr = 833: " PID TTY TIME"; 834: spr (a) 835: register struct psout *a; 836: { 837: printf ("%6u", a->o_pid); 838: ptty (a->o_tty); 839: ptime (a); 840: } 841: 842: char *lhdr = 843: " F S UID PID PPID CPU PRI NICE ADDR SZ WCHAN TTY TIME"; 844: lpr (a) 845: register struct psout *a; 846: { 847: printf ("%3o %c", 0377 & a->o_flag, "0SWRIZT"[a->o_stat]); 848: printf ("%6u", a->o_uid); 849: printf ("%6u", a->o_pid); 850: printf ("%6u%4d%4d%4d%7o", a->o_ppid, a->o_cpu&0377, a->o_pri, a->o_nice, a->o_addr0); 851: printf ("%4d", a->o_size); 852: if (nflg) 853: if (a->o_wchan) 854: printf ("%7o", a->o_wchan); 855: else printf (" "); 856: else printf (" %-6.6s", getchan (a->o_wchan)); 857: ptty (a->o_tty); 858: ptime (a); 859: } 860: 861: ptty (tp) 862: char *tp; 863: { 864: printf (" %-8.8s", tp); 865: } 866: 867: ptime (a) 868: register struct psout *a; 869: { 870: time_t tm; 871: 872: tm = (a->o_utime + a->o_stime + 30) / hz; 873: printf ("%3ld:", tm / 60); 874: tm %= 60; 875: printf (tm < 10 ? "0%ld" : "%ld", tm); 876: } 877: 878: cantread (what, fromwhat) 879: char *what, *fromwhat; 880: { 881: fprintf (stderr, "ps: error reading %s from %s\n", what, fromwhat); 882: } 883: 884: getcmd (a, addr) 885: off_t addr; 886: register struct psout *a; 887: { 888: /* amount of top of stack to examine for args */ 889: #define ARGLIST (1024/sizeof(int)) 890: register *ip; 891: register char *cp, *cp1; 892: char c; 893: char **ap; 894: int cc, nbad, abuf [ARGLIST]; 895: 896: a->o_args[0] = 0; /* in case of early return */ 897: #ifdef VIRUS_VFORK 898: addr += ctob ((off_t) mproc->p_ssize) - ARGLIST*sizeof(int); 899: #else 900: addr += ctob ((off_t) mproc->p_size) - ARGLIST*sizeof(int); 901: #endif 902: 903: /* look for sh special */ 904: lseek (file, addr + ARGLIST*sizeof(int) - sizeof (char **), 0); 905: if (read (file, (char *) &ap, sizeof (char *)) != sizeof (char *)) 906: return (1); 907: if (ap) { 908: char b[82]; 909: char *bp = b; 910: while ((cp = getptr (ap++)) && cp && (bp < b+sizeof (a->o_args)) ) { 911: nbad = 0; 912: while ((c = getbyte (cp++)) && (bp < b+sizeof (a->o_args))) { 913: if (c<' ' || c > '~') { 914: if (nbad++ > 3) 915: break; 916: continue; 917: } 918: *bp++ = c; 919: } 920: *bp++ = ' '; 921: } 922: *bp++ = 0; 923: strcpy (a->o_args, b); 924: return (1); 925: } 926: 927: if (pread (file, (char *) abuf, sizeof (abuf), addr) != sizeof (abuf)) 928: return (1); 929: abuf[ARGLIST-1] = 0; 930: for (ip = &abuf[ARGLIST-2]; ip > abuf;) { 931: if (*--ip == -1 || *ip == 0) { 932: cp = (char *) (ip + 1); 933: if (*cp == '\0') 934: cp++; 935: nbad = 0; 936: for (cp1 = cp; cp1 < (char *) &abuf[ARGLIST]; cp1++) { 937: cc = *cp1 & 0177; 938: if (cc == 0) 939: *cp1 = ' '; 940: else if (cc < ' ' || cc > 0176) { 941: if (++nbad >= 5) { 942: *cp1++ = ' '; 943: break; 944: } 945: *cp1 = '?'; 946: } else if (cc == '=') { 947: *cp1 = '\0'; 948: while (cp1 > cp && *--cp1 != ' ') 949: *cp1 = '\0'; 950: break; 951: } 952: } 953: while (*--cp1 == ' ') 954: *cp1 = 0; 955: strcpy (a->o_args, cp); 956: garbage: 957: cp = a->o_args; 958: if (cp[0] == '-' && cp[1] <= ' ' || cp[0] == '?' || cp[0] <= ' ') { 959: strcat (cp, " ("); 960: strcat (cp, u.u_comm); 961: strcat (cp, ")"); 962: } 963: cp[63] = 0; /* max room in psout is 64 chars */ 964: if (xflg || gflg || tptr || cp[0] != '-') 965: return (1); 966: return (0); 967: } 968: } 969: goto garbage; 970: } 971: 972: printhdr () 973: { 974: register char *hdr; 975: #ifdef TERMCAP 976: register char *cmdstr = " COMMAND"; 977: #endif 978: 979: if (rflg) 980: return; 981: if (lflg && uflg) 982: err ("ps: specify only one of l and u"); 983: hdr = lflg ? lhdr : (uflg ? uhdr : shdr); 984: cmdstart = strlen (hdr); 985: #ifdef TERMCAP 986: if (cmdstart + strlen (cmdstr) >= twidth) 987: cmdstr = " CMD"; 988: printf ("%s%s\n", hdr, cmdstr); 989: #else 990: printf ("%s COMMAND\n", hdr); 991: #endif 992: 993: fflush (stdout); 994: }