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