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