1 #ifndef lint 2 static char *sccsid = "@(#)ps.c 4.19 (Berkeley) 11/14/82"; 3 #endif 4 5 /* 6 * ps 7 */ 8 9 #include <stdio.h> 10 #include <ctype.h> 11 #include <nlist.h> 12 #include <pwd.h> 13 #include <sys/param.h> 14 #include <sys/tty.h> 15 #include <dir.h> 16 #include <sys/user.h> 17 #include <sys/proc.h> 18 #include <sys/pte.h> 19 #include <sys/vm.h> 20 #include <sys/text.h> 21 #include <sys/stat.h> 22 #include <math.h> 23 #include <sys/vlimit.h> 24 25 struct nlist nl[] = { 26 { "_proc" }, 27 #define X_PROC 0 28 { "_Usrptmap" }, 29 #define X_USRPTMA 1 30 { "_usrpt" }, 31 #define X_USRPT 2 32 { "_text" }, 33 #define X_TEXT 3 34 { "_nswap" }, 35 #define X_NSWAP 4 36 { "_maxslp" }, 37 #define X_MAXSLP 5 38 { "_ccpu" }, 39 #define X_CCPU 6 40 { "_ecmx" }, 41 #define X_ECMX 7 42 { "_nproc" }, 43 #define X_NPROC 8 44 { "_ntext" }, 45 #define X_NTEXT 9 46 { 0 }, 47 }; 48 49 struct savcom { 50 union { 51 struct lsav *lp; 52 float u_pctcpu; 53 struct vsav *vp; 54 int s_ssiz; 55 struct sssav *ssp; 56 } sun; 57 struct asav *ap; 58 } *savcom; 59 60 struct asav { 61 char *a_cmdp; 62 int a_flag; 63 short a_stat, a_uid, a_pid, a_nice, a_pri, a_slptime, a_time; 64 size_t a_size, a_rss, a_tsiz, a_txtrss; 65 short a_xccount; 66 char a_tty[MAXNAMLEN+1]; 67 dev_t a_ttyd; 68 time_t a_cpu; 69 size_t a_maxrss; 70 }; 71 72 char *lhdr; 73 struct lsav { 74 short l_ppid; 75 char l_cpu; 76 int l_addr; 77 caddr_t l_wchan; 78 }; 79 80 char *sshdr; 81 struct sssav { 82 short ss_ppid; 83 short ss_brother; 84 short ss_sons; 85 }; 86 87 char *uhdr; 88 char *shdr; 89 90 char *vhdr; 91 struct vsav { 92 u_int v_majflt; 93 size_t v_swrss, v_txtswrss; 94 float v_pctcpu; 95 }; 96 97 struct proc proc[8]; /* 8 = a few, for less syscalls */ 98 struct proc *mproc; 99 struct text *text; 100 101 union { 102 struct user user; 103 char upages[UPAGES][NBPG]; 104 } user; 105 #define u user.user 106 107 #define clear(x) ((int)x & 0x7fffffff) 108 109 int chkpid; 110 int aflg, cflg, eflg, gflg, kflg, lflg, sflg, ssflg, 111 nonssflg, uflg, vflg, xflg; 112 char *tptr; 113 char *gettty(), *getcmd(), *getname(), *savestr(), *alloc(), *state(); 114 char *rindex(), *calloc(), *sbrk(), *strcpy(), *strcat(), *strncat(); 115 long lseek(); 116 double pcpu(), pmem(); 117 int pscomp(); 118 int nswap, maxslp; 119 struct text *atext; 120 double ccpu; 121 int ecmx; 122 struct pte *Usrptma, *usrpt; 123 int nproc, ntext, hz; 124 125 struct ttys { 126 char name[MAXNAMLEN+1]; 127 dev_t ttyd; 128 struct ttys *next; 129 struct ttys *cand; 130 } *allttys, *cand[16]; 131 132 int npr; 133 134 int cmdstart; 135 int twidth; 136 char *kmemf, *memf, *swapf, *nlistf; 137 int kmem, mem, swap = -1; 138 int rawcpu, sumcpu; 139 140 int pcbpf; 141 int argaddr; 142 extern char _sobuf[]; 143 144 main(argc, argv) 145 char **argv; 146 { 147 register int i, j; 148 register char *ap; 149 int uid; 150 off_t procp; 151 152 twidth = 80; 153 if (ap = rindex(argv[0], '/')) 154 ap++; 155 else 156 ap = argv[0]; 157 if (*ap == 's') /* If name starts with 's' */ 158 ssflg++; 159 160 argc--, argv++; 161 if (argc > 0) { 162 ap = argv[0]; 163 while (*ap) switch (*ap++) { 164 165 case 'C': 166 rawcpu++; nonssflg++; 167 break; 168 case 'S': 169 sumcpu++; 170 break; 171 case 'a': 172 aflg++; 173 break; 174 case 'c': 175 cflg = !cflg; nonssflg++; 176 break; 177 case 'e': 178 eflg++; nonssflg++; 179 break; 180 case 'g': 181 gflg++; nonssflg++; 182 break; 183 case 'k': 184 kflg++; nonssflg++; 185 break; 186 case 'l': 187 lflg++; nonssflg++; 188 break; 189 case 's': 190 sflg++; nonssflg++; 191 break; 192 case 't': 193 if (*ap) 194 tptr = ap; 195 aflg++; nonssflg++; 196 gflg++; 197 if (*tptr == '?') 198 xflg++; 199 while (*ap) 200 ap++; 201 break; 202 case 'u': 203 uflg++; nonssflg++; 204 break; 205 case 'v': 206 cflg = 1; 207 vflg++; nonssflg++; 208 break; 209 case 'w': 210 if (twidth == 80) 211 twidth = 132; 212 else 213 twidth = BUFSIZ; 214 break; 215 case 'x': 216 xflg++; 217 break; 218 case 'y': /* Rand 2/81 */ 219 ssflg++; 220 break; 221 default: 222 if (!isdigit(ap[-1])) 223 break; 224 chkpid = atoi(--ap); 225 *ap = 0; 226 aflg++; nonssflg++; 227 xflg++; 228 break; 229 } 230 } 231 if (ssflg) { 232 if (nonssflg) { 233 fprintf (stderr, "Usage: ss [axwS]\n"); 234 exit(1); 235 } 236 uflg++; 237 gflg++; 238 } 239 openfiles(argc, argv); 240 getkvars(argc, argv); 241 if (chdir("/dev") < 0) { 242 perror("/dev"); 243 exit(1); 244 } 245 getdev(); 246 uid = getuid(); 247 printhdr(); 248 procp = getw(nl[X_PROC].n_value); 249 nproc = getw(nl[X_NPROC].n_value); 250 savcom = (struct savcom *)calloc(nproc, sizeof (*savcom)); 251 for (i=0; i<nproc; i += 8) { 252 klseek(kmem, (long)procp, 0); 253 j = nproc - i; 254 if (j > 8) 255 j = 8; 256 j *= sizeof (struct proc); 257 if (read(kmem, (char *)proc, j) != j) { 258 cantread("proc table", kmemf); 259 exit(1); 260 } 261 procp += j; 262 for (j = j / sizeof (struct proc) - 1; j >= 0; j--) { 263 mproc = &proc[j]; 264 if (mproc->p_stat == 0 || 265 mproc->p_pgrp == 0 && xflg == 0) 266 continue; 267 if (tptr == 0 && gflg == 0 && xflg == 0 && 268 mproc->p_ppid == 1) 269 continue; 270 if (uid != mproc->p_uid && aflg==0 || 271 chkpid != 0 && chkpid != mproc->p_pid) 272 continue; 273 if (vflg && gflg == 0 && xflg == 0) { 274 if (mproc->p_stat == SZOMB || 275 mproc->p_flag&SWEXIT) 276 continue; 277 if (mproc->p_slptime > MAXSLP && 278 (mproc->p_stat == SSLEEP || 279 mproc->p_stat == SSTOP)) 280 continue; 281 } 282 save(); 283 } 284 } 285 qsort(savcom, npr, sizeof(savcom[0]), pscomp); 286 if (ssflg) { 287 walk(npr); 288 exit (npr == 0); 289 } 290 for (i=0; i<npr; i++) { 291 register struct savcom *sp = &savcom[i]; 292 if (lflg) 293 lpr(sp); 294 else if (vflg) 295 vpr(sp); 296 else if (uflg) 297 upr(sp); 298 else 299 spr(sp); 300 if (sp->ap->a_flag & SWEXIT) 301 printf(" <exiting>"); 302 else if (sp->ap->a_stat == SZOMB) 303 printf(" <defunct>"); 304 else if (sp->ap->a_pid == 0) 305 printf(" swapper"); 306 else if (sp->ap->a_pid == 2) 307 printf(" pagedaemon"); 308 else if (sp->ap->a_pid == 3 && sp->ap->a_flag & SSYS) 309 printf(" ip input"); 310 else 311 printf(" %.*s", twidth - cmdstart - 2, sp->ap->a_cmdp); 312 printf("\n"); 313 } 314 exit(npr == 0); 315 } 316 317 getw(loc) 318 unsigned long loc; 319 { 320 long word; 321 322 klseek(kmem, (long)loc, 0); 323 if (read(kmem, (char *)&word, sizeof (word)) != sizeof (word)) 324 printf("error reading kmem at %x\n", loc); 325 return (word); 326 } 327 328 klseek(fd, loc, off) 329 int fd; 330 long loc; 331 int off; 332 { 333 334 if (kflg) 335 loc &= 0x7fffffff; 336 (void) lseek(fd, (long)loc, off); 337 } 338 339 openfiles(argc, argv) 340 char **argv; 341 { 342 343 kmemf = "/dev/kmem"; 344 if (kflg) 345 kmemf = argc > 2 ? argv[2] : "/vmcore"; 346 kmem = open(kmemf, 0); 347 if (kmem < 0) { 348 perror(kmemf); 349 exit(1); 350 } 351 if (kflg) { 352 mem = kmem; 353 memf = kmemf; 354 } else { 355 memf = "/dev/mem"; 356 mem = open(memf, 0); 357 if (mem < 0) { 358 perror(memf); 359 exit(1); 360 } 361 } 362 if (kflg == 0 || argc > 3) { 363 swapf = argc>3 ? argv[3]: "/dev/drum"; 364 swap = open(swapf, 0); 365 if (swap < 0) { 366 perror(swapf); 367 exit(1); 368 } 369 } 370 } 371 372 getkvars(argc, argv) 373 char **argv; 374 { 375 register struct nlist *nlp; 376 377 nlistf = argc > 1 ? argv[1] : "/vmunix"; 378 nlist(nlistf, nl); 379 if (nl[0].n_type == 0) { 380 fprintf(stderr, "%s: No namelist\n", nlistf); 381 exit(1); 382 } 383 if (kflg) 384 for (nlp = nl; nlp < &nl[sizeof (nl)/sizeof (nl[0])]; nlp++) 385 nlp->n_value = clear(nlp->n_value); 386 usrpt = (struct pte *)nl[X_USRPT].n_value; /* don't clear!! */ 387 Usrptma = (struct pte *)nl[X_USRPTMA].n_value; 388 klseek(kmem, (long)nl[X_NSWAP].n_value, 0); 389 if (read(kmem, (char *)&nswap, sizeof (nswap)) != sizeof (nswap)) { 390 cantread("nswap", kmemf); 391 exit(1); 392 } 393 klseek(kmem, (long)nl[X_MAXSLP].n_value, 0); 394 if (read(kmem, (char *)&maxslp, sizeof (maxslp)) != sizeof (maxslp)) { 395 cantread("maxslp", kmemf); 396 exit(1); 397 } 398 klseek(kmem, (long)nl[X_CCPU].n_value, 0); 399 if (read(kmem, (char *)&ccpu, sizeof (ccpu)) != sizeof (ccpu)) { 400 cantread("ccpu", kmemf); 401 exit(1); 402 } 403 klseek(kmem, (long)nl[X_ECMX].n_value, 0); 404 if (read(kmem, (char *)&ecmx, sizeof (ecmx)) != sizeof (ecmx)) { 405 cantread("ecmx", kmemf); 406 exit(1); 407 } 408 if (uflg || vflg) { 409 ntext = getw(nl[X_NTEXT].n_value); 410 text = (struct text *)alloc(ntext * sizeof (struct text)); 411 if (text == 0) { 412 fprintf(stderr, "no room for text table\n"); 413 exit(1); 414 } 415 atext = (struct text *)getw(nl[X_TEXT].n_value); 416 klseek(kmem, (long)atext, 0); 417 if (read(kmem, (char *)text, ntext * sizeof (struct text)) 418 != ntext * sizeof (struct text)) { 419 cantread("text table", kmemf); 420 exit(1); 421 } 422 } 423 } 424 425 printhdr() 426 { 427 char *hdr; 428 429 if (sflg+lflg+vflg+uflg > 1) { 430 fprintf(stderr, "ps: specify only one of s,l,v and u\n"); 431 exit(1); 432 } 433 hdr = ssflg ? sshdr : 434 (lflg ? lhdr : 435 (vflg ? vhdr : 436 (uflg ? uhdr : shdr))); 437 if (lflg+vflg+uflg+sflg == 0) 438 hdr += strlen("SSIZ "); 439 cmdstart = strlen(hdr); 440 printf("%s COMMAND\n", hdr); 441 (void) fflush(stdout); 442 } 443 444 cantread(what, fromwhat) 445 char *what, *fromwhat; 446 { 447 448 fprintf(stderr, "ps: error reading %s from %s\n", what, fromwhat); 449 } 450 451 struct direct *dbuf; 452 int dialbase; 453 454 getdev() 455 { 456 register DIR *df; 457 458 dialbase = -1; 459 if ((df = opendir(".")) == NULL) { 460 fprintf(stderr, "Can't open . in /dev\n"); 461 exit(1); 462 } 463 while ((dbuf = readdir(df)) != NULL) 464 maybetty(); 465 closedir(df); 466 } 467 468 /* 469 * Attempt to avoid stats by guessing minor device 470 * numbers from tty names. Console is known, 471 * know that r(hp|up|mt) are unlikely as are different mem's, 472 * floppy, null, tty, etc. 473 */ 474 maybetty() 475 { 476 register char *cp = dbuf->d_name; 477 register struct ttys *dp; 478 int x; 479 struct stat stb; 480 481 switch (cp[0]) { 482 483 case 'c': 484 if (!strcmp(cp, "console")) { 485 x = 0; 486 goto donecand; 487 } 488 /* cu[la]? are possible!?! don't rule them out */ 489 break; 490 491 case 'd': 492 if (!strcmp(cp, "drum")) 493 return; 494 break; 495 496 case 'f': 497 if (!strcmp(cp, "floppy")) 498 return; 499 break; 500 501 case 'k': 502 cp++; 503 if (*cp == 'U') 504 cp++; 505 goto trymem; 506 507 case 'r': 508 cp++; 509 if (*cp == 'r' || *cp == 'u' || *cp == 'h') 510 cp++; 511 #define is(a,b) cp[0] == 'a' && cp[1] == 'b' 512 if (is(r,p) || is(u,p) || is(r,k) || is(r,m) || is(m,t)) { 513 cp += 2; 514 if (isdigit(*cp) && cp[2] == 0) 515 return; 516 } 517 break; 518 519 case 'm': 520 trymem: 521 if (cp[0] == 'm' && cp[1] == 'e' && cp[2] == 'm' && cp[3] == 0) 522 return; 523 if (cp[0] == 'm' && cp[1] == 't') 524 return; 525 break; 526 527 case 'n': 528 if (!strcmp(cp, "null")) 529 return; 530 break; 531 532 case 'v': 533 if ((cp[1] == 'a' || cp[1] == 'p') && isdigit(cp[2]) && 534 cp[3] == 0) 535 return; 536 break; 537 } 538 cp = dbuf->d_name + dbuf->d_namlen - 1; 539 x = 0; 540 if (cp[-1] == 'd') { 541 if (dialbase == -1) { 542 if (stat("ttyd0", &stb) == 0) 543 dialbase = stb.st_rdev & 017; 544 else 545 dialbase = -2; 546 } 547 if (dialbase == -2) 548 x = 0; 549 else 550 x = 11; 551 } 552 if (cp > dbuf->d_name && isdigit(cp[-1]) && isdigit(*cp)) 553 x += 10 * (cp[-1] - ' ') + cp[0] - '0'; 554 else if (*cp >= 'a' && *cp <= 'f') 555 x += 10 + *cp - 'a'; 556 else if (isdigit(*cp)) 557 x += *cp - '0'; 558 else 559 x = -1; 560 donecand: 561 dp = (struct ttys *)alloc(sizeof (struct ttys)); 562 (void) strcpy(dp->name, dbuf->d_name); 563 dp->next = allttys; 564 dp->ttyd = -1; 565 allttys = dp; 566 if (x == -1) 567 return; 568 x &= 017; 569 dp->cand = cand[x]; 570 cand[x] = dp; 571 } 572 573 char * 574 gettty() 575 { 576 register char *p; 577 register struct ttys *dp; 578 struct stat stb; 579 int x; 580 581 if (u.u_ttyp == 0) 582 return("?"); 583 x = u.u_ttyd & 017; 584 for (dp = cand[x]; dp; dp = dp->cand) { 585 if (dp->ttyd == -1) { 586 if (stat(dp->name, &stb) == 0 && 587 (stb.st_mode&S_IFMT)==S_IFCHR) 588 dp->ttyd = stb.st_rdev; 589 else 590 dp->ttyd = -2; 591 } 592 if (dp->ttyd == u.u_ttyd) 593 goto found; 594 } 595 /* ick */ 596 for (dp = allttys; dp; dp = dp->next) { 597 if (dp->ttyd == -1) { 598 if (stat(dp->name, &stb) == 0 && 599 (stb.st_mode&S_IFMT)==S_IFCHR) 600 dp->ttyd = stb.st_rdev; 601 else 602 dp->ttyd = -2; 603 } 604 if (dp->ttyd == u.u_ttyd) 605 goto found; 606 } 607 return ("?"); 608 found: 609 p = dp->name; 610 if (p[0]=='t' && p[1]=='t' && p[2]=='y') 611 p += 3; 612 return (p); 613 } 614 615 save() 616 { 617 register struct savcom *sp; 618 register struct asav *ap; 619 register char *cp; 620 register struct text *xp; 621 char *ttyp, *cmdp; 622 623 if (mproc->p_stat != SZOMB && getu() == 0) 624 return; 625 ttyp = gettty(); 626 if (xflg == 0 && ttyp[0] == '?' || tptr && strncmp(tptr, ttyp, 2)) 627 return; 628 sp = &savcom[npr]; 629 cmdp = getcmd(); 630 if (cmdp == 0) 631 return; 632 sp->ap = ap = (struct asav *)alloc(sizeof (struct asav)); 633 sp->ap->a_cmdp = cmdp; 634 #define e(a,b) ap->a = mproc->b 635 e(a_flag, p_flag); e(a_stat, p_stat); e(a_nice, p_nice); 636 e(a_uid, p_uid); e(a_pid, p_pid); e(a_pri, p_pri); 637 e(a_slptime, p_slptime); e(a_time, p_time); 638 ap->a_tty[0] = ttyp[0]; 639 ap->a_tty[1] = ttyp[1] ? ttyp[1] : ' '; 640 if (ap->a_stat == SZOMB) { 641 register struct xproc *xp = (struct xproc *)mproc; 642 643 ap->a_cpu = 0; 644 } else { 645 ap->a_size = mproc->p_dsize + mproc->p_ssize; 646 e(a_rss, p_rssize); 647 ap->a_ttyd = u.u_ttyd; 648 ap->a_cpu = u.u_ru.ru_utime.tv_sec + u.u_ru.ru_stime.tv_sec; 649 if (sumcpu) 650 ap->a_cpu += u.u_cru.ru_utime.tv_sec + u.u_cru.ru_stime.tv_sec; 651 if (mproc->p_textp && text) { 652 xp = &text[mproc->p_textp - atext]; 653 ap->a_tsiz = xp->x_size; 654 ap->a_txtrss = xp->x_rssize; 655 ap->a_xccount = xp->x_ccount; 656 } 657 } 658 #undef e 659 ap->a_maxrss = mproc->p_maxrss; 660 if (lflg) { 661 register struct lsav *lp; 662 663 sp->sun.lp = lp = (struct lsav *)alloc(sizeof (struct lsav)); 664 #define e(a,b) lp->a = mproc->b 665 e(l_ppid, p_ppid); e(l_cpu, p_cpu); 666 if (ap->a_stat != SZOMB) 667 e(l_wchan, p_wchan); 668 #undef e 669 lp->l_addr = pcbpf; 670 } else if (vflg) { 671 register struct vsav *vp; 672 673 sp->sun.vp = vp = (struct vsav *)alloc(sizeof (struct vsav)); 674 #define e(a,b) vp->a = mproc->b 675 if (ap->a_stat != SZOMB) { 676 e(v_swrss, p_swrss); 677 vp->v_majflt = u.u_ru.ru_majflt; 678 if (mproc->p_textp) 679 vp->v_txtswrss = xp->x_swrss; 680 } 681 vp->v_pctcpu = pcpu(); 682 #undef e 683 } else if (uflg) { 684 if (!ssflg) 685 sp->sun.u_pctcpu = pcpu(); 686 else { 687 register struct sssav *ssp; 688 689 sp->sun.ssp =ssp= (struct sssav *)alloc(sizeof (struct sssav)); 690 ssp->ss_ppid = mproc->p_ppid; 691 } 692 } else if (sflg) { 693 if (ap->a_stat != SZOMB) { 694 for (cp = (char *)u.u_stack; 695 cp < &user.upages[UPAGES][0]; ) 696 if (*cp++) 697 break; 698 sp->sun.s_ssiz = (&user.upages[UPAGES][0] - cp); 699 } 700 } 701 702 npr++; 703 } 704 705 double 706 pmem(ap) 707 register struct asav *ap; 708 { 709 double fracmem; 710 int szptudot; 711 712 if ((ap->a_flag&SLOAD) == 0) 713 fracmem = 0.0; 714 else { 715 szptudot = UPAGES + clrnd(ctopt(ap->a_size+ap->a_tsiz)); 716 fracmem = ((float)ap->a_rss+szptudot)/CLSIZE/ecmx; 717 if (ap->a_xccount) 718 fracmem += ((float)ap->a_txtrss)/CLSIZE/ 719 ap->a_xccount/ecmx; 720 } 721 return (100.0 * fracmem); 722 } 723 724 double 725 pcpu() 726 { 727 time_t time; 728 729 time = mproc->p_time; 730 if (time == 0 || (mproc->p_flag&SLOAD) == 0) 731 return (0.0); 732 if (rawcpu) 733 return (100.0 * mproc->p_pctcpu); 734 return (100.0 * mproc->p_pctcpu / (1.0 - exp(time * log(ccpu)))); 735 } 736 737 getu() 738 { 739 struct pte *pteaddr, apte; 740 struct pte arguutl[UPAGES+CLSIZE]; 741 register int i; 742 int ncl, size; 743 744 size = sflg ? ctob(UPAGES) : sizeof (struct user); 745 if ((mproc->p_flag & SLOAD) == 0) { 746 if (swap < 0) 747 return (0); 748 (void) lseek(swap, (long)ctob(mproc->p_swaddr), 0); 749 if (read(swap, (char *)&user.user, size) != size) { 750 fprintf(stderr, "ps: cant read u for pid %d from %s\n", 751 mproc->p_pid, swapf); 752 return (0); 753 } 754 pcbpf = 0; 755 argaddr = 0; 756 return (1); 757 } 758 if (kflg) 759 mproc->p_p0br = (struct pte *)clear(mproc->p_p0br); 760 pteaddr = &Usrptma[btokmx(mproc->p_p0br) + mproc->p_szpt - 1]; 761 klseek(kmem, (long)pteaddr, 0); 762 if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) { 763 printf("ps: cant read indir pte to get u for pid %d from %s\n", 764 mproc->p_pid, swapf); 765 return (0); 766 } 767 klseek(mem, 768 (long)ctob(apte.pg_pfnum+1) - (UPAGES+CLSIZE) * sizeof (struct pte), 769 0); 770 if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) { 771 printf("ps: cant read page table for u of pid %d from %s\n", 772 mproc->p_pid, kmemf); 773 return (0); 774 } 775 if (arguutl[0].pg_fod == 0 && arguutl[0].pg_pfnum) 776 argaddr = ctob(arguutl[0].pg_pfnum); 777 else 778 argaddr = 0; 779 pcbpf = arguutl[CLSIZE].pg_pfnum; 780 ncl = (size + NBPG*CLSIZE - 1) / (NBPG*CLSIZE); 781 while (--ncl >= 0) { 782 i = ncl * CLSIZE; 783 klseek(mem, (long)ctob(arguutl[CLSIZE+i].pg_pfnum), 0); 784 if (read(mem, user.upages[i], CLSIZE*NBPG) != CLSIZE*NBPG) { 785 printf("ps: cant read page %d of u of pid %d from %s\n", 786 arguutl[CLSIZE+i].pg_pfnum, mproc->p_pid, memf); 787 return(0); 788 } 789 } 790 return (1); 791 } 792 793 char * 794 getcmd() 795 { 796 char cmdbuf[BUFSIZ]; 797 union { 798 char argc[CLSIZE*NBPG]; 799 int argi[CLSIZE*NBPG/sizeof (int)]; 800 } argspac; 801 register char *cp; 802 register int *ip; 803 char c; 804 int nbad; 805 struct dblock db; 806 char *file; 807 808 if (mproc->p_stat == SZOMB || mproc->p_flag&(SSYS|SWEXIT)) 809 return (""); 810 if (cflg) { 811 (void) strncpy(cmdbuf, u.u_comm, sizeof (u.u_comm)); 812 return (savestr(cmdbuf)); 813 } 814 if ((mproc->p_flag & SLOAD) == 0 || argaddr == 0) { 815 if (swap < 0) 816 goto retucomm; 817 vstodb(0, CLSIZE, &u.u_smap, &db, 1); 818 (void) lseek(swap, (long)ctob(db.db_base), 0); 819 if (read(swap, (char *)&argspac, sizeof(argspac)) 820 != sizeof(argspac)) 821 goto bad; 822 file = swapf; 823 } else { 824 klseek(mem, (long)argaddr, 0); 825 if (read(mem, (char *)&argspac, sizeof (argspac)) 826 != sizeof (argspac)) 827 goto bad; 828 file = memf; 829 } 830 ip = &argspac.argi[CLSIZE*NBPG/sizeof (int)]; 831 ip -= 2; /* last arg word and .long 0 */ 832 while (*--ip) 833 if (ip == argspac.argi) 834 goto retucomm; 835 *(char *)ip = ' '; 836 ip++; 837 nbad = 0; 838 for (cp = (char *)ip; cp < &argspac.argc[CLSIZE*NBPG]; cp++) { 839 c = *cp & 0177; 840 if (c == 0) 841 *cp = ' '; 842 else if (c < ' ' || c > 0176) { 843 if (++nbad >= 5*(eflg+1)) { 844 *cp++ = ' '; 845 break; 846 } 847 *cp = '?'; 848 } else if (eflg == 0 && c == '=') { 849 while (*--cp != ' ') 850 if (cp <= (char *)ip) 851 break; 852 break; 853 } 854 } 855 *cp = 0; 856 while (*--cp == ' ') 857 *cp = 0; 858 cp = (char *)ip; 859 (void) strncpy(cmdbuf, cp, &argspac.argc[CLSIZE*NBPG] - cp); 860 if (cp[0] == '-' || cp[0] == '?' || cp[0] <= ' ') { 861 (void) strcat(cmdbuf, " ("); 862 (void) strncat(cmdbuf, u.u_comm, sizeof(u.u_comm)); 863 (void) strcat(cmdbuf, ")"); 864 } 865 /* 866 if (xflg == 0 && gflg == 0 && tptr == 0 && cp[0] == '-') 867 return (0); 868 */ 869 return (savestr(cmdbuf)); 870 871 bad: 872 fprintf(stderr, "ps: error locating command name for pid %d from %s\n", 873 mproc->p_pid, file); 874 retucomm: 875 (void) strcpy(cmdbuf, " ("); 876 (void) strncat(cmdbuf, u.u_comm, sizeof (u.u_comm)); 877 (void) strcat(cmdbuf, ")"); 878 return (savestr(cmdbuf)); 879 } 880 881 char *lhdr = 882 " F UID PID PPID CP PRI NI ADDR SZ RSS WCHAN STAT TT TIME"; 883 lpr(sp) 884 struct savcom *sp; 885 { 886 register struct asav *ap = sp->ap; 887 register struct lsav *lp = sp->sun.lp; 888 889 printf("%6x%4d%6u%6u%3d%4d%3d%5x%4d%5d", 890 ap->a_flag, ap->a_uid, 891 ap->a_pid, lp->l_ppid, lp->l_cpu&0377, ap->a_pri-PZERO, 892 ap->a_nice-NZERO, lp->l_addr, ap->a_size/2, ap->a_rss/2); 893 printf(lp->l_wchan ? " %5x" : " ", (int)lp->l_wchan&0xfffff); 894 printf(" %4.4s ", state(ap)); 895 ptty(ap->a_tty); 896 ptime(ap); 897 } 898 899 ptty(tp) 900 char *tp; 901 { 902 903 printf("%-2.2s", tp); 904 } 905 906 ptime(ap) 907 struct asav *ap; 908 { 909 910 printf("%3ld:%02ld", ap->a_cpu / 60, ap->a_cpu % 60); 911 } 912 913 char *uhdr = 914 "USER PID %CPU %MEM SZ RSS TT STAT TIME"; 915 upr(sp) 916 struct savcom *sp; 917 { 918 register struct asav *ap = sp->ap; 919 int vmsize, rmsize; 920 921 vmsize = (ap->a_size + ap->a_tsiz)/2; 922 rmsize = ap->a_rss/2; 923 if (ap->a_xccount) 924 rmsize += ap->a_txtrss/ap->a_xccount/2; 925 printf("%-8.8s %5d%5.1f%5.1f%5d%5d", 926 getname(ap->a_uid), ap->a_pid, sp->sun.u_pctcpu, pmem(ap), 927 vmsize, rmsize); 928 putchar(' '); 929 ptty(ap->a_tty); 930 printf(" %4.4s", state(ap)); 931 ptime(ap); 932 } 933 934 char *vhdr = 935 " PID TT STAT TIME SL RE PAGEIN SIZE RSS LIM TSIZ TRS %CPU %MEM"; 936 vpr(sp) 937 struct savcom *sp; 938 { 939 register struct vsav *vp = sp->sun.vp; 940 register struct asav *ap = sp->ap; 941 942 printf("%5u ", ap->a_pid); 943 ptty(ap->a_tty); 944 printf(" %4.4s", state(ap)); 945 ptime(ap); 946 printf("%3d%3d%7d%5d%5d", 947 ap->a_slptime > 99 ? 99 : ap-> a_slptime, 948 ap->a_time > 99 ? 99 : ap->a_time, vp->v_majflt, 949 ap->a_size/2, ap->a_rss/2); 950 if (ap->a_maxrss == (INFINITY/NBPG)) 951 printf(" xx"); 952 else 953 printf("%5d", ap->a_maxrss/2); 954 printf("%5d%4d%5.1f%5.1f", 955 ap->a_tsiz/2, ap->a_txtrss/2, vp->v_pctcpu, pmem(ap)); 956 } 957 958 char *shdr = 959 "SSIZ PID TT STAT TIME"; 960 spr(sp) 961 struct savcom *sp; 962 { 963 register struct asav *ap = sp->ap; 964 965 if (sflg) 966 printf("%4d ", sp->sun.s_ssiz); 967 printf("%5u", ap->a_pid); 968 putchar(' '); 969 ptty(ap->a_tty); 970 printf(" %4.4s", state(ap)); 971 ptime(ap); 972 } 973 974 char * 975 state(ap) 976 register struct asav *ap; 977 { 978 char stat, load, nice, anom; 979 static char res[5]; 980 981 switch (ap->a_stat) { 982 983 case SSTOP: 984 stat = 'T'; 985 break; 986 987 case SSLEEP: 988 if (ap->a_pri >= PZERO) 989 if (ap->a_slptime >= MAXSLP) 990 stat = 'I'; 991 else 992 stat = 'S'; 993 else if (ap->a_flag & SPAGE) 994 stat = 'P'; 995 else 996 stat = 'D'; 997 break; 998 999 case SWAIT: 1000 case SRUN: 1001 case SIDL: 1002 stat = 'R'; 1003 break; 1004 1005 case SZOMB: 1006 stat = 'Z'; 1007 break; 1008 1009 default: 1010 stat = '?'; 1011 } 1012 load = ap->a_flag & SLOAD ? (ap->a_rss>ap->a_maxrss ? '>' : ' ') : 'W'; 1013 if (ap->a_nice < NZERO) 1014 nice = '<'; 1015 else if (ap->a_nice > NZERO) 1016 nice = 'N'; 1017 else 1018 nice = ' '; 1019 anom = (ap->a_flag&SUANOM) ? 'A' : ((ap->a_flag&SSEQL) ? 'S' : ' '); 1020 res[0] = stat; res[1] = load; res[2] = nice; res[3] = anom; 1021 return (res); 1022 } 1023 1024 /* 1025 * Given a base/size pair in virtual swap area, 1026 * return a physical base/size pair which is the 1027 * (largest) initial, physically contiguous block. 1028 */ 1029 vstodb(vsbase, vssize, dmp, dbp, rev) 1030 register int vsbase; 1031 int vssize; 1032 struct dmap *dmp; 1033 register struct dblock *dbp; 1034 { 1035 register int blk = DMMIN; 1036 register swblk_t *ip = dmp->dm_map; 1037 1038 if (vsbase < 0 || vsbase + vssize > dmp->dm_size) 1039 panic("vstodb"); 1040 while (vsbase >= blk) { 1041 vsbase -= blk; 1042 if (blk < DMMAX) 1043 blk *= 2; 1044 ip++; 1045 } 1046 if (*ip <= 0 || *ip + blk > nswap) 1047 panic("vstodb *ip"); 1048 dbp->db_size = min(vssize, blk - vsbase); 1049 dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase); 1050 } 1051 1052 /*ARGSUSED*/ 1053 panic(cp) 1054 char *cp; 1055 { 1056 1057 #ifdef DEBUG 1058 printf("%s\n", cp); 1059 #endif 1060 } 1061 1062 min(a, b) 1063 { 1064 1065 return (a < b ? a : b); 1066 } 1067 1068 pscomp(s1, s2) 1069 struct savcom *s1, *s2; 1070 { 1071 register int i; 1072 1073 if (uflg && !ssflg) 1074 return (s2->sun.u_pctcpu > s1->sun.u_pctcpu ? 1 : -1); 1075 if (vflg) 1076 return (vsize(s2) - vsize(s1)); 1077 i = s1->ap->a_ttyd - s2->ap->a_ttyd; 1078 if (i == 0) 1079 i = s1->ap->a_pid - s2->ap->a_pid; 1080 return (i); 1081 } 1082 1083 vsize(sp) 1084 struct savcom *sp; 1085 { 1086 register struct asav *ap = sp->ap; 1087 register struct vsav *vp = sp->sun.vp; 1088 1089 if (ap->a_flag & SLOAD) 1090 return (ap->a_rss + 1091 ap->a_txtrss / (ap->a_xccount ? ap->a_xccount : 1)); 1092 return (vp->v_swrss + (ap->a_xccount ? 0 : vp->v_txtswrss)); 1093 } 1094 1095 #define NMAX 8 1096 #define NUID 2048 1097 1098 char names[NUID][NMAX+1]; 1099 1100 /* 1101 * Stolen from ls... 1102 */ 1103 char * 1104 getname(uid) 1105 { 1106 register struct passwd *pw; 1107 static init; 1108 struct passwd *getpwent(); 1109 1110 if (uid >= 0 && uid < NUID && names[uid][0]) 1111 return (&names[uid][0]); 1112 if (init == 2) 1113 return (0); 1114 if (init == 0) 1115 setpwent(), init = 1; 1116 while (pw = getpwent()) { 1117 if (pw->pw_uid >= NUID) 1118 continue; 1119 if (names[pw->pw_uid][0]) 1120 continue; 1121 (void) strncpy(names[pw->pw_uid], pw->pw_name, NMAX); 1122 if (pw->pw_uid == uid) 1123 return (&names[uid][0]); 1124 } 1125 init = 2; 1126 endpwent(); 1127 return (0); 1128 } 1129 1130 char *freebase; 1131 int nleft; 1132 1133 char * 1134 alloc(size) 1135 int size; 1136 { 1137 register char *cp; 1138 register int i; 1139 1140 if (size > nleft) { 1141 freebase = (char *)sbrk((int)(i = size > 2048 ? size : 2048)); 1142 if (freebase == 0) { 1143 fprintf(stderr, "ps: ran out of memory\n"); 1144 exit(1); 1145 } 1146 nleft = i - size; 1147 } else 1148 nleft -= size; 1149 cp = freebase; 1150 for (i = size; --i >= 0; ) 1151 *cp++ = 0; 1152 freebase = cp; 1153 return (cp - size); 1154 } 1155 1156 char * 1157 savestr(cp) 1158 char *cp; 1159 { 1160 register int len; 1161 register char *dp; 1162 1163 len = strlen(cp); 1164 dp = (char *)alloc(len+1); 1165 (void) strcpy(dp, cp); 1166 return (dp); 1167 } 1168 1169 walk(np) 1170 int np; 1171 { 1172 register int i, j, k, l, m; 1173 #undef afl 1174 #undef sfl 1175 #define afl(i,f) savcom[i].ap -> f 1176 #define sfl(i,f) savcom[i].sun.ssp -> f 1177 1178 for(i = 0; i < np; i = j) { 1179 for(j = i; afl(j,a_ttyd) == afl(i,a_ttyd); j++) { 1180 sfl(j,ss_brother) = -1; 1181 sfl(j,ss_sons) = -1; 1182 } 1183 for(k = i+1; k < j; k++) { 1184 if(sfl(k,ss_ppid) == sfl(i,ss_ppid)) { 1185 for(l=i; sfl(l,ss_brother) != -1; 1186 l=sfl(l,ss_brother)) ; 1187 sfl(l,ss_brother) = k; 1188 goto next; 1189 } 1190 for(l = i; l < j; l++) { 1191 if(l == k) continue; 1192 if(sfl(k,ss_ppid) == afl(l,a_pid)) { 1193 if(sfl(l,ss_sons) == -1) 1194 sfl(l,ss_sons) = k; 1195 else { 1196 for(m = sfl(l,ss_sons); 1197 sfl(m,ss_brother) != -1; 1198 m = sfl(m,ss_brother)) ; 1199 sfl(m,ss_brother) = k; 1200 } 1201 goto next; 1202 } 1203 } 1204 for(l = i; l < j; l++) { 1205 if(l == k) continue; 1206 if(sfl(k,ss_ppid) == sfl(l,ss_ppid)) { 1207 for(m = k; sfl(m,ss_brother) != -1; 1208 m = sfl(m,ss_brother)) ; 1209 sfl(m,ss_brother) = l; 1210 } 1211 } 1212 next: ; 1213 } 1214 walk1(i, 0); 1215 } 1216 } 1217 1218 walk1(pno, depth) 1219 int pno, depth; 1220 { 1221 if(pno == -1) 1222 return; 1223 /*** printf("%5d, %d\n",outargs[pno].o_pid, depth); ***/ 1224 walkpr(&savcom[pno], depth); 1225 walk1(sfl(pno,ss_sons), depth+1); 1226 walk1(sfl(pno,ss_brother), depth); 1227 } 1228 1229 char *sshdr = 1230 "TTY User SZ RSS CPU S PID "; 1231 1232 walkpr(a, depth) 1233 register struct savcom *a; 1234 int depth; 1235 { 1236 1237 if(!depth) { 1238 printf("%-2.2s", a->ap->a_tty); 1239 printf(" %-8.8s", getname(a->ap->a_uid)); 1240 } else 1241 printf(" %-8s", &".......*"[8-(depth<=8?depth:8)]); 1242 printf("%4d%4d", a->ap->a_size/2, a->ap->a_rss/2); 1243 ptime(a->ap); 1244 /* Once there was a "CCPU" field here. Subsumed by -S now. */ 1245 printf(" %4.4s", state(a->ap)); 1246 printf("%6u ", a->ap->a_pid); 1247 if (a->ap->a_pid == 0) 1248 printf(" swapper"); 1249 else if (a->ap->a_pid == 2) 1250 printf(" pagedaemon"); 1251 else 1252 printf(" %.*s", twidth - cmdstart - 2, a->ap->a_cmdp); 1253 putchar('\n'); 1254 } 1255