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