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