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