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