xref: /original-bsd/bin/ps/print.c (revision 70c898fa)
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.14 (Berkeley) 04/29/93";
10 #endif /* not lint */
11 
12 #include <sys/param.h>
13 #include <sys/time.h>
14 #include <sys/resource.h>
15 #include <sys/proc.h>
16 #include <sys/stat.h>
17 
18 #ifdef SPPWAIT
19 #define NEWVM
20 #endif
21 
22 #ifdef NEWVM
23 #include <sys/ucred.h>
24 #include <sys/sysctl.h>
25 #include <vm/vm.h>
26 #else
27 #include <machine/pte.h>
28 #include <sys/vmparam.h>
29 #include <sys/vm.h>
30 #endif
31 
32 #include <err.h>
33 #include <math.h>
34 #include <nlist.h>
35 #include <stddef.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <tzfile.h>
40 
41 #include "ps.h"
42 
43 static void printval __P((char*, struct var *));
44 
45 void
46 printheader()
47 {
48 	register VAR *v;
49 	register struct varent *vent;
50 
51 	for (vent = vhead; vent; vent = vent->next) {
52 		v = vent->var;
53 		if (v->flag & LJUST) {
54 			if (vent->next == NULL)	/* last one */
55 				(void)printf("%s", v->header);
56 			else
57 				(void)printf("%-*s", v->width, v->header);
58 		} else
59 			(void)printf("%*s", v->width, v->header);
60 		if (vent->next != NULL)
61 			(void)putchar(' ');
62 	}
63 	(void)putchar('\n');
64 }
65 
66 void
67 command(k, ve)
68 	KINFO *k;
69 	VARENT *ve;
70 {
71 	extern int termwidth, totwidth;
72 	VAR *v;
73 
74 	v = ve->var;
75 	if (ve->next == NULL) {
76 		/* last field */
77 		if (termwidth == UNLIMITED) {
78 			if (k->ki_env)
79 				(void)printf("%s ", k->ki_env);
80 			(void)printf("%s", k->ki_args);
81 		} else {
82 			register int left = termwidth - (totwidth - v->width);
83 			register char *cp;
84 
85 			if (left < 1) /* already wrapped, just use std width */
86 				left = v->width;
87 			cp = k->ki_env;
88 			if (cp != 0) {
89 				while (--left >= 0 && *cp)
90 					(void)putchar(*cp++);
91 				if (--left >= 0)
92 					putchar(' ');
93 			}
94 			cp = k->ki_args;
95 			while (--left >= 0 && *cp)
96 				(void)putchar(*cp++);
97 		}
98 	} else
99 		/* XXX env? */
100 		(void)printf("%-*.*s", v->width, v->width, k->ki_args);
101 }
102 
103 void
104 ucomm(k, ve)
105 	KINFO *k;
106 	VARENT *ve;
107 {
108 	VAR *v;
109 
110 	v = ve->var;
111 	(void)printf("%-*s", v->width, KI_PROC(k)->p_comm);
112 }
113 
114 void
115 logname(k, ve)
116 	KINFO *k;
117 	VARENT *ve;
118 {
119 	VAR *v;
120 
121 	v = ve->var;
122 #ifndef NEWVM
123 	(void)printf("%-*s", v->width, KI_PROC(k)->p_logname);
124 #else /* NEWVM */
125 	(void)printf("%-*s", v->width, KI_EPROC(k)->e_login);
126 #endif /* NEWVM */
127 }
128 
129 void
130 state(k, ve)
131 	KINFO *k;
132 	VARENT *ve;
133 {
134 	register struct proc *p;
135 	register int flag;
136 	register char *cp;
137 	VAR *v;
138 	char buf[16];
139 
140 	v = ve->var;
141 	p = KI_PROC(k);
142 	flag = p->p_flag;
143 	cp = buf;
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 = '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 (KI_EPROC(k)->e_flag & EPROC_SLEADER)
205 		*cp++ = 's';
206 	if ((flag & SCTTY) && KI_EPROC(k)->e_pgid == KI_EPROC(k)->e_tpgid)
207 		*cp++ = '+';
208 	*cp = '\0';
209 	(void)printf("%-*s", v->width, buf);
210 }
211 
212 void
213 pri(k, ve)
214 	KINFO *k;
215 	VARENT *ve;
216 {
217 	VAR *v;
218 
219 	v = ve->var;
220 	(void)printf("%*d", v->width, KI_PROC(k)->p_pri - PZERO);
221 }
222 
223 void
224 uname(k, ve)
225 	KINFO *k;
226 	VARENT *ve;
227 {
228 	VAR *v;
229 
230 	v = ve->var;
231 #ifndef NEWVM
232 	(void)printf("%-*s",
233 	    (int)v->width, user_from_uid(KI_PROC(k)->p_uid, 0));
234 #else
235 	(void)printf("%-*s",
236 	    (int)v->width, user_from_uid(KI_EPROC(k)->e_ucred.cr_uid, 0));
237 #endif
238 }
239 
240 void
241 runame(k, ve)
242 	KINFO *k;
243 	VARENT *ve;
244 {
245 	VAR *v;
246 
247 	v = ve->var;
248 #ifndef NEWVM
249 	(void)printf("%-*s",
250 	    (int)v->width, user_from_uid(KI_PROC(k)->p_ruid, 0));
251 #else
252 	(void)printf("%-*s",
253 	    (int)v->width, user_from_uid(KI_EPROC(k)->e_pcred.p_ruid, 0));
254 #endif
255 }
256 
257 void
258 tdev(k, ve)
259 	KINFO *k;
260 	VARENT *ve;
261 {
262 	VAR *v;
263 	dev_t dev;
264 	char buff[16];
265 
266 	v = ve->var;
267 	dev = KI_EPROC(k)->e_tdev;
268 	if (dev == NODEV)
269 		(void)printf("%*s", v->width, "??");
270 	else {
271 		(void)snprintf(buff, sizeof(buff),
272 		    "%d/%d", major(dev), minor(dev));
273 		(void)printf("%*s", v->width, buff);
274 	}
275 }
276 
277 void
278 tname(k, ve)
279 	KINFO *k;
280 	VARENT *ve;
281 {
282 	VAR *v;
283 	dev_t dev;
284 	char *ttname;
285 
286 	v = ve->var;
287 	dev = KI_EPROC(k)->e_tdev;
288 	if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
289 		(void)printf("%-*s", v->width, "??");
290 	else {
291 		if (strncmp(ttname, "tty", 3) == 0)
292 			ttname += 3;
293 		(void)printf("%*.*s%c", v->width-1, v->width-1, ttname,
294 			KI_EPROC(k)->e_flag & EPROC_CTTY ? ' ' : '-');
295 	}
296 }
297 
298 void
299 longtname(k, ve)
300 	KINFO *k;
301 	VARENT *ve;
302 {
303 	VAR *v;
304 	dev_t dev;
305 	char *ttname;
306 
307 	v = ve->var;
308 	dev = KI_EPROC(k)->e_tdev;
309 	if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
310 		(void)printf("%-*s", v->width, "??");
311 	else
312 		(void)printf("%-*s", v->width, ttname);
313 }
314 
315 void
316 started(k, ve)
317 	KINFO *k;
318 	VARENT *ve;
319 {
320 	VAR *v;
321 	static time_t now;
322 	struct tm *tp;
323 	char buf[100];
324 
325 	v = ve->var;
326 	if (!k->ki_u.u_valid) {
327 		(void)printf("%-*s", v->width, "-");
328 		return;
329 	}
330 
331 	tp = localtime(&k->ki_u.u_start.tv_sec);
332 	if (!now)
333 		(void)time(&now);
334 	if (now - k->ki_u.u_start.tv_sec < 24 * SECSPERHOUR) {
335 		static char fmt[] = "%l:@M%p";
336 		fmt[3] = '%';			/* I *hate* SCCS... */
337 		(void)strftime(buf, sizeof(buf) - 1, fmt, tp);
338 	} else if (now - k->ki_u.u_start.tv_sec < 7 * SECSPERDAY) {
339 		static char fmt[] = "%a@I%p";
340 		fmt[2] = '%';			/* I *hate* SCCS... */
341 		(void)strftime(buf, sizeof(buf) - 1, fmt, tp);
342 	} else
343 		(void)strftime(buf, sizeof(buf) - 1, "%e%b%y", tp);
344 	(void)printf("%-*s", v->width, buf);
345 }
346 
347 void
348 lstarted(k, ve)
349 	KINFO *k;
350 	VARENT *ve;
351 {
352 	VAR *v;
353 	char buf[100];
354 
355 	v = ve->var;
356 	if (!k->ki_u.u_valid) {
357 		(void)printf("%-*s", v->width, "-");
358 		return;
359 	}
360 	(void)strftime(buf, sizeof(buf) -1, "%C",
361 	    localtime(&k->ki_u.u_start.tv_sec));
362 	(void)printf("%-*s", v->width, buf);
363 }
364 
365 void
366 wchan(k, ve)
367 	KINFO *k;
368 	VARENT *ve;
369 {
370 	VAR *v;
371 
372 	v = ve->var;
373 	if (KI_PROC(k)->p_wchan) {
374 		if (KI_PROC(k)->p_wmesg)
375 			(void)printf("%-*.*s", v->width, v->width,
376 				      KI_EPROC(k)->e_wmesg);
377 		else
378 			(void)printf("%-*x", v->width,
379 			    (int)KI_PROC(k)->p_wchan &~ KERNBASE);
380 	} else
381 		(void)printf("%-*s", v->width, "-");
382 }
383 
384 #define pgtok(a)        (((a)*NBPG)/1024)
385 
386 void
387 vsize(k, ve)
388 	KINFO *k;
389 	VARENT *ve;
390 {
391 	VAR *v;
392 
393 	v = ve->var;
394 	(void)printf("%*d", v->width,
395 #ifndef NEWVM
396 	    pgtok(KI_PROC(k)->p_dsize + KI_PROC(k)->p_ssize + KI_EPROC(k)->e_xsize));
397 #else /* NEWVM */
398 	    pgtok(KI_EPROC(k)->e_vm.vm_dsize + KI_EPROC(k)->e_vm.vm_ssize +
399 		KI_EPROC(k)->e_vm.vm_tsize));
400 #endif /* NEWVM */
401 }
402 
403 void
404 rssize(k, ve)
405 	KINFO *k;
406 	VARENT *ve;
407 {
408 	VAR *v;
409 
410 	v = ve->var;
411 #ifndef NEWVM
412 	(void)printf("%*d", v->width,
413 	    pgtok(KI_PROC(k)->p_rssize + (KI_EPROC(k)->e_xccount ?
414 	    (KI_EPROC(k)->e_xrssize / KI_EPROC(k)->e_xccount) : 0)));
415 #else /* NEWVM */
416 	/* XXX don't have info about shared */
417 	(void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_vm.vm_rssize));
418 #endif /* NEWVM */
419 }
420 
421 void
422 p_rssize(k, ve)		/* doesn't account for text */
423 	KINFO *k;
424 	VARENT *ve;
425 {
426 	VAR *v;
427 
428 	v = ve->var;
429 #ifndef NEWVM
430 	(void)printf("%*d", v->width, pgtok(KI_PROC(k)->p_rssize));
431 #else /* NEWVM */
432 	(void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_vm.vm_rssize));
433 #endif /* NEWVM */
434 }
435 
436 void
437 cputime(k, ve)
438 	KINFO *k;
439 	VARENT *ve;
440 {
441 	extern int sumrusage;
442 	VAR *v;
443 	long secs;
444 	long psecs;	/* "parts" of a second. first micro, then centi */
445 	char obuff[128];
446 
447 	v = ve->var;
448 	if (KI_PROC(k)->p_stat == SZOMB || !k->ki_u.u_valid) {
449 		secs = 0;
450 		psecs = 0;
451 	} else {
452 		/*
453 		 * This counts time spent handling interrupts.  We could
454 		 * fix this, but it is not 100% trivial (and interrupt
455 		 * time fractions only work on the sparc anyway).	XXX
456 		 */
457 		secs = KI_PROC(k)->p_rtime.tv_sec;
458 		psecs = KI_PROC(k)->p_rtime.tv_usec;
459 		if (sumrusage) {
460 			secs += k->ki_u.u_cru.ru_utime.tv_sec +
461 				k->ki_u.u_cru.ru_stime.tv_sec;
462 			psecs += k->ki_u.u_cru.ru_utime.tv_usec +
463 				k->ki_u.u_cru.ru_stime.tv_usec;
464 		}
465 		/*
466 		 * round and scale to 100's
467 		 */
468 		psecs = (psecs + 5000) / 10000;
469 		secs += psecs / 100;
470 		psecs = psecs % 100;
471 	}
472 	(void)snprintf(obuff, sizeof(obuff),
473 	    "%3ld:%02ld.%02ld", secs/60, secs%60, psecs);
474 	(void)printf("%*s", v->width, obuff);
475 }
476 
477 double
478 getpcpu(k)
479 	KINFO *k;
480 {
481 	extern fixpt_t ccpu;
482 	extern int fscale, nlistread, rawcpu;
483 	struct proc *p;
484 	static int failure;
485 
486 	if (!nlistread)
487 		failure = donlist();
488 	if (failure)
489 		return (0.0);
490 
491 	p = KI_PROC(k);
492 #define	fxtofl(fixpt)	((double)(fixpt) / fscale)
493 
494 	/* XXX - I don't like this */
495 	if (p->p_time == 0 || (p->p_flag & SLOAD) == 0)
496 		return (0.0);
497 	if (rawcpu)
498 		return (100.0 * fxtofl(p->p_pctcpu));
499 	return (100.0 * fxtofl(p->p_pctcpu) /
500 		(1.0 - exp(p->p_time * log(fxtofl(ccpu)))));
501 }
502 
503 void
504 pcpu(k, ve)
505 	KINFO *k;
506 	VARENT *ve;
507 {
508 	VAR *v;
509 
510 	v = ve->var;
511 	(void)printf("%*.1f", v->width, getpcpu(k));
512 }
513 
514 double
515 getpmem(k)
516 	KINFO *k;
517 {
518 	extern int mempages, nlistread;
519 	static int failure;
520 	struct proc *p;
521 	struct eproc *e;
522 	double fracmem;
523 	int szptudot;
524 
525 	if (!nlistread)
526 		failure = donlist();
527 	if (failure)
528 		return (0.0);
529 
530 	p = KI_PROC(k);
531 	e = KI_EPROC(k);
532 	if ((p->p_flag & SLOAD) == 0)
533 		return (0.0);
534 #ifndef NEWVM
535 	szptudot = UPAGES + clrnd(ctopt(p->p_dsize + p->p_ssize + e->e_xsize));
536 	fracmem = ((float)p->p_rssize + szptudot)/CLSIZE/mempages;
537 	if (p->p_textp && e->e_xccount)
538 		fracmem += ((float)e->e_xrssize)/CLSIZE/e->e_xccount/mempages;
539 #else /* NEWVM */
540 	/* XXX want pmap ptpages, segtab, etc. (per architecture) */
541 	szptudot = UPAGES;
542 	/* XXX don't have info about shared */
543 	fracmem = ((float)e->e_vm.vm_rssize + szptudot)/CLSIZE/mempages;
544 #endif /* NEWVM */
545 	return (100.0 * fracmem);
546 }
547 
548 void
549 pmem(k, ve)
550 	KINFO *k;
551 	VARENT *ve;
552 {
553 	VAR *v;
554 
555 	v = ve->var;
556 	(void)printf("%*.1f", v->width, getpmem(k));
557 }
558 
559 void
560 pagein(k, ve)
561 	KINFO *k;
562 	VARENT *ve;
563 {
564 	VAR *v;
565 
566 	v = ve->var;
567 	(void)printf("%*d", v->width,
568 	    k->ki_u.u_valid ? k->ki_u.u_ru.ru_majflt : 0);
569 }
570 
571 void
572 maxrss(k, ve)
573 	KINFO *k;
574 	VARENT *ve;
575 {
576 	VAR *v;
577 
578 	v = ve->var;
579 #ifndef NEWVM	/* not yet */
580 	if (KI_PROC(k)->p_maxrss != (RLIM_INFINITY/NBPG))
581 		(void)printf("%*d", v->width, pgtok(KI_PROC(k)->p_maxrss));
582 	else
583 #endif /* NEWVM */
584 		(void)printf("%*s", v->width, "-");
585 }
586 
587 void
588 tsize(k, ve)
589 	KINFO *k;
590 	VARENT *ve;
591 {
592 	VAR *v;
593 
594 	v = ve->var;
595 #ifndef NEWVM
596 	(void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_xsize));
597 #else /* NEWVM */
598 	(void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_vm.vm_tsize));
599 #endif /* NEWVM */
600 }
601 
602 #ifndef NEWVM
603 void
604 trss(k, ve)
605 	KINFO *k;
606 	VARENT *ve;
607 {
608 	VAR *v;
609 
610 	v = ve->var;
611 	(void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_xrssize));
612 }
613 #endif /* NEWVM */
614 
615 /*
616  * Generic output routines.  Print fields from various prototype
617  * structures.
618  */
619 void
620 pvar(k, ve)
621 	KINFO *k;
622 	VARENT *ve;
623 {
624 	VAR *v;
625 
626 	v = ve->var;
627 	printval((char *)((char *)KI_PROC(k) + v->off), v);
628 }
629 
630 void
631 evar(k, ve)
632 	KINFO *k;
633 	VARENT *ve;
634 {
635 	VAR *v;
636 
637 	v = ve->var;
638 	printval((char *)((char *)KI_EPROC(k) + v->off), v);
639 }
640 
641 void
642 uvar(k, ve)
643 	KINFO *k;
644 	VARENT *ve;
645 {
646 	VAR *v;
647 
648 	v = ve->var;
649 	if (k->ki_u.u_valid)
650 		printval((char *)((char *)&k->ki_u + v->off), v);
651 	else
652 		(void)printf("%*s", v->width, "-");
653 }
654 
655 void
656 rvar(k, ve)
657 	KINFO *k;
658 	VARENT *ve;
659 {
660 	VAR *v;
661 
662 	v = ve->var;
663 	if (k->ki_u.u_valid)
664 		printval((char *)((char *)(&k->ki_u.u_ru) + v->off), v);
665 	else
666 		(void)printf("%*s", v->width, "-");
667 }
668 
669 static void
670 printval(bp, v)
671 	char *bp;
672 	VAR *v;
673 {
674 	static char ofmt[32] = "%";
675 	register char *fcp, *cp;
676 
677 	cp = ofmt + 1;
678 	fcp = v->fmt;
679 	if (v->flag & LJUST)
680 		*cp++ = '-';
681 	*cp++ = '*';
682 	while (*cp++ = *fcp++);
683 
684 	switch (v->type) {
685 	case CHAR:
686 		(void)printf(ofmt, v->width, *(char *)bp);
687 		break;
688 	case UCHAR:
689 		(void)printf(ofmt, v->width, *(u_char *)bp);
690 		break;
691 	case SHORT:
692 		(void)printf(ofmt, v->width, *(short *)bp);
693 		break;
694 	case USHORT:
695 		(void)printf(ofmt, v->width, *(u_short *)bp);
696 		break;
697 	case LONG:
698 		(void)printf(ofmt, v->width, *(long *)bp);
699 		break;
700 	case ULONG:
701 		(void)printf(ofmt, v->width, *(u_long *)bp);
702 		break;
703 	case KPTR:
704 		(void)printf(ofmt, v->width, *(u_long *)bp &~ KERNBASE);
705 		break;
706 	default:
707 		errx(1, "unknown type %d", v->type);
708 	}
709 }
710