xref: /original-bsd/bin/ps/print.c (revision 68d9582f)
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.11 (Berkeley) 06/05/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 = (flag & SPAGE) ? 'P' : '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 
303 	dev = KI_EPROC(k)->e_tdev;
304 	if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
305 		(void)printf("%-*s", v->width, "??");
306 	else
307 		(void)printf("%-*s", v->width, ttname);
308 }
309 
310 void
311 started(k, ve)
312 	KINFO *k;
313 	VARENT *ve;
314 {
315 	VAR *v;
316 	static time_t now;
317 	struct tm *tp;
318 	char buf[100];
319 
320 	v = ve->var;
321 	if (!k->ki_u.u_valid) {
322 		(void)printf("%-*s", v->width, "-");
323 		return;
324 	}
325 
326 	tp = localtime(&k->ki_u.u_start.tv_sec);
327 	if (!now)
328 		(void)time(&now);
329 	if (now - k->ki_u.u_start.tv_sec < 24 * SECSPERHOUR) {
330 		static char fmt[] = "%l:@M%p";
331 		fmt[3] = '%';			/* I *hate* SCCS... */
332 		(void)strftime(buf, sizeof(buf) - 1, fmt, tp);
333 	} else if (now - k->ki_u.u_start.tv_sec < 7 * SECSPERDAY) {
334 		static char fmt[] = "%a@I%p";
335 		fmt[2] = '%';			/* I *hate* SCCS... */
336 		(void)strftime(buf, sizeof(buf) - 1, fmt, tp);
337 	} else
338 		(void)strftime(buf, sizeof(buf) - 1, "%e%b%y", tp);
339 	(void)printf("%-*s", v->width, buf);
340 }
341 
342 void
343 lstarted(k, ve)
344 	KINFO *k;
345 	VARENT *ve;
346 {
347 	VAR *v;
348 	char buf[100];
349 
350 	v = ve->var;
351 
352 	if (!k->ki_u.u_valid) {
353 		(void)printf("%-*s", v->width, "-");
354 		return;
355 	}
356 	(void)strftime(buf, sizeof(buf) -1, "%C",
357 	    localtime(&k->ki_u.u_start.tv_sec));
358 	(void)printf("%-*s", v->width, buf);
359 }
360 
361 void
362 wchan(k, ve)
363 	KINFO *k;
364 	VARENT *ve;
365 {
366 	VAR *v;
367 
368 	v = ve->var;
369 	if (KI_PROC(k)->p_wchan) {
370 		if (KI_PROC(k)->p_wmesg)
371 			(void)printf("%-*.*s", v->width, v->width,
372 				      KI_EPROC(k)->e_wmesg);
373 		else
374 			(void)printf("%-*x", v->width,
375 			    (int)KI_PROC(k)->p_wchan &~ KERNBASE);
376 	} else
377 		(void)printf("%-*s", v->width, "-");
378 }
379 
380 #define pgtok(a)        (((a)*NBPG)/1024)
381 
382 void
383 vsize(k, ve)
384 	KINFO *k;
385 	VARENT *ve;
386 {
387 	VAR *v;
388 
389 	v = ve->var;
390 	(void)printf("%*d", v->width,
391 #ifndef NEWVM
392 	    pgtok(KI_PROC(k)->p_dsize + KI_PROC(k)->p_ssize + KI_EPROC(k)->e_xsize));
393 #else /* NEWVM */
394 	    pgtok(KI_EPROC(k)->e_vm.vm_dsize + KI_EPROC(k)->e_vm.vm_ssize +
395 		KI_EPROC(k)->e_vm.vm_tsize));
396 #endif /* NEWVM */
397 }
398 
399 void
400 rssize(k, ve)
401 	KINFO *k;
402 	VARENT *ve;
403 {
404 	VAR *v;
405 
406 	v = ve->var;
407 #ifndef NEWVM
408 	(void)printf("%*d", v->width,
409 	    pgtok(KI_PROC(k)->p_rssize + (KI_EPROC(k)->e_xccount ?
410 	    (KI_EPROC(k)->e_xrssize / KI_EPROC(k)->e_xccount) : 0)));
411 #else /* NEWVM */
412 	/* XXX don't have info about shared */
413 	(void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_vm.vm_rssize));
414 #endif /* NEWVM */
415 }
416 
417 void
418 p_rssize(k, ve)		/* doesn't account for text */
419 	KINFO *k;
420 	VARENT *ve;
421 {
422 	VAR *v;
423 
424 	v = ve->var;
425 #ifndef NEWVM
426 	(void)printf("%*d", v->width, pgtok(KI_PROC(k)->p_rssize));
427 #else /* NEWVM */
428 	(void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_vm.vm_rssize));
429 #endif /* NEWVM */
430 }
431 
432 void
433 cputime(k, ve)
434 	KINFO *k;
435 	VARENT *ve;
436 {
437 	extern int sumrusage;
438 	VAR *v;
439 	long secs;
440 	long psecs;	/* "parts" of a second. first micro, then centi */
441 	char obuff[128];
442 
443 	v = ve->var;
444 	if (KI_PROC(k)->p_stat == SZOMB || !k->ki_u.u_valid) {
445 		secs = 0;
446 		psecs = 0;
447 	} else {
448 		secs = KI_PROC(k)->p_utime.tv_sec +
449 			KI_PROC(k)->p_stime.tv_sec;
450 		psecs = KI_PROC(k)->p_utime.tv_usec +
451 			KI_PROC(k)->p_stime.tv_usec;
452 		if (sumrusage) {
453 			secs += k->ki_u.u_cru.ru_utime.tv_sec +
454 				k->ki_u.u_cru.ru_stime.tv_sec;
455 			psecs += k->ki_u.u_cru.ru_utime.tv_usec +
456 				k->ki_u.u_cru.ru_stime.tv_usec;
457 		}
458 		/*
459 		 * round and scale to 100's
460 		 */
461 		psecs = (psecs + 5000) / 10000;
462 		secs += psecs / 100;
463 		psecs = psecs % 100;
464 	}
465 	(void)snprintf(obuff, sizeof(obuff),
466 	    "%3ld:%02ld.%02ld", secs/60, secs%60, psecs);
467 	(void)printf("%*s", v->width, obuff);
468 }
469 
470 double
471 getpcpu(k)
472 	KINFO *k;
473 {
474 	extern fixpt_t ccpu;
475 	extern int fscale, nlistread, rawcpu;
476 	struct proc *p;
477 	static int failure;
478 
479 	if (!nlistread)
480 		failure = donlist();
481 	if (failure)
482 		return (0.0);
483 
484 	p = KI_PROC(k);
485 #define	fxtofl(fixpt)	((double)(fixpt) / fscale)
486 
487 	/* XXX - I don't like this */
488 	if (p->p_time == 0 || (p->p_flag & SLOAD) == 0)
489 		return (0.0);
490 	if (rawcpu)
491 		return (100.0 * fxtofl(p->p_pctcpu));
492 	return (100.0 * fxtofl(p->p_pctcpu) /
493 		(1.0 - exp(p->p_time * log(fxtofl(ccpu)))));
494 }
495 
496 void
497 pcpu(k, ve)
498 	KINFO *k;
499 	VARENT *ve;
500 {
501 	VAR *v;
502 
503 	v = ve->var;
504 	(void)printf("%*.1f", v->width, getpcpu(k));
505 }
506 
507 double
508 getpmem(k)
509 	KINFO *k;
510 {
511 	extern int mempages, nlistread;
512 	static int failure;
513 	struct proc *p;
514 	struct eproc *e;
515 	double fracmem;
516 	int szptudot;
517 
518 	if (!nlistread)
519 		failure = donlist();
520 	if (failure)
521 		return (0.0);
522 
523 	p = KI_PROC(k);
524 	e = KI_EPROC(k);
525 	if ((p->p_flag & SLOAD) == 0)
526 		return (0.0);
527 #ifndef NEWVM
528 	szptudot = UPAGES + clrnd(ctopt(p->p_dsize + p->p_ssize + e->e_xsize));
529 	fracmem = ((float)p->p_rssize + szptudot)/CLSIZE/mempages;
530 	if (p->p_textp && e->e_xccount)
531 		fracmem += ((float)e->e_xrssize)/CLSIZE/e->e_xccount/mempages;
532 #else /* NEWVM */
533 	/* XXX want pmap ptpages, segtab, etc. (per architecture) */
534 	szptudot = UPAGES;
535 	/* XXX don't have info about shared */
536 	fracmem = ((float)e->e_vm.vm_rssize + szptudot)/CLSIZE/mempages;
537 #endif /* NEWVM */
538 	return (100.0 * fracmem);
539 }
540 
541 void
542 pmem(k, ve)
543 	KINFO *k;
544 	VARENT *ve;
545 {
546 	VAR *v;
547 
548 	v = ve->var;
549 	(void)printf("%*.1f", v->width, getpmem(k));
550 }
551 
552 void
553 pagein(k, ve)
554 	KINFO *k;
555 	VARENT *ve;
556 {
557 	VAR *v;
558 
559 	v = ve->var;
560 	(void)printf("%*d", v->width,
561 	    k->ki_u.u_valid ? k->ki_u.u_ru.ru_majflt : 0);
562 }
563 
564 void
565 maxrss(k, ve)
566 	KINFO *k;
567 	VARENT *ve;
568 {
569 	VAR *v;
570 
571 	v = ve->var;
572 #ifndef NEWVM	/* not yet */
573 	if (KI_PROC(k)->p_maxrss != (RLIM_INFINITY/NBPG))
574 		(void)printf("%*d", v->width, pgtok(KI_PROC(k)->p_maxrss));
575 	else
576 #endif /* NEWVM */
577 		(void)printf("%*s", v->width, "-");
578 }
579 
580 void
581 tsize(k, ve)
582 	KINFO *k;
583 	VARENT *ve;
584 {
585 	VAR *v;
586 
587 	v = ve->var;
588 #ifndef NEWVM
589 	(void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_xsize));
590 #else /* NEWVM */
591 	(void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_vm.vm_tsize));
592 #endif /* NEWVM */
593 }
594 
595 #ifndef NEWVM
596 void
597 trss(k, ve)
598 	KINFO *k;
599 	VARENT *ve;
600 {
601 	VAR *v;
602 
603 	v = ve->var;
604 	(void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_xrssize));
605 }
606 #endif /* NEWVM */
607 
608 /*
609  * Generic output routines.  Print fields from various prototype
610  * structures.
611  */
612 void
613 pvar(k, ve)
614 	KINFO *k;
615 	VARENT *ve;
616 {
617 	VAR *v;
618 
619 	v = ve->var;
620 	printval((char *)((char *)KI_PROC(k) + v->off), v);
621 }
622 
623 void
624 evar(k, ve)
625 	KINFO *k;
626 	VARENT *ve;
627 {
628 	VAR *v;
629 
630 	v = ve->var;
631 	printval((char *)((char *)KI_EPROC(k) + v->off), v);
632 }
633 
634 void
635 uvar(k, ve)
636 	KINFO *k;
637 	VARENT *ve;
638 {
639 	VAR *v;
640 
641 	v = ve->var;
642 	if (k->ki_u.u_valid)
643 		printval((char *)((char *)&k->ki_u + v->off), v);
644 	else
645 		(void)printf("%*s", v->width, "-");
646 }
647 
648 void
649 rvar(k, ve)
650 	KINFO *k;
651 	VARENT *ve;
652 {
653 	VAR *v;
654 
655 	v = ve->var;
656 	if (k->ki_u.u_valid)
657 		printval((char *)((char *)(&k->ki_u.u_ru) + v->off), v);
658 	else
659 		(void)printf("%*s", v->width, "-");
660 }
661 
662 static void
663 printval(bp, v)
664 	char *bp;
665 	VAR *v;
666 {
667 	static char ofmt[32] = "%";
668 	register char *fcp, *cp;
669 
670 	cp = ofmt + 1;
671 	fcp = v->fmt;
672 	if (v->flag & LJUST)
673 		*cp++ = '-';
674 	*cp++ = '*';
675 	while (*cp++ = *fcp++);
676 
677 	switch (v->type) {
678 	case CHAR:
679 		(void)printf(ofmt, v->width, *(char *)bp);
680 		break;
681 	case UCHAR:
682 		(void)printf(ofmt, v->width, *(u_char *)bp);
683 		break;
684 	case SHORT:
685 		(void)printf(ofmt, v->width, *(short *)bp);
686 		break;
687 	case USHORT:
688 		(void)printf(ofmt, v->width, *(u_short *)bp);
689 		break;
690 	case LONG:
691 		(void)printf(ofmt, v->width, *(long *)bp);
692 		break;
693 	case ULONG:
694 		(void)printf(ofmt, v->width, *(u_long *)bp);
695 		break;
696 	case KPTR:
697 		(void)printf(ofmt, v->width, *(u_long *)bp &~ KERNBASE);
698 		break;
699 	default:
700 		err("unknown type %d", v->type);
701 	}
702 }
703