1 /*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 static char sccsid[] = "@(#)print.c 5.9 (Berkeley) 7/1/91"; 36 static char rcsid[] = "$Header: /cvsroot/src/bin/ps/print.c,v 1.7 1993/06/18 09:32:27 cgd Exp $"; 37 #endif /* not lint */ 38 39 #include <sys/param.h> 40 #include <sys/time.h> 41 #include <sys/resource.h> 42 #include <sys/proc.h> 43 #include <sys/stat.h> 44 #include <math.h> 45 #include <tzfile.h> 46 #include <stddef.h> 47 #include <string.h> 48 #include <vis.h> 49 #include "ps.h" 50 51 #ifdef SPPWAIT 52 #define NEWVM 53 #endif 54 55 #ifdef NEWVM 56 #include <vm/vm.h> 57 #include <sys/ucred.h> 58 #include <sys/kinfo_proc.h> 59 #else 60 #include <machine/pte.h> 61 #include <sys/vmparam.h> 62 #include <sys/vm.h> 63 #endif 64 65 printheader() 66 { 67 register VAR *v; 68 register struct varent *vent; 69 70 for (vent = vhead; vent; vent = vent->next) { 71 v = vent->var; 72 if (v->flag & LJUST) { 73 if (vent->next == NULL) /* last one */ 74 (void) printf("%s", v->header); 75 else 76 (void) printf("%-*s", v->width, v->header); 77 } else 78 (void) printf("%*s", v->width, v->header); 79 if (vent->next != NULL) 80 (void) putchar(' '); 81 } 82 (void) putchar('\n'); 83 } 84 85 command(k, v, next) 86 KINFO *k; 87 VAR *v; 88 { 89 extern int termwidth, totwidth; 90 char *vis_env, *vis_args; 91 92 vis_args = (char *)malloc(strlen(k->ki_args)*4 + 1); 93 if (vis_args == NULL) 94 err("out of memory"); 95 strvis(vis_args, k->ki_args, VIS_TAB|VIS_NL|VIS_NOSLASH); 96 97 if (k->ki_env) { 98 vis_env = (char *)malloc(strlen(k->ki_env)*4 + 1); 99 if (vis_env == NULL) 100 err("out of memory"); 101 strvis(vis_env, k->ki_env, VIS_TAB|VIS_NL|VIS_NOSLASH); 102 } else { 103 vis_env = NULL; 104 } 105 106 if (next == NULL) { 107 /* last field */ 108 if (termwidth == UNLIMITED) { 109 if (vis_env) 110 (void)printf("%s ", vis_env); 111 (void) printf("%s", vis_args); 112 } else { 113 register int left = termwidth - (totwidth - v->width); 114 register char *cp; 115 116 if (left < 1) /* already wrapped, just use std width */ 117 left = v->width; 118 cp = vis_env; 119 if (cp != 0) { 120 while (--left >= 0 && *cp) 121 (void)putchar(*cp++); 122 if (--left >= 0) 123 putchar(' '); 124 } 125 cp = vis_args; 126 while (--left >= 0 && *cp) 127 (void) putchar(*cp++); 128 } 129 } else 130 /* XXX environment strings? */ 131 (void) printf("%-*.*s", v->width, v->width, vis_args); 132 133 free(vis_args); 134 if (vis_env != NULL) 135 free(vis_env); 136 } 137 138 ucomm(k, v) 139 KINFO *k; 140 VAR *v; 141 { 142 (void) printf("%-*s", v->width, k->ki_p->p_comm); 143 } 144 145 logname(k, v) 146 KINFO *k; 147 VAR *v; 148 { 149 #ifndef NEWVM 150 (void) printf("%-*s", v->width, k->ki_p->p_logname); 151 #else /* NEWVM */ 152 (void) printf("%-*s", v->width, k->ki_e->e_login); 153 #endif /* NEWVM */ 154 } 155 156 state(k, v) 157 KINFO *k; 158 VAR *v; 159 { 160 char buf[16]; 161 register char *cp = buf; 162 register struct proc *p = k->ki_p; 163 register flag = p->p_flag; 164 165 switch (p->p_stat) { 166 167 case SSTOP: 168 *cp = 'T'; 169 break; 170 171 case SSLEEP: 172 if (flag & SSINTR) /* interuptable (long) */ 173 *cp = p->p_slptime >= MAXSLP ? 'I' : 'S'; 174 else 175 *cp = (flag & SPAGE) ? 'P' : 'D'; 176 break; 177 178 case SRUN: 179 case SIDL: 180 *cp = 'R'; 181 break; 182 183 case SZOMB: 184 *cp = 'Z'; 185 break; 186 187 default: 188 *cp = '?'; 189 } 190 cp++; 191 if (flag & SLOAD) { 192 #ifndef NEWVM 193 if (p->p_rssize > p->p_maxrss) 194 *cp++ = '>'; 195 #endif 196 } else 197 *cp++ = 'W'; 198 if (p->p_nice < NZERO) 199 *cp++ = '<'; 200 else if (p->p_nice > NZERO) 201 *cp++ = 'N'; 202 #ifndef NEWVM 203 if (flag & SUANOM) 204 *cp++ = 'A'; 205 else if (flag & SSEQL) 206 *cp++ = 'S'; 207 #endif 208 if (flag & STRC) 209 *cp++ = 'X'; 210 if (flag & SWEXIT && p->p_stat != SZOMB) 211 *cp++ = 'E'; 212 #ifdef NEWVM 213 if (flag & SPPWAIT) 214 #else 215 if (flag & SVFORK) 216 #endif 217 *cp++ = 'V'; 218 #ifdef NEWVM 219 if (flag & (SSYS|SLOCK|SKEEP|SPHYSIO)) 220 #else 221 if (flag & (SSYS|SLOCK|SULOCK|SKEEP|SPHYSIO)) 222 #endif 223 *cp++ = 'L'; 224 if (k->ki_e->e_flag & EPROC_SLEADER) 225 *cp++ = 's'; 226 if ((flag & SCTTY) && k->ki_e->e_pgid == k->ki_e->e_tpgid) 227 *cp++ = '+'; 228 *cp = '\0'; 229 (void) printf("%-*s", v->width, buf); 230 } 231 232 pri(k, v) 233 KINFO *k; 234 VAR *v; 235 { 236 (void) printf("%*d", v->width, k->ki_p->p_pri - PZERO); 237 } 238 239 uname(k, v) 240 KINFO *k; 241 VAR *v; 242 { 243 #ifndef NEWVM 244 (void) printf("%-*s", v->width, user_from_uid(k->ki_p->p_uid, 0)); 245 #else /* NEWVM */ 246 (void) printf("%-*s", v->width, 247 user_from_uid(k->ki_e->e_ucred.cr_uid, 0)); 248 #endif /* NEWVM */ 249 } 250 251 runame(k, v) 252 KINFO *k; 253 VAR *v; 254 { 255 #ifndef NEWVM 256 (void) printf("%-*s", v->width, user_from_uid(k->ki_p->p_ruid, 0)); 257 #else /* NEWVM */ 258 (void) printf("%-*s", v->width, 259 user_from_uid(k->ki_e->e_pcred.p_ruid, 0)); 260 #endif /* NEWVM */ 261 } 262 263 tdev(k, v) 264 KINFO *k; 265 VAR *v; 266 { 267 dev_t dev = k->ki_e->e_tdev; 268 269 if (dev == NODEV) 270 (void) printf("%*s", v->width, "??"); 271 else { 272 char buff[16]; 273 274 (void) sprintf(buff, "%d/%d", major(dev), minor(dev)); 275 (void) printf("%*s", v->width, buff); 276 } 277 } 278 279 tname(k, v) 280 KINFO *k; 281 VAR *v; 282 { 283 dev_t dev; 284 char *ttname, *devname(); 285 286 dev = k->ki_e->e_tdev; 287 if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL) 288 (void) printf("%-*s", v->width, "??"); 289 else { 290 if (strncmp(ttname, "tty", 3) == 0) 291 ttname += 3; 292 (void) printf("%*.*s%c", v->width-1, v->width-1, ttname, 293 k->ki_e->e_flag & EPROC_CTTY ? ' ' : '-'); 294 } 295 } 296 297 longtname(k, v) 298 KINFO *k; 299 VAR *v; 300 { 301 dev_t dev; 302 char *ttname, *devname(); 303 304 dev = k->ki_e->e_tdev; 305 if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL) 306 (void) printf("%-*s", v->width, "??"); 307 else 308 (void) printf("%-*s", v->width, ttname); 309 } 310 311 started(k, v) 312 KINFO *k; 313 VAR *v; 314 { 315 static time_t now; 316 struct tm *tp; 317 char buf[100]; 318 319 if (!k->ki_u) { 320 (void) printf("%-*s", v->width, "-"); 321 return; 322 } 323 324 tp = localtime(&k->ki_u->u_start.tv_sec); 325 if (!now) 326 (void)time(&now); 327 if (now - k->ki_u->u_start.tv_sec < 24 * SECSPERHOUR) { 328 static char fmt[] = "%l:@M%p"; 329 fmt[3] = '%'; /* I *hate* SCCS... */ 330 (void) strftime(buf, sizeof(buf) - 1, fmt, tp); 331 } else if (now - k->ki_u->u_start.tv_sec < 7 * SECSPERDAY) { 332 static char fmt[] = "%a@I%p"; 333 fmt[2] = '%'; /* I *hate* SCCS... */ 334 (void) strftime(buf, sizeof(buf) - 1, fmt, tp); 335 } else 336 (void) strftime(buf, sizeof(buf) - 1, "%e%b%y", tp); 337 (void) printf("%-*s", v->width, buf); 338 } 339 340 lstarted(k, v) 341 KINFO *k; 342 VAR *v; 343 { 344 char buf[100]; 345 346 if (!k->ki_u) { 347 (void) printf("%-*s", v->width, "-"); 348 return; 349 } 350 (void) strftime(buf, sizeof(buf) -1, "%C", 351 localtime(&k->ki_u->u_start.tv_sec)); 352 (void) printf("%-*s", v->width, buf); 353 } 354 355 wchan(k, v) 356 KINFO *k; 357 VAR *v; 358 { 359 if (k->ki_p->p_wchan) { 360 if (k->ki_p->p_wmesg) 361 (void) printf("%-*.*s", v->width, v->width, k->ki_e->e_wmesg); 362 else 363 (void) printf("%-*x", v->width, 364 (int)k->ki_p->p_wchan &~ KERNBASE); 365 } else 366 (void) printf("%-*s", v->width, "-"); 367 } 368 369 #define pgtok(a) (((a)*NBPG)/1024) 370 371 vsize(k, v) 372 KINFO *k; 373 VAR *v; 374 { 375 (void) printf("%*d", v->width, 376 #ifndef NEWVM 377 pgtok(k->ki_p->p_dsize + k->ki_p->p_ssize + k->ki_e->e_xsize)); 378 #else /* NEWVM */ 379 (k->ki_p->p_stat == SZOMB ? 0 : 380 pgtok(k->ki_e->e_vm.vm_dsize + k->ki_e->e_vm.vm_ssize + 381 k->ki_e->e_vm.vm_tsize))); 382 #endif /* NEWVM */ 383 } 384 385 rssize(k, v) 386 KINFO *k; 387 VAR *v; 388 { 389 #ifndef NEWVM 390 (void) printf("%*d", v->width, 391 pgtok(k->ki_p->p_rssize + (k->ki_e->e_xccount ? 392 (k->ki_e->e_xrssize / k->ki_e->e_xccount) : 0))); 393 #else /* NEWVM */ 394 /* XXX don't have info about shared */ 395 (void) printf("%*d", v->width, (k->ki_p->p_stat == SZOMB ? 0 : 396 pgtok(k->ki_e->e_vm.vm_rssize))); 397 #endif /* NEWVM */ 398 } 399 400 p_rssize(k, v) /* doesn't account for text */ 401 KINFO *k; 402 VAR *v; 403 { 404 #ifndef NEWVM 405 (void) printf("%*d", v->width, pgtok(k->ki_p->p_rssize)); 406 #else /* NEWVM */ 407 (void) printf("%*d", v->width, pgtok(k->ki_e->e_vm.vm_rssize)); 408 #endif /* NEWVM */ 409 } 410 411 cputime(k, v) 412 KINFO *k; 413 VAR *v; 414 { 415 extern int sumrusage; 416 long secs; 417 long psecs; /* "parts" of a second. first micro, then centi */ 418 char obuff[128]; 419 420 if (k->ki_p->p_stat == SZOMB || k->ki_u == NULL) { 421 secs = 0; 422 psecs = 0; 423 } else { 424 secs = k->ki_p->p_utime.tv_sec + 425 k->ki_p->p_stime.tv_sec; 426 psecs = k->ki_p->p_utime.tv_usec + 427 k->ki_p->p_stime.tv_usec; 428 if (sumrusage) { 429 secs += k->ki_u->u_cru.ru_utime.tv_sec + 430 k->ki_u->u_cru.ru_stime.tv_sec; 431 psecs += k->ki_u->u_cru.ru_utime.tv_usec + 432 k->ki_u->u_cru.ru_stime.tv_usec; 433 } 434 /* 435 * round and scale to 100's 436 */ 437 psecs = (psecs + 5000) / 10000; 438 secs += psecs / 100; 439 psecs = psecs % 100; 440 } 441 (void) sprintf(obuff, "%3ld:%02ld.%02ld", secs/60, secs%60, psecs); 442 (void) printf("%*s", v->width, obuff); 443 } 444 445 double 446 getpcpu(k) 447 KINFO *k; 448 { 449 extern fixpt_t ccpu; 450 extern int fscale, nlistread, rawcpu; 451 struct proc *p; 452 static int failure; 453 454 if (!nlistread) 455 failure = donlist(); 456 if (failure) 457 return (0.0); 458 459 p = k->ki_p; 460 #define fxtofl(fixpt) ((double)(fixpt) / fscale) 461 462 /* XXX - I don't like this */ 463 if (p->p_time == 0 || (p->p_stat & SZOMB) || (p->p_flag & SLOAD) == 0) 464 return (0.0); 465 if (rawcpu) 466 return (100.0 * fxtofl(p->p_pctcpu)); 467 return (100.0 * fxtofl(p->p_pctcpu) / 468 (1.0 - exp(p->p_time * log(fxtofl(ccpu))))); 469 } 470 471 pcpu(k, v) 472 KINFO *k; 473 VAR *v; 474 { 475 (void) printf("%*.1f", v->width, getpcpu(k)); 476 } 477 478 double 479 getpmem(k) 480 KINFO *k; 481 { 482 extern int mempages, nlistread; 483 static int failure; 484 struct proc *p; 485 struct eproc *e; 486 double fracmem; 487 int szptudot; 488 489 if (!nlistread) 490 failure = donlist(); 491 if (failure) 492 return (0.0); 493 494 p = k->ki_p; 495 e = k->ki_e; 496 if ((p->p_flag & SLOAD) == 0 || (p->p_stat == SZOMB)) 497 return (0.0); 498 #ifndef NEWVM 499 szptudot = UPAGES + clrnd(ctopt(p->p_dsize + p->p_ssize + e->e_xsize)); 500 fracmem = ((float)p->p_rssize + szptudot)/CLSIZE/mempages; 501 if (p->p_textp && e->e_xccount) 502 fracmem += ((float)e->e_xrssize)/CLSIZE/e->e_xccount/mempages; 503 #else /* NEWVM */ 504 /* XXX want pmap ptpages, segtab, etc. (per architecture) */ 505 szptudot = UPAGES; 506 /* XXX don't have info about shared */ 507 fracmem = ((float)e->e_vm.vm_rssize + szptudot)/CLSIZE/mempages; 508 #endif /* NEWVM */ 509 return (100.0 * fracmem); 510 } 511 512 pmem(k, v) 513 KINFO *k; 514 VAR *v; 515 { 516 (void) printf("%*.1f", v->width, getpmem(k)); 517 } 518 519 pagein(k, v) 520 KINFO *k; 521 VAR *v; 522 { 523 (void) printf("%*d", v->width, k->ki_u ? k->ki_u->u_ru.ru_majflt : 0); 524 } 525 526 maxrss(k, v) 527 KINFO *k; 528 VAR *v; 529 { 530 #ifndef NEWVM /* not yet */ 531 if (k->ki_p->p_maxrss != (RLIM_INFINITY/NBPG)) 532 (void) printf("%*d", v->width, pgtok(k->ki_p->p_maxrss)); 533 else 534 #endif /* NEWVM */ 535 (void) printf("%*s", v->width, "-"); 536 } 537 538 tsize(k, v) 539 KINFO *k; 540 VAR *v; 541 { 542 #ifndef NEWVM 543 (void) printf("%*d", v->width, pgtok(k->ki_e->e_xsize)); 544 #else /* NEWVM */ 545 (void) printf("%*d", v->width, pgtok(k->ki_e->e_vm.vm_tsize)); 546 #endif /* NEWVM */ 547 } 548 549 #ifndef NEWVM 550 trss(k, v) 551 KINFO *k; 552 VAR *v; 553 { 554 (void) printf("%*d", v->width, pgtok(k->ki_e->e_xrssize)); 555 } 556 #endif /* NEWVM */ 557 558 /* 559 * Generic output routines. Print fields from various prototype 560 * structures. 561 */ 562 pvar(k, v) 563 KINFO *k; 564 VAR *v; 565 { 566 printval((char *)((char *)k->ki_p + v->off), v); 567 } 568 569 evar(k, v) 570 KINFO *k; 571 VAR *v; 572 { 573 printval((char *)((char *)k->ki_e + v->off), v); 574 } 575 576 uvar(k, v) 577 KINFO *k; 578 VAR *v; 579 { 580 if (k->ki_u) 581 printval((char *)((char *)k->ki_u + v->off), v); 582 else 583 (void) printf("%*s", v->width, "-"); 584 } 585 586 rvar(k, v) 587 KINFO *k; 588 VAR *v; 589 { 590 if (k->ki_u) 591 printval((char *)((char *)(&k->ki_u->u_ru) + v->off), v); 592 else 593 (void) printf("%*s", v->width, "-"); 594 } 595 596 printval(bp, v) 597 char *bp; 598 VAR *v; 599 { 600 static char ofmt[32] = "%"; 601 register char *cp = ofmt+1, *fcp = v->fmt; 602 603 if (v->flag & LJUST) 604 *cp++ = '-'; 605 *cp++ = '*'; 606 while (*cp++ = *fcp++); 607 608 switch (v->type) { 609 case CHAR: 610 (void) printf(ofmt, v->width, *(char *)bp); 611 break; 612 case UCHAR: 613 (void) printf(ofmt, v->width, *(u_char *)bp); 614 break; 615 case SHORT: 616 (void) printf(ofmt, v->width, *(short *)bp); 617 break; 618 case USHORT: 619 (void) printf(ofmt, v->width, *(u_short *)bp); 620 break; 621 case LONG: 622 (void) printf(ofmt, v->width, *(long *)bp); 623 break; 624 case ULONG: 625 (void) printf(ofmt, v->width, *(u_long *)bp); 626 break; 627 case KPTR: 628 (void) printf(ofmt, v->width, *(u_long *)bp &~ KERNBASE); 629 break; 630 default: 631 err("unknown type %d", v->type); 632 } 633 } 634