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