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.11 (Berkeley) 06/05/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 = (flag & SPAGE) ? 'P' : '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 303 dev = KI_EPROC(k)->e_tdev; 304 if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL) 305 (void)printf("%-*s", v->width, "??"); 306 else 307 (void)printf("%-*s", v->width, ttname); 308 } 309 310 void 311 started(k, ve) 312 KINFO *k; 313 VARENT *ve; 314 { 315 VAR *v; 316 static time_t now; 317 struct tm *tp; 318 char buf[100]; 319 320 v = ve->var; 321 if (!k->ki_u.u_valid) { 322 (void)printf("%-*s", v->width, "-"); 323 return; 324 } 325 326 tp = localtime(&k->ki_u.u_start.tv_sec); 327 if (!now) 328 (void)time(&now); 329 if (now - k->ki_u.u_start.tv_sec < 24 * SECSPERHOUR) { 330 static char fmt[] = "%l:@M%p"; 331 fmt[3] = '%'; /* I *hate* SCCS... */ 332 (void)strftime(buf, sizeof(buf) - 1, fmt, tp); 333 } else if (now - k->ki_u.u_start.tv_sec < 7 * SECSPERDAY) { 334 static char fmt[] = "%a@I%p"; 335 fmt[2] = '%'; /* I *hate* SCCS... */ 336 (void)strftime(buf, sizeof(buf) - 1, fmt, tp); 337 } else 338 (void)strftime(buf, sizeof(buf) - 1, "%e%b%y", tp); 339 (void)printf("%-*s", v->width, buf); 340 } 341 342 void 343 lstarted(k, ve) 344 KINFO *k; 345 VARENT *ve; 346 { 347 VAR *v; 348 char buf[100]; 349 350 v = ve->var; 351 352 if (!k->ki_u.u_valid) { 353 (void)printf("%-*s", v->width, "-"); 354 return; 355 } 356 (void)strftime(buf, sizeof(buf) -1, "%C", 357 localtime(&k->ki_u.u_start.tv_sec)); 358 (void)printf("%-*s", v->width, buf); 359 } 360 361 void 362 wchan(k, ve) 363 KINFO *k; 364 VARENT *ve; 365 { 366 VAR *v; 367 368 v = ve->var; 369 if (KI_PROC(k)->p_wchan) { 370 if (KI_PROC(k)->p_wmesg) 371 (void)printf("%-*.*s", v->width, v->width, 372 KI_EPROC(k)->e_wmesg); 373 else 374 (void)printf("%-*x", v->width, 375 (int)KI_PROC(k)->p_wchan &~ KERNBASE); 376 } else 377 (void)printf("%-*s", v->width, "-"); 378 } 379 380 #define pgtok(a) (((a)*NBPG)/1024) 381 382 void 383 vsize(k, ve) 384 KINFO *k; 385 VARENT *ve; 386 { 387 VAR *v; 388 389 v = ve->var; 390 (void)printf("%*d", v->width, 391 #ifndef NEWVM 392 pgtok(KI_PROC(k)->p_dsize + KI_PROC(k)->p_ssize + KI_EPROC(k)->e_xsize)); 393 #else /* NEWVM */ 394 pgtok(KI_EPROC(k)->e_vm.vm_dsize + KI_EPROC(k)->e_vm.vm_ssize + 395 KI_EPROC(k)->e_vm.vm_tsize)); 396 #endif /* NEWVM */ 397 } 398 399 void 400 rssize(k, ve) 401 KINFO *k; 402 VARENT *ve; 403 { 404 VAR *v; 405 406 v = ve->var; 407 #ifndef NEWVM 408 (void)printf("%*d", v->width, 409 pgtok(KI_PROC(k)->p_rssize + (KI_EPROC(k)->e_xccount ? 410 (KI_EPROC(k)->e_xrssize / KI_EPROC(k)->e_xccount) : 0))); 411 #else /* NEWVM */ 412 /* XXX don't have info about shared */ 413 (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_vm.vm_rssize)); 414 #endif /* NEWVM */ 415 } 416 417 void 418 p_rssize(k, ve) /* doesn't account for text */ 419 KINFO *k; 420 VARENT *ve; 421 { 422 VAR *v; 423 424 v = ve->var; 425 #ifndef NEWVM 426 (void)printf("%*d", v->width, pgtok(KI_PROC(k)->p_rssize)); 427 #else /* NEWVM */ 428 (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_vm.vm_rssize)); 429 #endif /* NEWVM */ 430 } 431 432 void 433 cputime(k, ve) 434 KINFO *k; 435 VARENT *ve; 436 { 437 extern int sumrusage; 438 VAR *v; 439 long secs; 440 long psecs; /* "parts" of a second. first micro, then centi */ 441 char obuff[128]; 442 443 v = ve->var; 444 if (KI_PROC(k)->p_stat == SZOMB || !k->ki_u.u_valid) { 445 secs = 0; 446 psecs = 0; 447 } else { 448 secs = KI_PROC(k)->p_utime.tv_sec + 449 KI_PROC(k)->p_stime.tv_sec; 450 psecs = KI_PROC(k)->p_utime.tv_usec + 451 KI_PROC(k)->p_stime.tv_usec; 452 if (sumrusage) { 453 secs += k->ki_u.u_cru.ru_utime.tv_sec + 454 k->ki_u.u_cru.ru_stime.tv_sec; 455 psecs += k->ki_u.u_cru.ru_utime.tv_usec + 456 k->ki_u.u_cru.ru_stime.tv_usec; 457 } 458 /* 459 * round and scale to 100's 460 */ 461 psecs = (psecs + 5000) / 10000; 462 secs += psecs / 100; 463 psecs = psecs % 100; 464 } 465 (void)snprintf(obuff, sizeof(obuff), 466 "%3ld:%02ld.%02ld", secs/60, secs%60, psecs); 467 (void)printf("%*s", v->width, obuff); 468 } 469 470 double 471 getpcpu(k) 472 KINFO *k; 473 { 474 extern fixpt_t ccpu; 475 extern int fscale, nlistread, rawcpu; 476 struct proc *p; 477 static int failure; 478 479 if (!nlistread) 480 failure = donlist(); 481 if (failure) 482 return (0.0); 483 484 p = KI_PROC(k); 485 #define fxtofl(fixpt) ((double)(fixpt) / fscale) 486 487 /* XXX - I don't like this */ 488 if (p->p_time == 0 || (p->p_flag & SLOAD) == 0) 489 return (0.0); 490 if (rawcpu) 491 return (100.0 * fxtofl(p->p_pctcpu)); 492 return (100.0 * fxtofl(p->p_pctcpu) / 493 (1.0 - exp(p->p_time * log(fxtofl(ccpu))))); 494 } 495 496 void 497 pcpu(k, ve) 498 KINFO *k; 499 VARENT *ve; 500 { 501 VAR *v; 502 503 v = ve->var; 504 (void)printf("%*.1f", v->width, getpcpu(k)); 505 } 506 507 double 508 getpmem(k) 509 KINFO *k; 510 { 511 extern int mempages, nlistread; 512 static int failure; 513 struct proc *p; 514 struct eproc *e; 515 double fracmem; 516 int szptudot; 517 518 if (!nlistread) 519 failure = donlist(); 520 if (failure) 521 return (0.0); 522 523 p = KI_PROC(k); 524 e = KI_EPROC(k); 525 if ((p->p_flag & SLOAD) == 0) 526 return (0.0); 527 #ifndef NEWVM 528 szptudot = UPAGES + clrnd(ctopt(p->p_dsize + p->p_ssize + e->e_xsize)); 529 fracmem = ((float)p->p_rssize + szptudot)/CLSIZE/mempages; 530 if (p->p_textp && e->e_xccount) 531 fracmem += ((float)e->e_xrssize)/CLSIZE/e->e_xccount/mempages; 532 #else /* NEWVM */ 533 /* XXX want pmap ptpages, segtab, etc. (per architecture) */ 534 szptudot = UPAGES; 535 /* XXX don't have info about shared */ 536 fracmem = ((float)e->e_vm.vm_rssize + szptudot)/CLSIZE/mempages; 537 #endif /* NEWVM */ 538 return (100.0 * fracmem); 539 } 540 541 void 542 pmem(k, ve) 543 KINFO *k; 544 VARENT *ve; 545 { 546 VAR *v; 547 548 v = ve->var; 549 (void)printf("%*.1f", v->width, getpmem(k)); 550 } 551 552 void 553 pagein(k, ve) 554 KINFO *k; 555 VARENT *ve; 556 { 557 VAR *v; 558 559 v = ve->var; 560 (void)printf("%*d", v->width, 561 k->ki_u.u_valid ? k->ki_u.u_ru.ru_majflt : 0); 562 } 563 564 void 565 maxrss(k, ve) 566 KINFO *k; 567 VARENT *ve; 568 { 569 VAR *v; 570 571 v = ve->var; 572 #ifndef NEWVM /* not yet */ 573 if (KI_PROC(k)->p_maxrss != (RLIM_INFINITY/NBPG)) 574 (void)printf("%*d", v->width, pgtok(KI_PROC(k)->p_maxrss)); 575 else 576 #endif /* NEWVM */ 577 (void)printf("%*s", v->width, "-"); 578 } 579 580 void 581 tsize(k, ve) 582 KINFO *k; 583 VARENT *ve; 584 { 585 VAR *v; 586 587 v = ve->var; 588 #ifndef NEWVM 589 (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_xsize)); 590 #else /* NEWVM */ 591 (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_vm.vm_tsize)); 592 #endif /* NEWVM */ 593 } 594 595 #ifndef NEWVM 596 void 597 trss(k, ve) 598 KINFO *k; 599 VARENT *ve; 600 { 601 VAR *v; 602 603 v = ve->var; 604 (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_xrssize)); 605 } 606 #endif /* NEWVM */ 607 608 /* 609 * Generic output routines. Print fields from various prototype 610 * structures. 611 */ 612 void 613 pvar(k, ve) 614 KINFO *k; 615 VARENT *ve; 616 { 617 VAR *v; 618 619 v = ve->var; 620 printval((char *)((char *)KI_PROC(k) + v->off), v); 621 } 622 623 void 624 evar(k, ve) 625 KINFO *k; 626 VARENT *ve; 627 { 628 VAR *v; 629 630 v = ve->var; 631 printval((char *)((char *)KI_EPROC(k) + v->off), v); 632 } 633 634 void 635 uvar(k, ve) 636 KINFO *k; 637 VARENT *ve; 638 { 639 VAR *v; 640 641 v = ve->var; 642 if (k->ki_u.u_valid) 643 printval((char *)((char *)&k->ki_u + v->off), v); 644 else 645 (void)printf("%*s", v->width, "-"); 646 } 647 648 void 649 rvar(k, ve) 650 KINFO *k; 651 VARENT *ve; 652 { 653 VAR *v; 654 655 v = ve->var; 656 if (k->ki_u.u_valid) 657 printval((char *)((char *)(&k->ki_u.u_ru) + v->off), v); 658 else 659 (void)printf("%*s", v->width, "-"); 660 } 661 662 static void 663 printval(bp, v) 664 char *bp; 665 VAR *v; 666 { 667 static char ofmt[32] = "%"; 668 register char *fcp, *cp; 669 670 cp = ofmt + 1; 671 fcp = v->fmt; 672 if (v->flag & LJUST) 673 *cp++ = '-'; 674 *cp++ = '*'; 675 while (*cp++ = *fcp++); 676 677 switch (v->type) { 678 case CHAR: 679 (void)printf(ofmt, v->width, *(char *)bp); 680 break; 681 case UCHAR: 682 (void)printf(ofmt, v->width, *(u_char *)bp); 683 break; 684 case SHORT: 685 (void)printf(ofmt, v->width, *(short *)bp); 686 break; 687 case USHORT: 688 (void)printf(ofmt, v->width, *(u_short *)bp); 689 break; 690 case LONG: 691 (void)printf(ofmt, v->width, *(long *)bp); 692 break; 693 case ULONG: 694 (void)printf(ofmt, v->width, *(u_long *)bp); 695 break; 696 case KPTR: 697 (void)printf(ofmt, v->width, *(u_long *)bp &~ KERNBASE); 698 break; 699 default: 700 err("unknown type %d", v->type); 701 } 702 } 703