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.2 (Berkeley) 02/08/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 if (psecs >= 100) { 328 psecs -= 100; 329 secs++; 330 } 331 } 332 (void) sprintf(obuff, "%3ld:%02ld.%02ld", secs/60, secs%60, psecs); 333 (void) printf("%*s", v->width, obuff); 334 } 335 336 double 337 getpcpu(k) 338 KINFO *k; 339 { 340 extern fixpt_t ccpu; 341 extern int fscale, nlistread, rawcpu; 342 struct proc *p; 343 static int failure; 344 345 if (!nlistread) 346 failure = donlist(); 347 if (failure) 348 return (0.0); 349 350 p = k->ki_p; 351 #define fxtofl(fixpt) ((double)(fixpt) / fscale) 352 353 /* XXX - I don't like this */ 354 if (p->p_time == 0 || (p->p_flag & SLOAD) == 0) 355 return (0.0); 356 if (rawcpu) 357 return (100.0 * fxtofl(p->p_pctcpu)); 358 return (100.0 * fxtofl(p->p_pctcpu) / 359 (1.0 - exp(p->p_time * log(fxtofl(ccpu))))); 360 } 361 362 pcpu(k, v) 363 KINFO *k; 364 VAR *v; 365 { 366 (void) printf("%*.1f", v->width, getpcpu(k)); 367 } 368 369 double 370 getpmem(k) 371 KINFO *k; 372 { 373 extern int ecmx, nlistread; 374 static int failure; 375 struct proc *p; 376 struct eproc *e; 377 double fracmem; 378 int szptudot; 379 380 if (!nlistread) 381 failure = donlist(); 382 if (failure) 383 return (0.0); 384 385 p = k->ki_p; 386 e = k->ki_e; 387 if ((p->p_flag & SLOAD) == 0) 388 return (0.0); 389 szptudot = UPAGES + clrnd(ctopt(p->p_dsize + p->p_ssize + e->e_xsize)); 390 fracmem = ((float)p->p_rssize + szptudot)/CLSIZE/ecmx; 391 if (p->p_textp && e->e_xccount) 392 fracmem += ((float)e->e_xrssize)/CLSIZE/e->e_xccount/ecmx; 393 return (100.0 * fracmem); 394 } 395 396 pmem(k, v) 397 KINFO *k; 398 VAR *v; 399 { 400 (void) printf("%*.1f", v->width, getpmem(k)); 401 } 402 403 pagein(k, v) 404 KINFO *k; 405 VAR *v; 406 { 407 (void) printf("%*d", v->width, k->ki_u ? k->ki_u->u_ru.ru_majflt : 0); 408 } 409 410 maxrss(k, v) 411 KINFO *k; 412 VAR *v; 413 { 414 if (k->ki_p->p_maxrss != (RLIM_INFINITY/NBPG)) 415 (void) printf("%*d", v->width, pgtok(k->ki_p->p_maxrss)); 416 else 417 (void) printf("%*s", v->width, "-"); 418 } 419 420 tsize(k, v) 421 KINFO *k; 422 VAR *v; 423 { 424 (void) printf("%*d", v->width, pgtok(k->ki_e->e_xsize)); 425 } 426 427 trss(k, v) 428 KINFO *k; 429 VAR *v; 430 { 431 (void) printf("%*d", v->width, pgtok(k->ki_e->e_xrssize)); 432 } 433 434 /* 435 * Generic output routines. Print fields from various prototype 436 * structures. 437 */ 438 pvar(k, v) 439 KINFO *k; 440 VAR *v; 441 { 442 printval((char *)((char *)k->ki_p + v->off), v); 443 } 444 445 evar(k, v) 446 KINFO *k; 447 VAR *v; 448 { 449 printval((char *)((char *)k->ki_e + v->off), v); 450 } 451 452 uvar(k, v) 453 KINFO *k; 454 VAR *v; 455 { 456 if (k->ki_u) 457 printval((char *)((char *)k->ki_u + v->off), v); 458 else 459 (void) printf("%*s", v->width, "-"); 460 } 461 462 rvar(k, v) 463 KINFO *k; 464 VAR *v; 465 { 466 if (k->ki_u) 467 printval((char *)((char *)(&k->ki_u->u_ru) + v->off), v); 468 else 469 (void) printf("%*s", v->width, "-"); 470 } 471 472 printval(bp, v) 473 char *bp; 474 VAR *v; 475 { 476 static char ofmt[32] = "%"; 477 register char *cp = ofmt+1, *fcp = v->fmt; 478 479 if (v->flag & LJUST) 480 *cp++ = '-'; 481 *cp++ = '*'; 482 while (*cp++ = *fcp++); 483 484 switch (v->type) { 485 case CHAR: 486 (void) printf(ofmt, v->width, *(char *)bp); 487 break; 488 case UCHAR: 489 (void) printf(ofmt, v->width, *(u_char *)bp); 490 break; 491 case SHORT: 492 (void) printf(ofmt, v->width, *(short *)bp); 493 break; 494 case USHORT: 495 (void) printf(ofmt, v->width, *(u_short *)bp); 496 break; 497 case LONG: 498 (void) printf(ofmt, v->width, *(long *)bp); 499 break; 500 case ULONG: 501 (void) printf(ofmt, v->width, *(u_long *)bp); 502 break; 503 case KPTR: 504 (void) printf(ofmt, v->width, *(u_long *)bp &~ KERNBASE); 505 break; 506 default: 507 error("unknown type %d", v->type); 508 } 509 } 510