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