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.1 (Berkeley) 05/31/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 SPPWAIT 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 /* NEWVM */ 125 (void)printf("%-*s", v->width, KI_EPROC(k)->e_login); 126 #endif /* NEWVM */ 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 & SSINTR) /* 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 & SLOAD) { 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 & STRC) 189 *cp++ = 'X'; 190 if (flag & SWEXIT && p->p_stat != SZOMB) 191 *cp++ = 'E'; 192 #ifdef NEWVM 193 if (flag & SPPWAIT) 194 #else 195 if (flag & SVFORK) 196 #endif 197 *cp++ = 'V'; 198 #ifdef NEWVM 199 if (flag & (SSYS|SLOCK|SKEEP|SPHYSIO)) 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 & SCTTY) && 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_pri - 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 + KI_PROC(k)->p_ssize + KI_EPROC(k)->e_xsize)); 397 #else /* NEWVM */ 398 pgtok(KI_EPROC(k)->e_vm.vm_dsize + KI_EPROC(k)->e_vm.vm_ssize + 399 KI_EPROC(k)->e_vm.vm_tsize)); 400 #endif /* NEWVM */ 401 } 402 403 void 404 rssize(k, ve) 405 KINFO *k; 406 VARENT *ve; 407 { 408 VAR *v; 409 410 v = ve->var; 411 #ifndef NEWVM 412 (void)printf("%*d", v->width, 413 pgtok(KI_PROC(k)->p_rssize + (KI_EPROC(k)->e_xccount ? 414 (KI_EPROC(k)->e_xrssize / KI_EPROC(k)->e_xccount) : 0))); 415 #else /* NEWVM */ 416 /* XXX don't have info about shared */ 417 (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_vm.vm_rssize)); 418 #endif /* NEWVM */ 419 } 420 421 void 422 p_rssize(k, ve) /* doesn't account for text */ 423 KINFO *k; 424 VARENT *ve; 425 { 426 VAR *v; 427 428 v = ve->var; 429 #ifndef NEWVM 430 (void)printf("%*d", v->width, pgtok(KI_PROC(k)->p_rssize)); 431 #else /* NEWVM */ 432 (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_vm.vm_rssize)); 433 #endif /* NEWVM */ 434 } 435 436 void 437 cputime(k, ve) 438 KINFO *k; 439 VARENT *ve; 440 { 441 extern int sumrusage; 442 VAR *v; 443 long secs; 444 long psecs; /* "parts" of a second. first micro, then centi */ 445 char obuff[128]; 446 447 v = ve->var; 448 if (KI_PROC(k)->p_stat == SZOMB || !k->ki_u.u_valid) { 449 secs = 0; 450 psecs = 0; 451 } else { 452 /* 453 * This counts time spent handling interrupts. We could 454 * fix this, but it is not 100% trivial (and interrupt 455 * time fractions only work on the sparc anyway). XXX 456 */ 457 secs = KI_PROC(k)->p_rtime.tv_sec; 458 psecs = KI_PROC(k)->p_rtime.tv_usec; 459 if (sumrusage) { 460 secs += k->ki_u.u_cru.ru_utime.tv_sec + 461 k->ki_u.u_cru.ru_stime.tv_sec; 462 psecs += k->ki_u.u_cru.ru_utime.tv_usec + 463 k->ki_u.u_cru.ru_stime.tv_usec; 464 } 465 /* 466 * round and scale to 100's 467 */ 468 psecs = (psecs + 5000) / 10000; 469 secs += psecs / 100; 470 psecs = psecs % 100; 471 } 472 (void)snprintf(obuff, sizeof(obuff), 473 "%3ld:%02ld.%02ld", secs/60, secs%60, psecs); 474 (void)printf("%*s", v->width, obuff); 475 } 476 477 double 478 getpcpu(k) 479 KINFO *k; 480 { 481 extern fixpt_t ccpu; 482 extern int fscale, nlistread, rawcpu; 483 struct proc *p; 484 static int failure; 485 486 if (!nlistread) 487 failure = donlist(); 488 if (failure) 489 return (0.0); 490 491 p = KI_PROC(k); 492 #define fxtofl(fixpt) ((double)(fixpt) / fscale) 493 494 /* XXX - I don't like this */ 495 if (p->p_time == 0 || (p->p_flag & SLOAD) == 0) 496 return (0.0); 497 if (rawcpu) 498 return (100.0 * fxtofl(p->p_pctcpu)); 499 return (100.0 * fxtofl(p->p_pctcpu) / 500 (1.0 - exp(p->p_time * log(fxtofl(ccpu))))); 501 } 502 503 void 504 pcpu(k, ve) 505 KINFO *k; 506 VARENT *ve; 507 { 508 VAR *v; 509 510 v = ve->var; 511 (void)printf("%*.1f", v->width, getpcpu(k)); 512 } 513 514 double 515 getpmem(k) 516 KINFO *k; 517 { 518 extern int mempages, nlistread; 519 static int failure; 520 struct proc *p; 521 struct eproc *e; 522 double fracmem; 523 int szptudot; 524 525 if (!nlistread) 526 failure = donlist(); 527 if (failure) 528 return (0.0); 529 530 p = KI_PROC(k); 531 e = KI_EPROC(k); 532 if ((p->p_flag & SLOAD) == 0) 533 return (0.0); 534 #ifndef NEWVM 535 szptudot = UPAGES + clrnd(ctopt(p->p_dsize + p->p_ssize + e->e_xsize)); 536 fracmem = ((float)p->p_rssize + szptudot)/CLSIZE/mempages; 537 if (p->p_textp && e->e_xccount) 538 fracmem += ((float)e->e_xrssize)/CLSIZE/e->e_xccount/mempages; 539 #else /* NEWVM */ 540 /* XXX want pmap ptpages, segtab, etc. (per architecture) */ 541 szptudot = UPAGES; 542 /* XXX don't have info about shared */ 543 fracmem = ((float)e->e_vm.vm_rssize + szptudot)/CLSIZE/mempages; 544 #endif /* NEWVM */ 545 return (100.0 * fracmem); 546 } 547 548 void 549 pmem(k, ve) 550 KINFO *k; 551 VARENT *ve; 552 { 553 VAR *v; 554 555 v = ve->var; 556 (void)printf("%*.1f", v->width, getpmem(k)); 557 } 558 559 void 560 pagein(k, ve) 561 KINFO *k; 562 VARENT *ve; 563 { 564 VAR *v; 565 566 v = ve->var; 567 (void)printf("%*d", v->width, 568 k->ki_u.u_valid ? k->ki_u.u_ru.ru_majflt : 0); 569 } 570 571 void 572 maxrss(k, ve) 573 KINFO *k; 574 VARENT *ve; 575 { 576 VAR *v; 577 578 v = ve->var; 579 #ifndef NEWVM /* not yet */ 580 if (KI_PROC(k)->p_maxrss != (RLIM_INFINITY/NBPG)) 581 (void)printf("%*d", v->width, pgtok(KI_PROC(k)->p_maxrss)); 582 else 583 #endif /* NEWVM */ 584 (void)printf("%*s", v->width, "-"); 585 } 586 587 void 588 tsize(k, ve) 589 KINFO *k; 590 VARENT *ve; 591 { 592 VAR *v; 593 594 v = ve->var; 595 #ifndef NEWVM 596 (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_xsize)); 597 #else /* NEWVM */ 598 (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_vm.vm_tsize)); 599 #endif /* NEWVM */ 600 } 601 602 #ifndef NEWVM 603 void 604 trss(k, ve) 605 KINFO *k; 606 VARENT *ve; 607 { 608 VAR *v; 609 610 v = ve->var; 611 (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_xrssize)); 612 } 613 #endif /* NEWVM */ 614 615 /* 616 * Generic output routines. Print fields from various prototype 617 * structures. 618 */ 619 void 620 pvar(k, ve) 621 KINFO *k; 622 VARENT *ve; 623 { 624 VAR *v; 625 626 v = ve->var; 627 printval((char *)((char *)KI_PROC(k) + v->off), v); 628 } 629 630 void 631 evar(k, ve) 632 KINFO *k; 633 VARENT *ve; 634 { 635 VAR *v; 636 637 v = ve->var; 638 printval((char *)((char *)KI_EPROC(k) + v->off), v); 639 } 640 641 void 642 uvar(k, ve) 643 KINFO *k; 644 VARENT *ve; 645 { 646 VAR *v; 647 648 v = ve->var; 649 if (k->ki_u.u_valid) 650 printval((char *)((char *)&k->ki_u + v->off), v); 651 else 652 (void)printf("%*s", v->width, "-"); 653 } 654 655 void 656 rvar(k, ve) 657 KINFO *k; 658 VARENT *ve; 659 { 660 VAR *v; 661 662 v = ve->var; 663 if (k->ki_u.u_valid) 664 printval((char *)((char *)(&k->ki_u.u_ru) + v->off), v); 665 else 666 (void)printf("%*s", v->width, "-"); 667 } 668 669 static void 670 printval(bp, v) 671 char *bp; 672 VAR *v; 673 { 674 static char ofmt[32] = "%"; 675 register char *fcp, *cp; 676 677 cp = ofmt + 1; 678 fcp = v->fmt; 679 if (v->flag & LJUST) 680 *cp++ = '-'; 681 *cp++ = '*'; 682 while (*cp++ = *fcp++); 683 684 switch (v->type) { 685 case CHAR: 686 (void)printf(ofmt, v->width, *(char *)bp); 687 break; 688 case UCHAR: 689 (void)printf(ofmt, v->width, *(u_char *)bp); 690 break; 691 case SHORT: 692 (void)printf(ofmt, v->width, *(short *)bp); 693 break; 694 case USHORT: 695 (void)printf(ofmt, v->width, *(u_short *)bp); 696 break; 697 case LONG: 698 (void)printf(ofmt, v->width, *(long *)bp); 699 break; 700 case ULONG: 701 (void)printf(ofmt, v->width, *(u_long *)bp); 702 break; 703 case KPTR: 704 (void)printf(ofmt, v->width, *(u_long *)bp &~ KERNBASE); 705 break; 706 default: 707 errx(1, "unknown type %d", v->type); 708 } 709 } 710