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