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