1 /*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)print.c 5.13 (Berkeley) 07/09/92"; 10 #endif /* not lint */ 11 12 #include <sys/param.h> 13 #include <sys/time.h> 14 #include <sys/resource.h> 15 #include <sys/proc.h> 16 #include <sys/stat.h> 17 #include <math.h> 18 #include <nlist.h> 19 #include <tzfile.h> 20 #include <stdio.h> 21 #include <stddef.h> 22 #include <string.h> 23 #include "ps.h" 24 25 #ifdef SPPWAIT 26 #define NEWVM 27 #endif 28 29 #ifdef NEWVM 30 #include <vm/vm.h> 31 #include <sys/ucred.h> 32 #include <sys/kinfo_proc.h> 33 #else 34 #include <machine/pte.h> 35 #include <sys/vmparam.h> 36 #include <sys/vm.h> 37 #endif 38 39 static void printval __P((char*, struct var *)); 40 41 void 42 printheader() 43 { 44 register VAR *v; 45 register struct varent *vent; 46 47 for (vent = vhead; vent; vent = vent->next) { 48 v = vent->var; 49 if (v->flag & LJUST) { 50 if (vent->next == NULL) /* last one */ 51 (void)printf("%s", v->header); 52 else 53 (void)printf("%-*s", v->width, v->header); 54 } else 55 (void)printf("%*s", v->width, v->header); 56 if (vent->next != NULL) 57 (void)putchar(' '); 58 } 59 (void)putchar('\n'); 60 } 61 62 void 63 command(k, ve) 64 KINFO *k; 65 VARENT *ve; 66 { 67 extern int termwidth, totwidth; 68 VAR *v; 69 70 v = ve->var; 71 if (ve->next == NULL) { 72 /* last field */ 73 if (termwidth == UNLIMITED) { 74 if (k->ki_env) 75 (void)printf("%s ", k->ki_env); 76 (void)printf("%s", k->ki_args); 77 } else { 78 register int left = termwidth - (totwidth - v->width); 79 register char *cp; 80 81 if (left < 1) /* already wrapped, just use std width */ 82 left = v->width; 83 cp = k->ki_env; 84 if (cp != 0) { 85 while (--left >= 0 && *cp) 86 (void)putchar(*cp++); 87 if (--left >= 0) 88 putchar(' '); 89 } 90 cp = k->ki_args; 91 while (--left >= 0 && *cp) 92 (void)putchar(*cp++); 93 } 94 } else 95 /* XXX env? */ 96 (void)printf("%-*.*s", v->width, v->width, k->ki_args); 97 } 98 99 void 100 ucomm(k, ve) 101 KINFO *k; 102 VARENT *ve; 103 { 104 VAR *v; 105 106 v = ve->var; 107 (void)printf("%-*s", v->width, KI_PROC(k)->p_comm); 108 } 109 110 void 111 logname(k, ve) 112 KINFO *k; 113 VARENT *ve; 114 { 115 VAR *v; 116 117 v = ve->var; 118 #ifndef NEWVM 119 (void)printf("%-*s", v->width, KI_PROC(k)->p_logname); 120 #else /* NEWVM */ 121 (void)printf("%-*s", v->width, KI_EPROC(k)->e_login); 122 #endif /* NEWVM */ 123 } 124 125 void 126 state(k, ve) 127 KINFO *k; 128 VARENT *ve; 129 { 130 register struct proc *p; 131 register int flag; 132 register char *cp; 133 VAR *v; 134 char buf[16]; 135 136 v = ve->var; 137 p = KI_PROC(k); 138 flag = p->p_flag; 139 cp = buf; 140 141 switch (p->p_stat) { 142 143 case SSTOP: 144 *cp = 'T'; 145 break; 146 147 case SSLEEP: 148 if (flag & SSINTR) /* interuptable (long) */ 149 *cp = p->p_slptime >= MAXSLP ? 'I' : 'S'; 150 else 151 *cp = 'D'; 152 break; 153 154 case SRUN: 155 case SIDL: 156 *cp = 'R'; 157 break; 158 159 case SZOMB: 160 *cp = 'Z'; 161 break; 162 163 default: 164 *cp = '?'; 165 } 166 cp++; 167 if (flag & SLOAD) { 168 #ifndef NEWVM 169 if (p->p_rssize > p->p_maxrss) 170 *cp++ = '>'; 171 #endif 172 } else 173 *cp++ = 'W'; 174 if (p->p_nice < NZERO) 175 *cp++ = '<'; 176 else if (p->p_nice > NZERO) 177 *cp++ = 'N'; 178 #ifndef NEWVM 179 if (flag & SUANOM) 180 *cp++ = 'A'; 181 else if (flag & SSEQL) 182 *cp++ = 'S'; 183 #endif 184 if (flag & STRC) 185 *cp++ = 'X'; 186 if (flag & SWEXIT && p->p_stat != SZOMB) 187 *cp++ = 'E'; 188 #ifdef NEWVM 189 if (flag & SPPWAIT) 190 #else 191 if (flag & SVFORK) 192 #endif 193 *cp++ = 'V'; 194 #ifdef NEWVM 195 if (flag & (SSYS|SLOCK|SKEEP|SPHYSIO)) 196 #else 197 if (flag & (SSYS|SLOCK|SULOCK|SKEEP|SPHYSIO)) 198 #endif 199 *cp++ = 'L'; 200 if (KI_EPROC(k)->e_flag & EPROC_SLEADER) 201 *cp++ = 's'; 202 if ((flag & SCTTY) && KI_EPROC(k)->e_pgid == KI_EPROC(k)->e_tpgid) 203 *cp++ = '+'; 204 *cp = '\0'; 205 (void)printf("%-*s", v->width, buf); 206 } 207 208 void 209 pri(k, ve) 210 KINFO *k; 211 VARENT *ve; 212 { 213 VAR *v; 214 215 v = ve->var; 216 (void)printf("%*d", v->width, KI_PROC(k)->p_pri - PZERO); 217 } 218 219 void 220 uname(k, ve) 221 KINFO *k; 222 VARENT *ve; 223 { 224 VAR *v; 225 226 v = ve->var; 227 #ifndef NEWVM 228 (void)printf("%-*s", v->width, user_from_uid(KI_PROC(k)->p_uid, 0)); 229 #else /* NEWVM */ 230 (void)printf("%-*s", v->width, 231 user_from_uid(KI_EPROC(k)->e_ucred.cr_uid, 0)); 232 #endif /* NEWVM */ 233 } 234 235 void 236 runame(k, ve) 237 KINFO *k; 238 VARENT *ve; 239 { 240 VAR *v; 241 242 v = ve->var; 243 #ifndef NEWVM 244 (void)printf("%-*s", v->width, user_from_uid(KI_PROC(k)->p_ruid, 0)); 245 #else /* NEWVM */ 246 (void)printf("%-*s", v->width, 247 user_from_uid(KI_EPROC(k)->e_pcred.p_ruid, 0)); 248 #endif /* NEWVM */ 249 } 250 251 void 252 tdev(k, ve) 253 KINFO *k; 254 VARENT *ve; 255 { 256 VAR *v; 257 dev_t dev; 258 char buff[16]; 259 260 v = ve->var; 261 dev = KI_EPROC(k)->e_tdev; 262 if (dev == NODEV) 263 (void)printf("%*s", v->width, "??"); 264 else { 265 (void)snprintf(buff, sizeof(buff), 266 "%d/%d", major(dev), minor(dev)); 267 (void)printf("%*s", v->width, buff); 268 } 269 } 270 271 void 272 tname(k, ve) 273 KINFO *k; 274 VARENT *ve; 275 { 276 VAR *v; 277 dev_t dev; 278 char *ttname; 279 280 v = ve->var; 281 dev = KI_EPROC(k)->e_tdev; 282 if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL) 283 (void)printf("%-*s", v->width, "??"); 284 else { 285 if (strncmp(ttname, "tty", 3) == 0) 286 ttname += 3; 287 (void)printf("%*.*s%c", v->width-1, v->width-1, ttname, 288 KI_EPROC(k)->e_flag & EPROC_CTTY ? ' ' : '-'); 289 } 290 } 291 292 void 293 longtname(k, ve) 294 KINFO *k; 295 VARENT *ve; 296 { 297 VAR *v; 298 dev_t dev; 299 char *ttname; 300 301 v = ve->var; 302 dev = KI_EPROC(k)->e_tdev; 303 if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL) 304 (void)printf("%-*s", v->width, "??"); 305 else 306 (void)printf("%-*s", v->width, ttname); 307 } 308 309 void 310 started(k, ve) 311 KINFO *k; 312 VARENT *ve; 313 { 314 VAR *v; 315 static time_t now; 316 struct tm *tp; 317 char buf[100]; 318 319 v = ve->var; 320 if (!k->ki_u.u_valid) { 321 (void)printf("%-*s", v->width, "-"); 322 return; 323 } 324 325 tp = localtime(&k->ki_u.u_start.tv_sec); 326 if (!now) 327 (void)time(&now); 328 if (now - k->ki_u.u_start.tv_sec < 24 * SECSPERHOUR) { 329 static char fmt[] = "%l:@M%p"; 330 fmt[3] = '%'; /* I *hate* SCCS... */ 331 (void)strftime(buf, sizeof(buf) - 1, fmt, tp); 332 } else if (now - k->ki_u.u_start.tv_sec < 7 * SECSPERDAY) { 333 static char fmt[] = "%a@I%p"; 334 fmt[2] = '%'; /* I *hate* SCCS... */ 335 (void)strftime(buf, sizeof(buf) - 1, fmt, tp); 336 } else 337 (void)strftime(buf, sizeof(buf) - 1, "%e%b%y", tp); 338 (void)printf("%-*s", v->width, buf); 339 } 340 341 void 342 lstarted(k, ve) 343 KINFO *k; 344 VARENT *ve; 345 { 346 VAR *v; 347 char buf[100]; 348 349 v = ve->var; 350 if (!k->ki_u.u_valid) { 351 (void)printf("%-*s", v->width, "-"); 352 return; 353 } 354 (void)strftime(buf, sizeof(buf) -1, "%C", 355 localtime(&k->ki_u.u_start.tv_sec)); 356 (void)printf("%-*s", v->width, buf); 357 } 358 359 void 360 wchan(k, ve) 361 KINFO *k; 362 VARENT *ve; 363 { 364 VAR *v; 365 366 v = ve->var; 367 if (KI_PROC(k)->p_wchan) { 368 if (KI_PROC(k)->p_wmesg) 369 (void)printf("%-*.*s", v->width, v->width, 370 KI_EPROC(k)->e_wmesg); 371 else 372 (void)printf("%-*x", v->width, 373 (int)KI_PROC(k)->p_wchan &~ KERNBASE); 374 } else 375 (void)printf("%-*s", v->width, "-"); 376 } 377 378 #define pgtok(a) (((a)*NBPG)/1024) 379 380 void 381 vsize(k, ve) 382 KINFO *k; 383 VARENT *ve; 384 { 385 VAR *v; 386 387 v = ve->var; 388 (void)printf("%*d", v->width, 389 #ifndef NEWVM 390 pgtok(KI_PROC(k)->p_dsize + KI_PROC(k)->p_ssize + KI_EPROC(k)->e_xsize)); 391 #else /* NEWVM */ 392 pgtok(KI_EPROC(k)->e_vm.vm_dsize + KI_EPROC(k)->e_vm.vm_ssize + 393 KI_EPROC(k)->e_vm.vm_tsize)); 394 #endif /* NEWVM */ 395 } 396 397 void 398 rssize(k, ve) 399 KINFO *k; 400 VARENT *ve; 401 { 402 VAR *v; 403 404 v = ve->var; 405 #ifndef NEWVM 406 (void)printf("%*d", v->width, 407 pgtok(KI_PROC(k)->p_rssize + (KI_EPROC(k)->e_xccount ? 408 (KI_EPROC(k)->e_xrssize / KI_EPROC(k)->e_xccount) : 0))); 409 #else /* NEWVM */ 410 /* XXX don't have info about shared */ 411 (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_vm.vm_rssize)); 412 #endif /* NEWVM */ 413 } 414 415 void 416 p_rssize(k, ve) /* doesn't account for text */ 417 KINFO *k; 418 VARENT *ve; 419 { 420 VAR *v; 421 422 v = ve->var; 423 #ifndef NEWVM 424 (void)printf("%*d", v->width, pgtok(KI_PROC(k)->p_rssize)); 425 #else /* NEWVM */ 426 (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_vm.vm_rssize)); 427 #endif /* NEWVM */ 428 } 429 430 void 431 cputime(k, ve) 432 KINFO *k; 433 VARENT *ve; 434 { 435 extern int sumrusage; 436 VAR *v; 437 long secs; 438 long psecs; /* "parts" of a second. first micro, then centi */ 439 char obuff[128]; 440 441 v = ve->var; 442 if (KI_PROC(k)->p_stat == SZOMB || !k->ki_u.u_valid) { 443 secs = 0; 444 psecs = 0; 445 } else { 446 /* 447 * This counts time spent handling interrupts. We could 448 * fix this, but it is not 100% trivial (and interrupt 449 * time fractions only work on the sparc anyway). XXX 450 */ 451 secs = KI_PROC(k)->p_rtime.tv_sec; 452 psecs = KI_PROC(k)->p_rtime.tv_usec; 453 if (sumrusage) { 454 secs += k->ki_u.u_cru.ru_utime.tv_sec + 455 k->ki_u.u_cru.ru_stime.tv_sec; 456 psecs += k->ki_u.u_cru.ru_utime.tv_usec + 457 k->ki_u.u_cru.ru_stime.tv_usec; 458 } 459 /* 460 * round and scale to 100's 461 */ 462 psecs = (psecs + 5000) / 10000; 463 secs += psecs / 100; 464 psecs = psecs % 100; 465 } 466 (void)snprintf(obuff, sizeof(obuff), 467 "%3ld:%02ld.%02ld", secs/60, secs%60, psecs); 468 (void)printf("%*s", v->width, obuff); 469 } 470 471 double 472 getpcpu(k) 473 KINFO *k; 474 { 475 extern fixpt_t ccpu; 476 extern int fscale, nlistread, rawcpu; 477 struct proc *p; 478 static int failure; 479 480 if (!nlistread) 481 failure = donlist(); 482 if (failure) 483 return (0.0); 484 485 p = KI_PROC(k); 486 #define fxtofl(fixpt) ((double)(fixpt) / fscale) 487 488 /* XXX - I don't like this */ 489 if (p->p_time == 0 || (p->p_flag & SLOAD) == 0) 490 return (0.0); 491 if (rawcpu) 492 return (100.0 * fxtofl(p->p_pctcpu)); 493 return (100.0 * fxtofl(p->p_pctcpu) / 494 (1.0 - exp(p->p_time * log(fxtofl(ccpu))))); 495 } 496 497 void 498 pcpu(k, ve) 499 KINFO *k; 500 VARENT *ve; 501 { 502 VAR *v; 503 504 v = ve->var; 505 (void)printf("%*.1f", v->width, getpcpu(k)); 506 } 507 508 double 509 getpmem(k) 510 KINFO *k; 511 { 512 extern int mempages, nlistread; 513 static int failure; 514 struct proc *p; 515 struct eproc *e; 516 double fracmem; 517 int szptudot; 518 519 if (!nlistread) 520 failure = donlist(); 521 if (failure) 522 return (0.0); 523 524 p = KI_PROC(k); 525 e = KI_EPROC(k); 526 if ((p->p_flag & SLOAD) == 0) 527 return (0.0); 528 #ifndef NEWVM 529 szptudot = UPAGES + clrnd(ctopt(p->p_dsize + p->p_ssize + e->e_xsize)); 530 fracmem = ((float)p->p_rssize + szptudot)/CLSIZE/mempages; 531 if (p->p_textp && e->e_xccount) 532 fracmem += ((float)e->e_xrssize)/CLSIZE/e->e_xccount/mempages; 533 #else /* NEWVM */ 534 /* XXX want pmap ptpages, segtab, etc. (per architecture) */ 535 szptudot = UPAGES; 536 /* XXX don't have info about shared */ 537 fracmem = ((float)e->e_vm.vm_rssize + szptudot)/CLSIZE/mempages; 538 #endif /* NEWVM */ 539 return (100.0 * fracmem); 540 } 541 542 void 543 pmem(k, ve) 544 KINFO *k; 545 VARENT *ve; 546 { 547 VAR *v; 548 549 v = ve->var; 550 (void)printf("%*.1f", v->width, getpmem(k)); 551 } 552 553 void 554 pagein(k, ve) 555 KINFO *k; 556 VARENT *ve; 557 { 558 VAR *v; 559 560 v = ve->var; 561 (void)printf("%*d", v->width, 562 k->ki_u.u_valid ? k->ki_u.u_ru.ru_majflt : 0); 563 } 564 565 void 566 maxrss(k, ve) 567 KINFO *k; 568 VARENT *ve; 569 { 570 VAR *v; 571 572 v = ve->var; 573 #ifndef NEWVM /* not yet */ 574 if (KI_PROC(k)->p_maxrss != (RLIM_INFINITY/NBPG)) 575 (void)printf("%*d", v->width, pgtok(KI_PROC(k)->p_maxrss)); 576 else 577 #endif /* NEWVM */ 578 (void)printf("%*s", v->width, "-"); 579 } 580 581 void 582 tsize(k, ve) 583 KINFO *k; 584 VARENT *ve; 585 { 586 VAR *v; 587 588 v = ve->var; 589 #ifndef NEWVM 590 (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_xsize)); 591 #else /* NEWVM */ 592 (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_vm.vm_tsize)); 593 #endif /* NEWVM */ 594 } 595 596 #ifndef NEWVM 597 void 598 trss(k, ve) 599 KINFO *k; 600 VARENT *ve; 601 { 602 VAR *v; 603 604 v = ve->var; 605 (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_xrssize)); 606 } 607 #endif /* NEWVM */ 608 609 /* 610 * Generic output routines. Print fields from various prototype 611 * structures. 612 */ 613 void 614 pvar(k, ve) 615 KINFO *k; 616 VARENT *ve; 617 { 618 VAR *v; 619 620 v = ve->var; 621 printval((char *)((char *)KI_PROC(k) + v->off), v); 622 } 623 624 void 625 evar(k, ve) 626 KINFO *k; 627 VARENT *ve; 628 { 629 VAR *v; 630 631 v = ve->var; 632 printval((char *)((char *)KI_EPROC(k) + v->off), v); 633 } 634 635 void 636 uvar(k, ve) 637 KINFO *k; 638 VARENT *ve; 639 { 640 VAR *v; 641 642 v = ve->var; 643 if (k->ki_u.u_valid) 644 printval((char *)((char *)&k->ki_u + v->off), v); 645 else 646 (void)printf("%*s", v->width, "-"); 647 } 648 649 void 650 rvar(k, ve) 651 KINFO *k; 652 VARENT *ve; 653 { 654 VAR *v; 655 656 v = ve->var; 657 if (k->ki_u.u_valid) 658 printval((char *)((char *)(&k->ki_u.u_ru) + v->off), v); 659 else 660 (void)printf("%*s", v->width, "-"); 661 } 662 663 static void 664 printval(bp, v) 665 char *bp; 666 VAR *v; 667 { 668 static char ofmt[32] = "%"; 669 register char *fcp, *cp; 670 671 cp = ofmt + 1; 672 fcp = v->fmt; 673 if (v->flag & LJUST) 674 *cp++ = '-'; 675 *cp++ = '*'; 676 while (*cp++ = *fcp++); 677 678 switch (v->type) { 679 case CHAR: 680 (void)printf(ofmt, v->width, *(char *)bp); 681 break; 682 case UCHAR: 683 (void)printf(ofmt, v->width, *(u_char *)bp); 684 break; 685 case SHORT: 686 (void)printf(ofmt, v->width, *(short *)bp); 687 break; 688 case USHORT: 689 (void)printf(ofmt, v->width, *(u_short *)bp); 690 break; 691 case LONG: 692 (void)printf(ofmt, v->width, *(long *)bp); 693 break; 694 case ULONG: 695 (void)printf(ofmt, v->width, *(u_long *)bp); 696 break; 697 case KPTR: 698 (void)printf(ofmt, v->width, *(u_long *)bp &~ KERNBASE); 699 break; 700 default: 701 err("unknown type %d", v->type); 702 } 703 } 704