1 static char *sccsid = "@(#)ps.c 4.1 (Berkeley) 10/01/80"; 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 20 struct nlist nl[] = { 21 { "_proc" }, 22 #define X_PROC 0 23 { "_Usrptmap" }, 24 #define X_USRPTMA 1 25 { "_usrpt" }, 26 #define X_USRPT 2 27 { "_text" }, 28 #define X_TEXT 3 29 { "_nswap" }, 30 #define X_NSWAP 4 31 { 0 }, 32 }; 33 34 struct savcom { 35 union { 36 struct lsav *lp; 37 float u_pctcpu; 38 struct vsav *vp; 39 int s_ssiz; 40 } sun; 41 struct asav *ap; 42 } savcom[NPROC]; 43 44 struct asav { 45 char *a_cmdp; 46 int a_flag; 47 short a_stat, a_uid, a_pid, a_nice; 48 size_t a_size, a_rss; 49 char a_tty[DIRSIZ+1]; 50 dev_t a_ttyd; 51 time_t a_time; 52 }; 53 54 char *lhdr; 55 /* F S UID PID PPID CP PRI NICE ADDR SZ RSS WCHAN TTY TIME */ 56 struct lsav { 57 short l_ppid; 58 char l_cpu, l_pri; 59 int l_addr; 60 caddr_t l_wchan; 61 }; 62 63 char *uhdr; 64 /* USER PID %CPU NICE SZ RSS TTY TIME */ 65 66 char *shdr; 67 /* SSIZ PID TTY TIME */ 68 69 char *vhdr; 70 /* F PID TTY TIME TIM SL MINFLT MAJFLT SIZE RSS SRS TSIZ TRS PF*/ 71 struct vsav { 72 short v_slptime, v_pri; 73 u_int v_minflt, v_majflt; 74 size_t v_swrss, v_tsiz, v_txtrss, v_txtswrss; 75 short v_xccount; 76 short v_aveflt; 77 }; 78 79 struct proc proc[8]; /* 8 = a few, for less syscalls */ 80 struct proc *mproc; 81 struct text *text; 82 83 union { 84 struct user user; 85 char upages[UPAGES][NBPG]; 86 } user; 87 #define u user.user 88 89 #define clear(x) ((int)x & 0x7fffffff) 90 91 int chkpid; 92 int aflg, cflg, eflg, gflg, kflg, lflg, sflg, uflg, vflg, xflg; 93 char *tptr; 94 char *gettty(), *getcmd(), *getname(), *savestr(), *alloc(); 95 int pscomp(); 96 int nswap; 97 struct pte *Usrptma, *usrpt; 98 99 struct ttys { 100 char name[DIRSIZ+1]; 101 dev_t ttyd; 102 struct ttys *next; 103 struct ttys *cand; 104 } *allttys, *cand[16]; 105 106 struct savcom savcom[NPROC]; 107 int npr; 108 109 int cmdstart; 110 int twidth; 111 char *kmemf, *memf, *swapf, *nlistf; 112 int kmem, mem, swap; 113 114 int pcbpf; 115 int argaddr; 116 extern char _sobuf[]; 117 118 main(argc, argv) 119 char **argv; 120 { 121 register int i, j; 122 register char *ap; 123 int uid; 124 off_t procp; 125 126 if (chdir("/dev") < 0) { 127 perror("/dev"); 128 exit(1); 129 } 130 twidth = 80; 131 setbuf(stdout, _sobuf); 132 argc--, argv++; 133 if (argc > 0) { 134 ap = argv[0]; 135 while (*ap) switch (*ap++) { 136 137 case 'a': 138 aflg++; 139 break; 140 case 'c': 141 cflg = !cflg; 142 break; 143 case 'e': 144 eflg++; 145 break; 146 case 'g': 147 gflg++; 148 break; 149 case 'k': 150 kflg++; 151 break; 152 case 'l': 153 lflg++; 154 break; 155 case 's': 156 sflg++; 157 break; 158 case 't': 159 if (*ap) 160 tptr = ap; 161 aflg++; 162 gflg++; 163 if (*tptr == '?') 164 xflg++; 165 while (*ap) 166 ap++; 167 break; 168 case 'u': 169 uflg++; 170 break; 171 case 'v': 172 cflg = 1; 173 vflg++; 174 break; 175 case 'w': 176 if (twidth == 80) 177 twidth = 132; 178 else 179 twidth = BUFSIZ; 180 break; 181 case 'x': 182 xflg++; 183 break; 184 default: 185 if (!isdigit(ap[-1])) 186 break; 187 chkpid = atoi(--ap); 188 *ap = 0; 189 aflg++; 190 xflg++; 191 break; 192 } 193 } 194 openfiles(argc, argv); 195 getkvars(argc, argv); 196 getdev(); 197 uid = getuid(); 198 printhdr(); 199 procp = nl[X_PROC].n_value; 200 for (i=0; i<NPROC; i += 8) { 201 lseek(kmem, (char *)procp, 0); 202 j = NPROC - i; 203 if (j > 8) 204 j = 8; 205 j *= sizeof (struct proc); 206 if (read(kmem, (char *)proc, j) != j) 207 cantread("proc table", kmemf); 208 procp += j; 209 for (j = j / sizeof (struct proc) - 1; j >= 0; j--) { 210 mproc = &proc[j]; 211 if (mproc->p_stat == 0 || 212 mproc->p_pgrp == 0 && xflg == 0) 213 continue; 214 if (tptr == 0 && gflg == 0 && xflg == 0 && 215 mproc->p_ppid == 1 && (mproc->p_flag&SDETACH) == 0) 216 continue; 217 if (uid != mproc->p_uid && aflg==0 || 218 chkpid != 0 && chkpid != mproc->p_pid) 219 continue; 220 if (vflg && gflg == 0 && xflg == 0) { 221 if (mproc->p_stat == SZOMB || 222 mproc->p_flag&SWEXIT) 223 continue; 224 if (mproc->p_slptime > MAXSLP && 225 (mproc->p_stat == SSLEEP || 226 mproc->p_stat == SSTOP)) 227 continue; 228 } 229 save(); 230 } 231 } 232 qsort(savcom, npr, sizeof(savcom[0]), pscomp); 233 for (i=0; i<npr; i++) { 234 register struct savcom *sp = &savcom[i]; 235 if (lflg) 236 lpr(sp); 237 else if (vflg) 238 vpr(sp); 239 else if (uflg) 240 upr(sp); 241 else 242 spr(sp); 243 if (sp->ap->a_flag & SWEXIT) 244 printf(" <exiting>"); 245 else if (sp->ap->a_stat == SZOMB) 246 printf(" <defunct>"); 247 else if (sp->ap->a_pid == 0) 248 printf(" swapper"); 249 else if (sp->ap->a_pid == 2) 250 printf(" pagedaemon"); 251 else 252 printf(" %.*s", twidth - cmdstart - 2, sp->ap->a_cmdp); 253 printf("\n"); 254 } 255 exit(npr == 0); 256 } 257 258 openfiles(argc, argv) 259 char **argv; 260 { 261 262 kmemf = "kmem"; 263 if (kflg) 264 kmemf = argc > 1 ? argv[1] : "/vmcore"; 265 kmem = open(kmemf, 0); 266 if (kmem < 0) { 267 perror(kmemf); 268 exit(1); 269 } 270 if (kflg) { 271 mem = kmem; 272 memf = kmemf; 273 } else { 274 memf = "mem"; 275 mem = open(memf, 0); 276 if (mem < 0) { 277 perror(memf); 278 exit(1); 279 } 280 } 281 swapf = argc>2 ? argv[2]: "drum"; 282 swap = open(swapf, 0); 283 if (swap < 0) { 284 perror(swapf); 285 exit(1); 286 } 287 } 288 289 getkvars(argc, argv) 290 char **argv; 291 { 292 register struct nlist *nlp; 293 294 nlistf = argc > 3 ? argv[3] : "/vmunix"; 295 nlist(nlistf, nl); 296 if (nl[0].n_type == 0) { 297 fprintf(stderr, "%s: No namelist\n", nlistf); 298 exit(1); 299 } 300 if (kflg) 301 for (nlp = nl; nlp < &nl[sizeof (nl)/sizeof (nl[0])]; nlp++) 302 nlp->n_value = clear(nlp->n_value); 303 Usrptma = (struct pte *)nl[X_USRPTMA].n_value; 304 usrpt = (struct pte *)nl[X_USRPT].n_value; 305 lseek(kmem, (long)nl[X_NSWAP].n_value, 0); 306 if (read(kmem, &nswap, sizeof (nswap)) != sizeof (nswap)) { 307 cantread("nswap", kmemf); 308 exit(1); 309 } 310 if (vflg) { 311 text = (struct text *)alloc(NTEXT * sizeof (struct text)); 312 if (text == 0) { 313 fprintf(stderr, "no room for text table\n"); 314 exit(1); 315 } 316 lseek(kmem, (long)nl[X_TEXT].n_value, 0); 317 if (read(kmem, (char *)text, NTEXT * sizeof (struct text)) 318 != NTEXT * sizeof (struct text)) { 319 cantread("text table", kmemf); 320 exit(1); 321 } 322 } 323 } 324 325 printhdr() 326 { 327 char *hdr; 328 329 if (sflg+lflg+vflg+uflg > 1) { 330 fprintf(stderr, "ps: specify only one of s,l,v and u\n"); 331 exit(1); 332 } 333 hdr = lflg ? lhdr : (vflg ? vhdr : (uflg ? uhdr : shdr)); 334 if (lflg+vflg+uflg+sflg == 0) 335 hdr += strlen(" SSIZ"); 336 cmdstart = strlen(hdr); 337 printf("%s COMMAND\n", hdr); 338 fflush(stdout); 339 } 340 341 cantread(what, fromwhat) 342 char *what, *fromwhat; 343 { 344 345 fprintf(stderr, "ps: error reading %s from %s", what, fromwhat); 346 } 347 348 struct direct dbuf; 349 int dialbase; 350 351 getdev() 352 { 353 register FILE *df; 354 register struct ttys *dp; 355 356 dialbase = -1; 357 if ((df = fopen(".", "r")) == NULL) { 358 fprintf(stderr, "Can't open . in /dev\n"); 359 exit(1); 360 } 361 while (fread((char *)&dbuf, sizeof(dbuf), 1, df) == 1) { 362 if (dbuf.d_ino == 0) 363 continue; 364 maybetty(dp); 365 } 366 fclose(df); 367 } 368 369 /* 370 * Attempt to avoid stats by guessing minor device 371 * numbers from tty names. Console is known, 372 * know that r(hp|up|mt) are unlikely as are different mem's, 373 * floppy, null, tty, etc. 374 */ 375 maybetty() 376 { 377 register char *cp = dbuf.d_name; 378 register struct ttys *dp; 379 int x; 380 struct stat stb; 381 382 switch (cp[0]) { 383 384 case 'c': 385 if (!strcmp(cp, "console")) { 386 x = 0; 387 goto donecand; 388 } 389 /* cu[la]? are possible!?! don't rule them out */ 390 break; 391 392 case 'd': 393 if (!strcmp(cp, "drum")) 394 return (0); 395 break; 396 397 case 'f': 398 if (!strcmp(cp, "floppy")) 399 return (0); 400 break; 401 402 case 'k': 403 cp++; 404 if (*cp == 'U') 405 cp++; 406 goto trymem; 407 408 case 'r': 409 cp++; 410 if (*cp == 'r' || *cp == 'u' || *cp == 'h') 411 cp++; 412 #define is(a,b) cp[0] == 'a' && cp[1] == 'b' 413 if (is(r,p) || is(u,p) || is(r,k) || is(r,m) || is(m,t)) { 414 cp += 2; 415 if (isdigit(*cp) && cp[2] == 0) 416 return (0); 417 } 418 break; 419 420 case 'm': 421 trymem: 422 if (cp[0] == 'm' && cp[1] == 'e' && cp[2] == 'm' && cp[3] == 0) 423 return (0); 424 break; 425 426 case 'n': 427 if (!strcmp(cp, "null")) 428 return (0); 429 break; 430 431 case 'v': 432 if ((cp[1] == 'a' || cp[1] == 'p') && isdigit(cp[2]) && 433 cp[3] == 0) 434 return (0); 435 break; 436 } 437 mightbe: 438 cp = dbuf.d_name; 439 while (cp < &dbuf.d_name[DIRSIZ] && *cp) 440 cp++; 441 --cp; 442 x = 0; 443 if (cp[-1] == 'd') { 444 if (dialbase == -1) { 445 if (stat("ttyd0", &stb) == 0) 446 dialbase = stb.st_rdev & 017; 447 else 448 dialbase = -2; 449 } 450 if (dialbase == -2) 451 x = 0; 452 else 453 x = 11; 454 } 455 if (cp > dbuf.d_name && isdigit(cp[-1]) && isdigit(*cp)) 456 x += 10 * (cp[-1] - ' ') + cp[0] - '0'; 457 else if (*cp >= 'a' && *cp <= 'f') 458 x += 10 + *cp - 'a'; 459 else if (isdigit(*cp)) 460 x += *cp - '0'; 461 else 462 x = -1; 463 donecand: 464 dp = (struct ttys *)alloc(sizeof (struct ttys)); 465 strncpy(dp->name, dbuf.d_name, DIRSIZ); 466 dp->next = allttys; 467 dp->ttyd = -1; 468 allttys = dp; 469 if (x == -1) 470 return; 471 x &= 017; 472 dp->cand = cand[x]; 473 cand[x] = dp; 474 } 475 476 char * 477 gettty() 478 { 479 register char *p; 480 register struct ttys *dp; 481 struct stat stb; 482 int x; 483 484 if (u.u_ttyp == 0) 485 return("?"); 486 x = u.u_ttyd & 017; 487 for (dp = cand[x]; dp; dp = dp->cand) { 488 if (dp->ttyd == -1) { 489 if (stat(dp->name, &stb) == 0) 490 dp->ttyd = stb.st_rdev; 491 else 492 dp->ttyd = -2; 493 } 494 if (dp->ttyd == u.u_ttyd) 495 goto found; 496 } 497 /* ick */ 498 for (dp = allttys; dp; dp = dp->next) { 499 if (dp->ttyd == -1) { 500 if (stat(dp->name, &stb) == 0) 501 dp->ttyd = stb.st_rdev; 502 else 503 dp->ttyd = -2; 504 } 505 if (dp->ttyd == u.u_ttyd) 506 goto found; 507 } 508 return ("?"); 509 found: 510 p = dp->name; 511 if (p[0]=='t' && p[1]=='t' && p[2]=='y') 512 p += 3; 513 return (p); 514 } 515 516 save() 517 { 518 register struct savcom *sp; 519 register struct asav *ap; 520 register char *cp; 521 char *ttyp, *cmdp; 522 523 if (mproc->p_stat != SZOMB && getu() == 0) 524 return; 525 ttyp = gettty(); 526 if (xflg == 0 && ttyp[0] == '?' || tptr && strcmpn(tptr, ttyp, 2)) 527 return; 528 sp = &savcom[npr]; 529 cmdp = getcmd(); 530 if (cmdp == 0) 531 return; 532 sp->ap = ap = (struct asav *)alloc(sizeof (struct asav)); 533 sp->ap->a_cmdp = cmdp; 534 #define e(a,b) ap->a = mproc->b 535 e(a_flag, p_flag); e(a_stat, p_stat); e(a_nice, p_nice); 536 e(a_uid, p_uid); e(a_pid, p_pid); e(a_rss, p_rssize); 537 #undef e 538 ap->a_tty[0] = ttyp[0]; 539 ap->a_tty[1] = ttyp[1] ? ttyp[1] : ' '; 540 if (ap->a_stat == SZOMB) { 541 register struct xproc *xp = (struct xproc *)mproc; 542 543 ap->a_time = xp->xp_vm.vm_utime + xp->xp_vm.vm_stime; 544 } else { 545 ap->a_size = mproc->p_dsize + mproc->p_ssize; 546 ap->a_ttyd = u.u_ttyd; 547 ap->a_time = u.u_vm.vm_utime + u.u_vm.vm_stime; 548 } 549 ap->a_time /= HZ; 550 if (lflg) { 551 register struct lsav *lp; 552 553 sp->sun.lp = lp = (struct lsav *)alloc(sizeof (struct lsav)); 554 #define e(a,b) lp->a = mproc->b 555 e(l_ppid, p_ppid); e(l_cpu, p_cpu); e(l_pri, p_pri); 556 if (ap->a_stat != SZOMB) 557 e(l_wchan, p_wchan); 558 #undef e 559 lp->l_addr = pcbpf; 560 } else if (vflg) { 561 register struct vsav *vp; 562 register struct text *xp; 563 564 sp->sun.vp = vp = (struct vsav *)alloc(sizeof (struct vsav)); 565 #define e(a,b) vp->a = mproc->b 566 e(v_slptime, p_slptime); e(v_pri, p_pri); 567 if (ap->a_stat != SZOMB) { 568 e(v_swrss, p_swrss); e(v_aveflt, p_aveflt); 569 vp->v_minflt = u.u_vm.vm_minflt; 570 vp->v_majflt = u.u_vm.vm_majflt; 571 if (mproc->p_textp) { 572 xp = &text[mproc->p_textp - 573 (struct text *)nl[X_TEXT].n_value]; 574 vp->v_tsiz = xp->x_size; 575 vp->v_txtrss = xp->x_rssize; 576 vp->v_txtswrss = xp->x_swrss; 577 vp->v_xccount = xp->x_ccount; 578 } 579 } 580 #undef e 581 } else if (uflg) 582 sp->sun.u_pctcpu = 0.0; 583 else if (sflg) { 584 if (ap->a_stat != SZOMB) { 585 for (cp = (char *)u.u_stack; 586 cp < &user.upages[UPAGES][NBPG]; ) 587 if (*cp++) 588 break; 589 sp->sun.s_ssiz = (&user.upages[UPAGES][NBPG] - cp); 590 } 591 } 592 npr++; 593 } 594 595 getu() 596 { 597 struct pte *pteaddr, apte, arguutl[UPAGES+CLSIZE]; 598 register int i; 599 int ncl, size; 600 601 size = sflg ? ctob(UPAGES) : sizeof (struct user); 602 if ((mproc->p_flag & SLOAD) == 0) { 603 lseek(swap, ctob(mproc->p_swaddr), 0); 604 if (read(swap, (char *)&user.user, size) != size) { 605 fprintf(stderr, "ps: cant read u for pid %d from %s\n", 606 mproc->p_pid, swapf); 607 return (0); 608 } 609 pcbpf = 0; 610 argaddr = 0; 611 return (1); 612 } 613 pteaddr = &Usrptma[btokmx(mproc->p_p0br) + mproc->p_szpt - 1]; 614 lseek(kmem, kflg ? clear(pteaddr) : (int)pteaddr, 0); 615 if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) { 616 printf("ps: cant read indir pte to get u for pid %d from %s\n", 617 mproc->p_pid, swapf); 618 return (0); 619 } 620 lseek(mem, 621 ctob(apte.pg_pfnum+1) - (UPAGES+CLSIZE) * sizeof (struct pte), 0); 622 if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) { 623 printf("ps: cant read page table for u of pid %d from %s\n", 624 mproc->p_pid, swapf); 625 return (0); 626 } 627 if (arguutl[0].pg_fod == 0 && arguutl[0].pg_pfnum) 628 argaddr = ctob(arguutl[0].pg_pfnum); 629 else 630 argaddr = 0; 631 pcbpf = arguutl[CLSIZE].pg_pfnum; 632 ncl = (size + NBPG*CLSIZE - 1) / (NBPG*CLSIZE); 633 while (--ncl >= 0) { 634 i = ncl * CLSIZE; 635 lseek(mem, ctob(arguutl[CLSIZE+i].pg_pfnum), 0); 636 if (read(mem, user.upages[i], CLSIZE*NBPG) != CLSIZE*NBPG) { 637 printf("ps: cant read page %d of u of pid %d from %s\n", 638 arguutl[CLSIZE+i].pg_pfnum, mproc->p_pid, memf); 639 return(0); 640 } 641 } 642 return (1); 643 } 644 645 char * 646 getcmd() 647 { 648 char cmdbuf[BUFSIZ]; 649 union { 650 char argc[CLSIZE*NBPG]; 651 int argi[CLSIZE*NBPG/sizeof (int)]; 652 } argspac; 653 register char *cp; 654 register int *ip; 655 char c; 656 int nbad; 657 struct dblock db; 658 659 if (mproc->p_stat == SZOMB || mproc->p_flag&(SSYS|SWEXIT)) 660 return (""); 661 if (cflg) { 662 strncpy(cmdbuf, u.u_comm, sizeof (u.u_comm)); 663 return (savestr(cmdbuf)); 664 } 665 if ((mproc->p_flag & SLOAD) == 0 || argaddr == 0) { 666 vstodb(0, CLSIZE, &u.u_smap, &db, 1); 667 lseek(swap, ctob(db.db_base), 0); 668 if (read(swap, (char *)&argspac, sizeof(argspac)) 669 != sizeof(argspac)) 670 goto bad; 671 } else { 672 lseek(mem, argaddr, 0); 673 if (read(mem, (char *)&argspac, sizeof (argspac)) 674 != sizeof (argspac)) 675 goto bad; 676 } 677 ip = &argspac.argi[CLSIZE*NBPG/sizeof (int)]; 678 ip -= 2; /* last arg word and .long 0 */ 679 while (*--ip) 680 if (ip == argspac.argi) 681 goto retucomm; 682 *(char *)ip = ' '; 683 ip++; 684 nbad = 0; 685 for (cp = (char *)ip; cp < &argspac.argc[CLSIZE*NBPG]; cp++) { 686 c = *cp & 0177; 687 if (c == 0) 688 *cp = ' '; 689 else if (c < ' ' || c > 0176) { 690 if (++nbad >= 5*(eflg+1)) { 691 *cp++ = ' '; 692 break; 693 } 694 *cp = '?'; 695 } else if (eflg == 0 && c == '=') { 696 while (*--cp != ' ') 697 if (cp <= (char *)ip) 698 break; 699 break; 700 } 701 } 702 *cp = 0; 703 while (*--cp == ' ') 704 *cp = 0; 705 cp = (char *)ip; 706 strncpy(cmdbuf, cp, &argspac.argc[CLSIZE*NBPG] - cp); 707 if (cp[0] == '-' || cp[0] == '?' || cp[0] <= ' ') { 708 strcat(cmdbuf, " ("); 709 strncat(cmdbuf, u.u_comm, sizeof(u.u_comm)); 710 strcat(cmdbuf, ")"); 711 } 712 if (xflg == 0 && gflg == 0 && tptr == 0 && cp[0] == '-') 713 return (0); 714 return (savestr(cmdbuf)); 715 716 bad: 717 fprintf(stderr, "ps: error locating command name for pid %d\n", 718 mproc->p_pid); 719 retucomm: 720 strcpy(cmdbuf, " ("); 721 strncat(cmdbuf, u.u_comm, sizeof (u.u_comm)); 722 strcat(cmdbuf, ")"); 723 return (savestr(cmdbuf)); 724 } 725 726 char *lhdr = 727 " F S UID PID PPID CP PRI NI ADDR SZ RSS WCHAN TTY TIME"; 728 lpr(sp) 729 struct savcom *sp; 730 { 731 register struct asav *ap = sp->ap; 732 register struct lsav *lp = sp->sun.lp; 733 734 printf("%6x %c%4d%6u%6u%3d%4d%2d%6x%4d%5d", 735 ap->a_flag, "0SWRIZT"[ap->a_stat], ap->a_uid, 736 ap->a_pid, lp->l_ppid, lp->l_cpu&0377, lp->l_pri-PZERO, 737 ap->a_nice-NZERO, lp->l_addr, ap->a_size, ap->a_rss); 738 printf(lp->l_wchan ? " %5x" : " ", (int)lp->l_wchan&0xfffff); 739 ptty(ap->a_tty); 740 ptime(ap); 741 } 742 743 ptty(tp) 744 char *tp; 745 { 746 747 printf(" %-2.2s", tp); 748 } 749 750 ptime(ap) 751 struct asav *ap; 752 { 753 754 printf("%3ld:%02ld", ap->a_time / HZ, ap->a_time % HZ); 755 } 756 757 char *uhdr = 758 "USER PID %CPU NICE SZ RSS TTY TIME"; 759 upr(sp) 760 struct savcom *sp; 761 { 762 register struct asav *ap = sp->ap; 763 764 printf("%-8.8s %5u%5.1f%5d%4d%5d", 765 getname(ap->a_uid), ap->a_pid, sp->sun.u_pctcpu, ap->a_nice-NZERO, 766 ap->a_size, ap->a_rss); 767 ptty(ap->a_tty); 768 ptime(ap); 769 } 770 771 char *vhdr = 772 "F PID TTY TIME RES SL MINFLT MAJFLT SIZE RSS SRS TSIZ TRS PF"; 773 vpr(sp) 774 struct savcom *sp; 775 { 776 register struct vsav *vp = sp->sun.vp; 777 register struct asav *ap = sp->ap; 778 char stat, nice, anom; 779 780 switch (ap->a_stat) { 781 782 case SSLEEP: 783 case SSTOP: 784 if ((ap->a_flag & SLOAD) == 0) 785 stat = 'W'; 786 else if (vp->v_pri >= PZERO) 787 stat = 'S'; 788 else if (ap->a_flag & SPAGE) 789 stat = 'P'; 790 else 791 stat = 'D'; 792 break; 793 794 case SRUN: 795 case SIDL: 796 stat = ap->a_flag & SLOAD ? 'R' : 'W'; 797 break; 798 } 799 nice = ap->a_nice > NZERO ? 'N' : ' '; 800 anom = ap->a_flag & (SANOM|SUANOM) ? 'A' : ' '; 801 printf("%c%c%c%6u ", stat, nice, anom, ap->a_pid); 802 ptty(ap->a_tty); 803 ptime(ap); 804 printf("%4d%3d%8d%8d%5d%5d%5d%5d%4d%3d", 805 ap->a_time, vp->v_slptime, vp->v_minflt, vp->v_majflt, 806 ap->a_size, ap->a_rss / 2, vp->v_swrss / 2, 807 vp->v_tsiz / 2, vp->v_txtrss / 2, vp->v_aveflt); 808 } 809 810 char *shdr = 811 " SSIZ PID TTY TIME"; 812 spr(sp) 813 struct savcom *sp; 814 { 815 register struct asav *ap = sp->ap; 816 817 if (sflg) 818 printf("%5d", sp->sun.s_ssiz); 819 printf(" %5u", ap->a_pid); 820 ptty(ap->a_tty); 821 ptime(ap); 822 } 823 824 /* 825 * Given a base/size pair in virtual swap area, 826 * return a physical base/size pair which is the 827 * (largest) initial, physically contiguous block. 828 */ 829 vstodb(vsbase, vssize, dmp, dbp, rev) 830 register int vsbase; 831 int vssize; 832 struct dmap *dmp; 833 register struct dblock *dbp; 834 { 835 register int blk = DMMIN; 836 register swblk_t *ip = dmp->dm_map; 837 838 if (vsbase < 0 || vsbase + vssize > dmp->dm_size) 839 panic("vstodb"); 840 while (vsbase >= blk) { 841 vsbase -= blk; 842 if (blk < DMMAX) 843 blk *= 2; 844 ip++; 845 } 846 if (*ip <= 0 || *ip + blk > nswap) 847 panic("vstodb *ip"); 848 dbp->db_size = min(vssize, blk - vsbase); 849 dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase); 850 } 851 852 /*ARGSUSED*/ 853 panic(cp) 854 char *cp; 855 { 856 857 #ifdef DEBUG 858 printf("%s\n", cp); 859 #endif 860 } 861 862 min(a, b) 863 { 864 865 return (a < b ? a : b); 866 } 867 868 pscomp(s1, s2) 869 struct savcom *s1, *s2; 870 { 871 register int i; 872 873 if (vflg) 874 return (vsize(s2) - vsize(s1)); 875 i = s1->ap->a_ttyd - s2->ap->a_ttyd; 876 if (i == 0) 877 i = s1->ap->a_pid - s2->ap->a_pid; 878 return (i); 879 } 880 881 vsize(sp) 882 struct savcom *sp; 883 { 884 register struct asav *ap = sp->ap; 885 register struct vsav *vp = sp->sun.vp; 886 887 if (ap->a_flag & SLOAD) 888 return (ap->a_rss + 889 vp->v_txtrss / (vp->v_xccount ? vp->v_xccount : 1)); 890 return (vp->v_swrss + (vp->v_xccount ? 0 : vp->v_txtswrss)); 891 } 892 893 #define NMAX 8 894 #define NUID 2048 895 896 char names[NUID][NMAX+1]; 897 898 /* 899 * Stolen from ls... 900 */ 901 char * 902 getname(uid) 903 { 904 register struct passwd *pw; 905 static init; 906 struct passwd *getpwent(); 907 908 if (names[uid][0]) 909 return (&names[uid][0]); 910 if (init == 2) 911 return (0); 912 if (init == 0) 913 setpwent(), init = 1; 914 while (pw = getpwent()) { 915 if (pw->pw_uid >= NUID) 916 continue; 917 if (names[pw->pw_uid][0]) 918 continue; 919 strncpy(names[pw->pw_uid], pw->pw_name, NMAX); 920 if (pw->pw_uid == uid) 921 return (&names[uid][0]); 922 } 923 init = 2; 924 endpwent(); 925 return (0); 926 } 927 928 char *freebase; 929 int nleft; 930 931 char * 932 alloc(size) 933 int size; 934 { 935 register char *cp; 936 register int i; 937 938 if (size > nleft) { 939 freebase = (char *)sbrk(i = size > 2048 ? size : 2048); 940 if (freebase == 0) { 941 fprintf(stderr, "ps: ran out of memory\n"); 942 exit(1); 943 } 944 nleft = i - size; 945 } else 946 nleft -= size; 947 cp = freebase; 948 for (i = size; --i >= 0; ) 949 *cp++ = 0; 950 freebase = cp; 951 return (cp - size); 952 } 953 954 char * 955 savestr(cp) 956 char *cp; 957 { 958 register int len; 959 register char *dp; 960 961 len = strlen(cp); 962 dp = (char *)alloc(len+1); 963 strcpy(dp, cp); 964 return (dp); 965 } 966