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