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