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.9 (Berkeley) 5/8/86"; 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: 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(" <defunct>"); 396: else if (sp->ap->a_flag & SWEXIT) 397: printf(" <exiting>"); 398: else if (sp->ap->a_pid == 0) 399: printf(" swapper"); 400: else if (sp->ap->a_pid == 2) 401: printf(" 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 &= ~0x80000000; 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: 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: 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 %*s STAT 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("%7x%4d%6u%6u%3d%4d%3d%5x%4d%5d", 1207: ap->a_flag, ap->a_uid, 1208: ap->a_pid, lp->l_ppid, lp->l_cpu&0377, ap->a_pri-PZERO, 1209: ap->a_nice-NZERO, lp->l_addr, pgtok(ap->a_size), pgtok(ap->a_rss)); 1210: if (lp->l_wchan == 0) 1211: printf(" %*s", wcwidth, ""); 1212: else if (nflg) 1213: printf(" %*x", wcwidth, (int)lp->l_wchan&0xffffff); 1214: else 1215: printf(" %*.*s", wcwidth, abs(wcwidth), getchan(lp->l_wchan)); 1216: printf(" %4.4s ", state(ap)); 1217: ptty(ap->a_tty); 1218: ptime(ap); 1219: } 1220: 1221: ptty(tp) 1222: char *tp; 1223: { 1224: 1225: printf("%-2.2s", tp); 1226: } 1227: 1228: ptime(ap) 1229: struct asav *ap; 1230: { 1231: 1232: printf("%3ld:%02ld", ap->a_cpu / 60, ap->a_cpu % 60); 1233: } 1234: 1235: char *uhdr = 1236: "%s PID %%CPU %%MEM SZ RSS TT STAT TIME"; 1237: upr(sp) 1238: struct savcom *sp; 1239: { 1240: register struct asav *ap = sp->ap; 1241: int vmsize, rmsize; 1242: 1243: vmsize = pgtok((ap->a_size + ap->a_tsiz)); 1244: rmsize = pgtok(ap->a_rss); 1245: if (ap->a_xccount) 1246: rmsize += pgtok(ap->a_txtrss/ap->a_xccount); 1247: if (nflg) 1248: printf("%4d ", ap->a_uid); 1249: else 1250: printf("%-8.8s ", getname(ap->a_uid)); 1251: printf("%5d%5.1f%5.1f%5d%5d", 1252: ap->a_pid, sp->s_un.u_pctcpu, pmem(ap), vmsize, rmsize); 1253: putchar(' '); 1254: ptty(ap->a_tty); 1255: printf(" %4.4s", state(ap)); 1256: ptime(ap); 1257: } 1258: 1259: char *vhdr = 1260: " SIZE PID TT STAT TIME SL RE PAGEIN SIZE RSS LIM TSIZ TRS %CPU %MEM"+5; 1261: vpr(sp) 1262: struct savcom *sp; 1263: { 1264: register struct vsav *vp = sp->s_un.vp; 1265: register struct asav *ap = sp->ap; 1266: 1267: printf("%5u ", ap->a_pid); 1268: ptty(ap->a_tty); 1269: printf(" %4.4s", state(ap)); 1270: ptime(ap); 1271: printf("%3d%3d%7d%5d%5d", 1272: ap->a_slptime > 99 ? 99 : ap-> a_slptime, 1273: ap->a_time > 99 ? 99 : ap->a_time, vp->v_majflt, 1274: pgtok(ap->a_size), pgtok(ap->a_rss)); 1275: if (ap->a_maxrss == (RLIM_INFINITY/NBPG)) 1276: printf(" xx"); 1277: else 1278: printf("%6d", pgtok(ap->a_maxrss)); 1279: printf("%5d%4d%5.1f%5.1f", 1280: pgtok(ap->a_tsiz), pgtok(ap->a_txtrss), vp->v_pctcpu, pmem(ap)); 1281: } 1282: 1283: char *shdr = 1284: "SSIZ PID TT STAT TIME"; 1285: spr(sp) 1286: struct savcom *sp; 1287: { 1288: register struct asav *ap = sp->ap; 1289: 1290: if (sflg) 1291: printf("%4d ", sp->s_un.s_ssiz); 1292: printf("%5u", ap->a_pid); 1293: putchar(' '); 1294: ptty(ap->a_tty); 1295: printf(" %4.4s", state(ap)); 1296: ptime(ap); 1297: } 1298: 1299: char * 1300: state(ap) 1301: register struct asav *ap; 1302: { 1303: char stat, load, nice, anom; 1304: static char res[5]; 1305: 1306: switch (ap->a_stat) { 1307: 1308: case SSTOP: 1309: stat = 'T'; 1310: break; 1311: 1312: case SSLEEP: 1313: if (ap->a_pri >= PZERO) 1314: if (ap->a_slptime >= MAXSLP) 1315: stat = 'I'; 1316: else 1317: stat = 'S'; 1318: else if (ap->a_flag & SPAGE) 1319: stat = 'P'; 1320: else 1321: stat = 'D'; 1322: break; 1323: 1324: case SWAIT: 1325: case SRUN: 1326: case SIDL: 1327: stat = 'R'; 1328: break; 1329: 1330: case SZOMB: 1331: stat = 'Z'; 1332: break; 1333: 1334: default: 1335: stat = '?'; 1336: } 1337: load = ap->a_flag & SLOAD ? (ap->a_rss>ap->a_maxrss ? '>' : ' ') : 'W'; 1338: if (ap->a_nice < NZERO) 1339: nice = '<'; 1340: else if (ap->a_nice > NZERO) 1341: nice = 'N'; 1342: else 1343: nice = ' '; 1344: anom = (ap->a_flag&SUANOM) ? 'A' : ((ap->a_flag&SSEQL) ? 'S' : ' '); 1345: res[0] = stat; res[1] = load; res[2] = nice; res[3] = anom; 1346: return (res); 1347: } 1348: 1349: /* 1350: * Given a base/size pair in virtual swap area, 1351: * return a physical base/size pair which is the 1352: * (largest) initial, physically contiguous block. 1353: */ 1354: vstodb(vsbase, vssize, dmp, dbp, rev) 1355: register int vsbase; 1356: int vssize; 1357: struct dmap *dmp; 1358: register struct dblock *dbp; 1359: { 1360: register int blk = dmmin; 1361: register swblk_t *ip = dmp->dm_map; 1362: 1363: vsbase = ctod(vsbase); 1364: vssize = ctod(vssize); 1365: if (vsbase < 0 || vsbase + vssize > dmp->dm_size) 1366: panic("vstodb"); 1367: while (vsbase >= blk) { 1368: vsbase -= blk; 1369: if (blk < dmmax) 1370: blk *= 2; 1371: ip++; 1372: } 1373: if (*ip <= 0 || *ip + blk > nswap) 1374: panic("vstodb *ip"); 1375: dbp->db_size = min(vssize, blk - vsbase); 1376: dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase); 1377: } 1378: 1379: /*ARGSUSED*/ 1380: panic(cp) 1381: char *cp; 1382: { 1383: 1384: #ifdef DEBUG 1385: printf("%s\n", cp); 1386: #endif 1387: } 1388: 1389: min(a, b) 1390: { 1391: 1392: return (a < b ? a : b); 1393: } 1394: 1395: pscomp(s1, s2) 1396: struct savcom *s1, *s2; 1397: { 1398: register int i; 1399: 1400: if (uflg) 1401: return (s2->s_un.u_pctcpu > s1->s_un.u_pctcpu ? 1 : -1); 1402: if (vflg) 1403: return (vsize(s2) - vsize(s1)); 1404: i = s1->ap->a_ttyd - s2->ap->a_ttyd; 1405: if (i == 0) 1406: i = s1->ap->a_pid - s2->ap->a_pid; 1407: return (i); 1408: } 1409: 1410: vsize(sp) 1411: struct savcom *sp; 1412: { 1413: register struct asav *ap = sp->ap; 1414: register struct vsav *vp = sp->s_un.vp; 1415: 1416: if (ap->a_flag & SLOAD) 1417: return (ap->a_rss + 1418: ap->a_txtrss / (ap->a_xccount ? ap->a_xccount : 1)); 1419: return (vp->v_swrss + (ap->a_xccount ? 0 : vp->v_txtswrss)); 1420: } 1421: 1422: #include <utmp.h> 1423: 1424: struct utmp utmp; 1425: #define NMAX (sizeof (utmp.ut_name)) 1426: #define SCPYN(a, b) strncpy(a, b, NMAX) 1427: 1428: #define NUID 64 1429: 1430: struct ncache { 1431: int uid; 1432: char name[NMAX+1]; 1433: } nc[NUID]; 1434: 1435: /* 1436: * This function assumes that the password file is hashed 1437: * (or some such) to allow fast access based on a uid key. 1438: */ 1439: char * 1440: getname(uid) 1441: { 1442: register struct passwd *pw; 1443: struct passwd *getpwent(); 1444: register int cp; 1445: extern int _pw_stayopen; 1446: 1447: _pw_stayopen = 1; 1448: 1449: #if (((NUID) & ((NUID) - 1)) != 0) 1450: cp = uid % (NUID); 1451: #else 1452: cp = uid & ((NUID) - 1); 1453: #endif 1454: if (uid >= 0 && nc[cp].uid == uid && nc[cp].name[0]) 1455: return (nc[cp].name); 1456: pw = getpwuid(uid); 1457: if (!pw) 1458: return (0); 1459: nc[cp].uid = uid; 1460: SCPYN(nc[cp].name, pw->pw_name); 1461: return (nc[cp].name); 1462: } 1463: 1464: char * 1465: savestr(cp) 1466: char *cp; 1467: { 1468: register unsigned len; 1469: register char *dp; 1470: 1471: len = strlen(cp); 1472: dp = (char *)calloc(len+1, sizeof (char)); 1473: (void) strcpy(dp, cp); 1474: return (dp); 1475: } 1476: 1477: /* 1478: * This routine was stolen from adb to simulate memory management 1479: * on the VAX. 1480: */ 1481: off_t 1482: vtophys(loc) 1483: long loc; 1484: { 1485: register p; 1486: off_t newloc; 1487: 1488: newloc = loc & ~0xc0000000; 1489: p = btop(newloc); 1490: if ((loc & 0xc0000000) == 0) { 1491: fprintf(stderr, "Vtophys: translating non-kernel address\n"); 1492: return((off_t) -1); 1493: } 1494: if (p >= Syssize) { 1495: fprintf(stderr, "Vtophys: page out of bound (%d>=%d)\n", 1496: p, Syssize); 1497: return((off_t) -1); 1498: } 1499: if (Sysmap[p].pg_v == 0 1500: && (Sysmap[p].pg_fod || Sysmap[p].pg_pfnum == 0)) { 1501: fprintf(stderr, "Vtophys: page not valid\n"); 1502: return((off_t) -1); 1503: } 1504: loc = (long) (ptob(Sysmap[p].pg_pfnum) + (loc & PGOFSET)); 1505: return(loc); 1506: } 1507: 1508: /* 1509: * since we can't init unions, the cleanest way to use a.out.h instead 1510: * of nlist.h (required since nlist() uses some defines) is to do a 1511: * runtime copy into the nl array -- sigh 1512: */ 1513: init_nlist() 1514: { 1515: register struct nlist *np; 1516: register char **namep; 1517: 1518: nllen = sizeof nl_names / sizeof (char *); 1519: np = nl = (struct nlist *) malloc(nllen * sizeof (struct nlist)); 1520: if (np == NULL) { 1521: fprintf(stderr, "ps: out of memory allocating namelist\n"); 1522: exit(1); 1523: } 1524: namep = &nl_names[0]; 1525: while (nllen > 0) { 1526: np->n_un.n_name = *namep; 1527: if (**namep == '\0') 1528: break; 1529: namep++; 1530: np++; 1531: } 1532: } 1533: 1534: /* 1535: * nlist - retreive attributes from name list (string table version) 1536: * modified to add wait channels - Charles R. LaBrec 8/85 1537: */ 1538: nlist(name, list) 1539: char *name; 1540: struct nlist *list; 1541: { 1542: register struct nlist *p, *q; 1543: register char *s1, *s2; 1544: register n, m; 1545: int maxlen, nreq; 1546: FILE *f; 1547: FILE *sf; 1548: off_t sa; /* symbol address */ 1549: off_t ss; /* start of strings */ 1550: int type; 1551: struct exec buf; 1552: struct nlist space[BUFSIZ/sizeof (struct nlist)]; 1553: char nambuf[BUFSIZ]; 1554: 1555: maxlen = 0; 1556: for (q = list, nreq = 0; q->n_un.n_name && q->n_un.n_name[0]; q++, nreq++) { 1557: q->n_type = 0; 1558: q->n_value = 0; 1559: q->n_desc = 0; 1560: q->n_other = 0; 1561: n = strlen(q->n_un.n_name); 1562: if (n > maxlen) 1563: maxlen = n; 1564: } 1565: f = fopen(name, "r"); 1566: if (f == NULL) 1567: return (-1); 1568: fread((char *)&buf, sizeof buf, 1, f); 1569: if (N_BADMAG(buf)) { 1570: fclose(f); 1571: return (-1); 1572: } 1573: sf = fopen(name, "r"); 1574: if (sf == NULL) { 1575: /* ??? */ 1576: fclose(f); 1577: return(-1); 1578: } 1579: sa = N_SYMOFF(buf); 1580: ss = sa + buf.a_syms; 1581: n = buf.a_syms; 1582: fseek(f, sa, 0); 1583: while (n) { 1584: m = sizeof (space); 1585: if (n < m) 1586: m = n; 1587: if (fread((char *)space, m, 1, f) != 1) 1588: break; 1589: n -= m; 1590: for (q = space; (m -= sizeof(struct nlist)) >= 0; q++) { 1591: if (q->n_un.n_strx == 0 || q->n_type & N_STAB) 1592: continue; 1593: /* 1594: * since we know what type of symbols we will get, 1595: * we can make a quick check here -- crl 1596: */ 1597: type = q->n_type & (N_TYPE | N_EXT); 1598: if ((q->n_type & N_TYPE) != N_ABS 1599: && type != (N_EXT | N_DATA) 1600: && type != (N_EXT | N_BSS)) 1601: continue; 1602: fseek(sf, ss+q->n_un.n_strx, 0); 1603: fread(nambuf, maxlen+1, 1, sf); 1604: /* if using wchans, add it to the list of channels */ 1605: if (!nflg) 1606: addchan(&nambuf[1], (caddr_t) q->n_value); 1607: for (p = list; p->n_un.n_name && p->n_un.n_name[0]; p++) { 1608: s1 = p->n_un.n_name; 1609: s2 = nambuf; 1610: if (strcmp(p->n_un.n_name, nambuf) == 0) { 1611: p->n_value = q->n_value; 1612: p->n_type = q->n_type; 1613: p->n_desc = q->n_desc; 1614: p->n_other = q->n_other; 1615: --nreq; 1616: break; 1617: } 1618: } 1619: } 1620: } 1621: alldone: 1622: fclose(f); 1623: fclose(sf); 1624: return (nreq); 1625: } 1626: 1627: /* 1628: * add the given channel to the channel list 1629: */ 1630: addchan(name, caddr) 1631: char *name; 1632: caddr_t caddr; 1633: { 1634: static int left = 0; 1635: register struct wchan *wp; 1636: register char **p; 1637: 1638: for (p = wchan_stop_list; *p; p++) { 1639: if (**p != *name) /* quick check first */ 1640: continue; 1641: if (strncmp(name, *p, WNAMESIZ) == 0) 1642: return; /* if found, don't add */ 1643: } 1644: if (left == 0) { 1645: if (wchanhd) { 1646: left = 100; 1647: wchanhd = (struct wchan *) realloc(wchanhd, 1648: (nchans + left) * sizeof (struct wchan)); 1649: } else { 1650: left = 600; 1651: wchanhd = (struct wchan *) malloc(left 1652: * sizeof (struct wchan)); 1653: } 1654: if (wchanhd == NULL) { 1655: fprintf(stderr, "ps: out of memory allocating wait channels\n"); 1656: nflg++; 1657: return; 1658: } 1659: } 1660: left--; 1661: wp = &wchanhd[nchans++]; 1662: strncpy(wp->wc_name, name, WNAMESIZ); 1663: wp->wc_name[WNAMESIZ] = '\0'; 1664: wp->wc_caddr = caddr; 1665: } 1666: 1667: /* 1668: * returns the symbolic wait channel corresponding to chan 1669: */ 1670: char * 1671: getchan(chan) 1672: register caddr_t chan; 1673: { 1674: register i, iend; 1675: register char *prevsym; 1676: register struct wchan *wp; 1677: 1678: prevsym = "???"; /* nothing, to begin with */ 1679: if (chan) { 1680: for (i = 0; i < NWCINDEX; i++) 1681: if ((unsigned) chan < (unsigned) wchan_index[i]) 1682: break; 1683: iend = i--; 1684: if (i < 0) /* can't be found */ 1685: return prevsym; 1686: iend *= nchans; 1687: iend /= NWCINDEX; 1688: i *= nchans; 1689: i /= NWCINDEX; 1690: wp = &wchanhd[i]; 1691: for ( ; i < iend; i++, wp++) { 1692: if ((unsigned) wp->wc_caddr > (unsigned) chan) 1693: break; 1694: prevsym = wp->wc_name; 1695: } 1696: } 1697: return prevsym; 1698: } 1699: 1700: /* 1701: * used in sorting the wait channel array 1702: */ 1703: int 1704: wchancomp (w1, w2) 1705: struct wchan *w1, *w2; 1706: { 1707: register unsigned c1, c2; 1708: 1709: c1 = (unsigned) w1->wc_caddr; 1710: c2 = (unsigned) w2->wc_caddr; 1711: if (c1 > c2) 1712: return 1; 1713: else if (c1 == c2) 1714: return 0; 1715: else 1716: return -1; 1717: }