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