xref: /original-bsd/bin/ps/print.c (revision 95ecee29)
1 /*-
2  * Copyright (c) 1990, 1993
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.3 (Berkeley) 09/23/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 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 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
125 	(void)printf("%-*s", v->width, KI_EPROC(k)->e_login);
126 #endif
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 & P_SINTR)	/* 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 & P_INMEM) {
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 & P_TRACED)
189 		*cp++ = 'X';
190 	if (flag & P_WEXIT && p->p_stat != SZOMB)
191 		*cp++ = 'E';
192 #ifdef NEWVM
193 	if (flag & P_PPWAIT)
194 #else
195 	if (flag & SVFORK)
196 #endif
197 		*cp++ = 'V';
198 #ifdef NEWVM
199 	if (flag & (P_SYSTEM | P_NOSWAP | P_PHYSIO))
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 & P_CONTROLT) && 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_priority - 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 +
397 	        KI_PROC(k)->p_ssize + KI_EPROC(k)->e_xsize));
398 #else
399 	    pgtok(KI_EPROC(k)->e_vm.vm_dsize + KI_EPROC(k)->e_vm.vm_ssize +
400 		KI_EPROC(k)->e_vm.vm_tsize));
401 #endif
402 }
403 
404 void
405 rssize(k, ve)
406 	KINFO *k;
407 	VARENT *ve;
408 {
409 	VAR *v;
410 
411 	v = ve->var;
412 #ifndef NEWVM
413 	(void)printf("%*d", v->width,
414 	    pgtok(KI_PROC(k)->p_rssize + (KI_EPROC(k)->e_xccount ?
415 	    (KI_EPROC(k)->e_xrssize / KI_EPROC(k)->e_xccount) : 0)));
416 #else
417 	/* XXX don't have info about shared */
418 	(void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_vm.vm_rssize));
419 #endif
420 }
421 
422 void
423 p_rssize(k, ve)		/* doesn't account for text */
424 	KINFO *k;
425 	VARENT *ve;
426 {
427 	VAR *v;
428 
429 	v = ve->var;
430 #ifndef NEWVM
431 	(void)printf("%*d", v->width, pgtok(KI_PROC(k)->p_rssize));
432 #else
433 	(void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_vm.vm_rssize));
434 #endif
435 }
436 
437 void
438 cputime(k, ve)
439 	KINFO *k;
440 	VARENT *ve;
441 {
442 	extern int sumrusage;
443 	VAR *v;
444 	long secs;
445 	long psecs;	/* "parts" of a second. first micro, then centi */
446 	char obuff[128];
447 
448 	v = ve->var;
449 	if (KI_PROC(k)->p_stat == SZOMB || !k->ki_u.u_valid) {
450 		secs = 0;
451 		psecs = 0;
452 	} else {
453 		/*
454 		 * This counts time spent handling interrupts.  We could
455 		 * fix this, but it is not 100% trivial (and interrupt
456 		 * time fractions only work on the sparc anyway).	XXX
457 		 */
458 		secs = KI_PROC(k)->p_rtime.tv_sec;
459 		psecs = KI_PROC(k)->p_rtime.tv_usec;
460 		if (sumrusage) {
461 			secs += k->ki_u.u_cru.ru_utime.tv_sec +
462 				k->ki_u.u_cru.ru_stime.tv_sec;
463 			psecs += k->ki_u.u_cru.ru_utime.tv_usec +
464 				k->ki_u.u_cru.ru_stime.tv_usec;
465 		}
466 		/*
467 		 * round and scale to 100's
468 		 */
469 		psecs = (psecs + 5000) / 10000;
470 		secs += psecs / 100;
471 		psecs = psecs % 100;
472 	}
473 	(void)snprintf(obuff, sizeof(obuff),
474 	    "%3ld:%02ld.%02ld", secs/60, secs%60, psecs);
475 	(void)printf("%*s", v->width, obuff);
476 }
477 
478 double
479 getpcpu(k)
480 	KINFO *k;
481 {
482 	extern fixpt_t ccpu;
483 	extern int fscale, nlistread, rawcpu;
484 	struct proc *p;
485 	static int failure;
486 
487 	if (!nlistread)
488 		failure = donlist();
489 	if (failure)
490 		return (0.0);
491 
492 	p = KI_PROC(k);
493 #define	fxtofl(fixpt)	((double)(fixpt) / fscale)
494 
495 	/* XXX - I don't like this */
496 	if (p->p_swtime == 0 || (p->p_flag & P_INMEM) == 0)
497 		return (0.0);
498 	if (rawcpu)
499 		return (100.0 * fxtofl(p->p_pctcpu));
500 	return (100.0 * fxtofl(p->p_pctcpu) /
501 		(1.0 - exp(p->p_swtime * log(fxtofl(ccpu)))));
502 }
503 
504 void
505 pcpu(k, ve)
506 	KINFO *k;
507 	VARENT *ve;
508 {
509 	VAR *v;
510 
511 	v = ve->var;
512 	(void)printf("%*.1f", v->width, getpcpu(k));
513 }
514 
515 double
516 getpmem(k)
517 	KINFO *k;
518 {
519 	extern int mempages, nlistread;
520 	static int failure;
521 	struct proc *p;
522 	struct eproc *e;
523 	double fracmem;
524 	int szptudot;
525 
526 	if (!nlistread)
527 		failure = donlist();
528 	if (failure)
529 		return (0.0);
530 
531 	p = KI_PROC(k);
532 	e = KI_EPROC(k);
533 	if ((p->p_flag & P_INMEM) == 0)
534 		return (0.0);
535 #ifndef NEWVM
536 	szptudot = UPAGES + clrnd(ctopt(p->p_dsize + p->p_ssize + e->e_xsize));
537 	fracmem = ((float)p->p_rssize + szptudot)/CLSIZE/mempages;
538 	if (p->p_textp && e->e_xccount)
539 		fracmem += ((float)e->e_xrssize)/CLSIZE/e->e_xccount/mempages;
540 #else
541 	/* XXX want pmap ptpages, segtab, etc. (per architecture) */
542 	szptudot = UPAGES;
543 	/* XXX don't have info about shared */
544 	fracmem = ((float)e->e_vm.vm_rssize + szptudot)/CLSIZE/mempages;
545 #endif
546 	return (100.0 * fracmem);
547 }
548 
549 void
550 pmem(k, ve)
551 	KINFO *k;
552 	VARENT *ve;
553 {
554 	VAR *v;
555 
556 	v = ve->var;
557 	(void)printf("%*.1f", v->width, getpmem(k));
558 }
559 
560 void
561 pagein(k, ve)
562 	KINFO *k;
563 	VARENT *ve;
564 {
565 	VAR *v;
566 
567 	v = ve->var;
568 	(void)printf("%*d", v->width,
569 	    k->ki_u.u_valid ? k->ki_u.u_ru.ru_majflt : 0);
570 }
571 
572 void
573 maxrss(k, ve)
574 	KINFO *k;
575 	VARENT *ve;
576 {
577 	VAR *v;
578 
579 	v = ve->var;
580 #ifndef NEWVM	/* not yet */
581 	if (KI_PROC(k)->p_maxrss != (RLIM_INFINITY/NBPG))
582 		(void)printf("%*d", v->width, pgtok(KI_PROC(k)->p_maxrss));
583 	else
584 #endif
585 		(void)printf("%*s", v->width, "-");
586 }
587 
588 void
589 tsize(k, ve)
590 	KINFO *k;
591 	VARENT *ve;
592 {
593 	VAR *v;
594 
595 	v = ve->var;
596 #ifndef NEWVM
597 	(void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_xsize));
598 #else
599 	(void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_vm.vm_tsize));
600 #endif
601 }
602 
603 #ifndef NEWVM
604 void
605 trss(k, ve)
606 	KINFO *k;
607 	VARENT *ve;
608 {
609 	VAR *v;
610 
611 	v = ve->var;
612 	(void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_xrssize));
613 }
614 #endif
615 
616 /*
617  * Generic output routines.  Print fields from various prototype
618  * structures.
619  */
620 void
621 pvar(k, ve)
622 	KINFO *k;
623 	VARENT *ve;
624 {
625 	VAR *v;
626 
627 	v = ve->var;
628 	printval((char *)((char *)KI_PROC(k) + v->off), v);
629 }
630 
631 void
632 evar(k, ve)
633 	KINFO *k;
634 	VARENT *ve;
635 {
636 	VAR *v;
637 
638 	v = ve->var;
639 	printval((char *)((char *)KI_EPROC(k) + v->off), v);
640 }
641 
642 void
643 uvar(k, ve)
644 	KINFO *k;
645 	VARENT *ve;
646 {
647 	VAR *v;
648 
649 	v = ve->var;
650 	if (k->ki_u.u_valid)
651 		printval((char *)((char *)&k->ki_u + v->off), v);
652 	else
653 		(void)printf("%*s", v->width, "-");
654 }
655 
656 void
657 rvar(k, ve)
658 	KINFO *k;
659 	VARENT *ve;
660 {
661 	VAR *v;
662 
663 	v = ve->var;
664 	if (k->ki_u.u_valid)
665 		printval((char *)((char *)(&k->ki_u.u_ru) + v->off), v);
666 	else
667 		(void)printf("%*s", v->width, "-");
668 }
669 
670 static void
671 printval(bp, v)
672 	char *bp;
673 	VAR *v;
674 {
675 	static char ofmt[32] = "%";
676 	register char *fcp, *cp;
677 
678 	cp = ofmt + 1;
679 	fcp = v->fmt;
680 	if (v->flag & LJUST)
681 		*cp++ = '-';
682 	*cp++ = '*';
683 	while (*cp++ = *fcp++);
684 
685 	switch (v->type) {
686 	case CHAR:
687 		(void)printf(ofmt, v->width, *(char *)bp);
688 		break;
689 	case UCHAR:
690 		(void)printf(ofmt, v->width, *(u_char *)bp);
691 		break;
692 	case SHORT:
693 		(void)printf(ofmt, v->width, *(short *)bp);
694 		break;
695 	case USHORT:
696 		(void)printf(ofmt, v->width, *(u_short *)bp);
697 		break;
698 	case LONG:
699 		(void)printf(ofmt, v->width, *(long *)bp);
700 		break;
701 	case ULONG:
702 		(void)printf(ofmt, v->width, *(u_long *)bp);
703 		break;
704 	case KPTR:
705 		(void)printf(ofmt, v->width, *(u_long *)bp &~ KERNBASE);
706 		break;
707 	default:
708 		errx(1, "unknown type %d", v->type);
709 	}
710 }
711