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