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