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