Home | History | Annotate | Line # | Download | only in ps
print.c revision 1.11
      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[] = "from: @(#)print.c	5.9 (Berkeley) 7/1/91";*/
     36 static char rcsid[] = "$Id: print.c,v 1.11 1994/05/05 06:44: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 P_PPWAIT
     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 & P_SINTR)	/* interuptable (long) */
    173 			*cp = p->p_slptime >= MAXSLP ? 'I' : 'S';
    174 		else
    175 			*cp = '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 & P_INMEM) {
    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 & P_TRACED)
    209 		*cp++ = 'X';
    210 	if (flag & P_WEXIT && p->p_stat != SZOMB)
    211 		*cp++ = 'E';
    212 #ifdef NEWVM
    213 	if (flag & P_PPWAIT)
    214 #else
    215 	if (flag & SVFORK)
    216 #endif
    217 		*cp++ = 'V';
    218 #ifdef NEWVM
    219 	if (flag & (P_SYSTEM|P_NOSWAP|P_PHYSIO))
    220 #else
    221 	if (flag & (P_SYSTEM|P_NOSWAP|P_PHYSIO))
    222 #endif
    223 		*cp++ = 'L';
    224 	if (k->ki_e->e_flag & EPROC_SLEADER)
    225 		*cp++ = 's';
    226 	if ((flag & P_CONTROLT) && 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_priority - 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_rtime.tv_sec;
    425 		psecs = k->ki_p->p_rtime.tv_usec;
    426 		if (sumrusage) {
    427 			secs += k->ki_u->u_cru.ru_utime.tv_sec +
    428 				k->ki_u->u_cru.ru_stime.tv_sec;
    429 			psecs += k->ki_u->u_cru.ru_utime.tv_usec +
    430 				k->ki_u->u_cru.ru_stime.tv_usec;
    431 		}
    432 		/*
    433 		 * round and scale to 100's
    434 		 */
    435 		psecs = (psecs + 5000) / 10000;
    436 		secs += psecs / 100;
    437 		psecs = psecs % 100;
    438 	}
    439 	(void) sprintf(obuff, "%3ld:%02ld.%02ld", secs/60, secs%60, psecs);
    440 	(void) printf("%*s", v->width, obuff);
    441 }
    442 
    443 double
    444 getpcpu(k)
    445 	KINFO *k;
    446 {
    447 	extern fixpt_t ccpu;
    448 	extern int fscale, nlistread, rawcpu;
    449 	struct proc *p;
    450 	static int failure;
    451 
    452 	if (!nlistread)
    453 		failure = donlist();
    454 	if (failure)
    455 		return (0.0);
    456 
    457 	p = k->ki_p;
    458 #define	fxtofl(fixpt)	((double)(fixpt) / fscale)
    459 
    460 	/* XXX - I don't like this */
    461 	if (p->p_swtime == 0 || (p->p_stat == SZOMB) || (p->p_flag & P_INMEM) == 0)
    462 		return (0.0);
    463 	if (rawcpu)
    464 		return (100.0 * fxtofl(p->p_pctcpu));
    465 	return (100.0 * fxtofl(p->p_pctcpu) /
    466 		(1.0 - exp(p->p_swtime * log(fxtofl(ccpu)))));
    467 }
    468 
    469 pcpu(k, v)
    470 	KINFO *k;
    471 	VAR *v;
    472 {
    473 	(void) printf("%*.1f", v->width, getpcpu(k));
    474 }
    475 
    476 double
    477 getpmem(k)
    478 	KINFO *k;
    479 {
    480 	extern int mempages, nlistread;
    481 	static int failure;
    482 	struct proc *p;
    483 	struct eproc *e;
    484 	double fracmem;
    485 	int szptudot;
    486 
    487 	if (!nlistread)
    488 		failure = donlist();
    489 	if (failure)
    490 		return (0.0);
    491 
    492 	p = k->ki_p;
    493 	e = k->ki_e;
    494 	if ((p->p_flag & P_INMEM) == 0 || (p->p_stat == SZOMB))
    495 		return (0.0);
    496 #ifndef NEWVM
    497 	szptudot = UPAGES + clrnd(ctopt(p->p_dsize + p->p_ssize + e->e_xsize));
    498 	fracmem = ((float)p->p_rssize + szptudot)/CLSIZE/mempages;
    499 	if (p->p_textp && e->e_xccount)
    500 		fracmem += ((float)e->e_xrssize)/CLSIZE/e->e_xccount/mempages;
    501 #else /* NEWVM */
    502 	/* XXX want pmap ptpages, segtab, etc. (per architecture) */
    503 	szptudot = UPAGES;
    504 	/* XXX don't have info about shared */
    505 	fracmem = ((float)e->e_vm.vm_rssize + szptudot)/CLSIZE/mempages;
    506 #endif /* NEWVM */
    507 	return (100.0 * fracmem);
    508 }
    509 
    510 pmem(k, v)
    511 	KINFO *k;
    512 	VAR *v;
    513 {
    514 	(void) printf("%*.1f", v->width, getpmem(k));
    515 }
    516 
    517 pagein(k, v)
    518 	KINFO *k;
    519 	VAR *v;
    520 {
    521 	(void) printf("%*d", v->width, k->ki_u ? k->ki_u->u_ru.ru_majflt : 0);
    522 }
    523 
    524 maxrss(k, v)
    525 	KINFO *k;
    526 	VAR *v;
    527 {
    528 #ifndef NEWVM	/* not yet */
    529 	if (k->ki_p->p_maxrss != (RLIM_INFINITY/NBPG))
    530 		(void) printf("%*d", v->width, pgtok(k->ki_p->p_maxrss));
    531 	else
    532 #endif /* NEWVM */
    533 		(void) printf("%*s", v->width, "-");
    534 }
    535 
    536 tsize(k, v)
    537 	KINFO *k;
    538 	VAR *v;
    539 {
    540 #ifndef NEWVM
    541 	(void) printf("%*d", v->width, pgtok(k->ki_e->e_xsize));
    542 #else /* NEWVM */
    543 	(void) printf("%*d", v->width, pgtok(k->ki_e->e_vm.vm_tsize));
    544 #endif /* NEWVM */
    545 }
    546 
    547 #ifndef NEWVM
    548 trss(k, v)
    549 	KINFO *k;
    550 	VAR *v;
    551 {
    552 	(void) printf("%*d", v->width, pgtok(k->ki_e->e_xrssize));
    553 }
    554 #endif /* NEWVM */
    555 
    556 /*
    557  * Generic output routines.  Print fields from various prototype
    558  * structures.
    559  */
    560 pvar(k, v)
    561 	KINFO *k;
    562 	VAR *v;
    563 {
    564 	printval((char *)((char *)k->ki_p + v->off), v);
    565 }
    566 
    567 evar(k, v)
    568 	KINFO *k;
    569 	VAR *v;
    570 {
    571 	printval((char *)((char *)k->ki_e + v->off), v);
    572 }
    573 
    574 uvar(k, v)
    575 	KINFO *k;
    576 	VAR *v;
    577 {
    578 	if (k->ki_u)
    579 		printval((char *)((char *)k->ki_u + v->off), v);
    580 	else
    581 		(void) printf("%*s", v->width, "-");
    582 }
    583 
    584 rvar(k, v)
    585 	KINFO *k;
    586 	VAR *v;
    587 {
    588 	if (k->ki_u)
    589 		printval((char *)((char *)(&k->ki_u->u_ru) + v->off), v);
    590 	else
    591 		(void) printf("%*s", v->width, "-");
    592 }
    593 
    594 printval(bp, v)
    595 	char *bp;
    596 	VAR *v;
    597 {
    598 	static char ofmt[32] = "%";
    599 	register char *cp = ofmt+1, *fcp = v->fmt;
    600 
    601 	if (v->flag & LJUST)
    602 		*cp++ = '-';
    603 	*cp++ = '*';
    604 	while (*cp++ = *fcp++);
    605 
    606 	switch (v->type) {
    607 	case CHAR:
    608 		(void) printf(ofmt, v->width, *(char *)bp);
    609 		break;
    610 	case UCHAR:
    611 		(void) printf(ofmt, v->width, *(u_char *)bp);
    612 		break;
    613 	case SHORT:
    614 		(void) printf(ofmt, v->width, *(short *)bp);
    615 		break;
    616 	case USHORT:
    617 		(void) printf(ofmt, v->width, *(u_short *)bp);
    618 		break;
    619 	case LONG:
    620 		(void) printf(ofmt, v->width, *(long *)bp);
    621 		break;
    622 	case ULONG:
    623 		(void) printf(ofmt, v->width, *(u_long *)bp);
    624 		break;
    625 	case KPTR:
    626 		(void) printf(ofmt, v->width, *(u_long *)bp &~ KERNBASE);
    627 		break;
    628 	default:
    629 		err("unknown type %d", v->type);
    630 	}
    631 }
    632