xref: /original-bsd/bin/ps/print.c (revision 6884d44a)
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.5 (Berkeley) 03/27/91";
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 <tzfile.h>
19 #include <stddef.h>
20 #include <string.h>
21 #include "ps.h"
22 
23 #ifdef SPPWAIT
24 #define NEWVM
25 #endif
26 
27 #ifdef NEWVM
28 #include <vm/vm.h>
29 #include <sys/ucred.h>
30 #include <sys/kinfo_proc.h>
31 #else
32 #include <machine/pte.h>
33 #include <sys/vmparam.h>
34 #include <sys/vm.h>
35 #endif
36 
37 printheader()
38 {
39 	register VAR *v;
40 	register struct varent *vent;
41 
42 	for (vent = vhead; vent; vent = vent->next) {
43 		v = vent->var;
44 		if (v->flag & LJUST) {
45 			if (vent->next == NULL)	/* last one */
46 				(void) printf("%s", v->header);
47 			else
48 				(void) printf("%-*s", v->width, v->header);
49 		} else
50 			(void) printf("%*s", v->width, v->header);
51 		if (vent->next != NULL)
52 			(void) putchar(' ');
53 	}
54 	(void) putchar('\n');
55 }
56 
57 command(k, v, next)
58 	KINFO *k;
59 	VAR *v;
60 {
61 	extern int termwidth, totwidth;
62 
63 	if (next == NULL) {
64 		/* last field */
65 		if (termwidth == UNLIMITED)
66 			(void) printf("%s", k->ki_args);
67 		else {
68 			register int left = termwidth - (totwidth - v->width);
69 			register char *cp = k->ki_args;
70 
71 			if (left < 1) /* already wrapped, just use std width */
72 				left = v->width;
73 			while (--left >= 0 && *cp)
74 				(void) putchar(*cp++);
75 		}
76 	} else
77 		(void) printf("%-*.*s", v->width, v->width, k->ki_args);
78 
79 }
80 
81 ucomm(k, v)
82 	KINFO *k;
83 	VAR *v;
84 {
85 	(void) printf("%-*s", v->width, k->ki_p->p_comm);
86 }
87 
88 logname(k, v)
89 	KINFO *k;
90 	VAR *v;
91 {
92 #ifndef NEWVM
93 	(void) printf("%-*s", v->width, k->ki_p->p_logname);
94 #else /* NEWVM */
95 	(void) printf("%-*s", v->width, k->ki_e->e_login);
96 #endif /* NEWVM */
97 }
98 
99 state(k, v)
100 	KINFO *k;
101 	VAR *v;
102 {
103 	char buf[16];
104 	register char *cp = buf;
105 	register struct proc *p = k->ki_p;
106 	register flag = p->p_flag;
107 
108 	switch (p->p_stat) {
109 
110 	case SSTOP:
111 		*cp = 'T';
112 		break;
113 
114 	case SSLEEP:
115 		if (flag & SSINTR)	/* interuptable (long) */
116 			*cp = p->p_slptime >= MAXSLP ? 'I' : 'S';
117 		else
118 			*cp = (flag & SPAGE) ? 'P' : 'D';
119 		break;
120 
121 	case SRUN:
122 	case SIDL:
123 		*cp = 'R';
124 		break;
125 
126 	case SZOMB:
127 		*cp = 'Z';
128 		break;
129 
130 	default:
131 		*cp = '?';
132 	}
133 	cp++;
134 	if (flag & SLOAD) {
135 #ifndef NEWVM
136 		if (p->p_rssize > p->p_maxrss)
137 			*cp++ = '>';
138 #endif
139 	} else
140 		*cp++ = 'W';
141 	if (p->p_nice < NZERO)
142 		*cp++ = '<';
143 	else if (p->p_nice > NZERO)
144 		*cp++ = 'N';
145 	if (flag & SUANOM)
146 		*cp++ = 'A';
147 	else if (flag & SSEQL)
148 		*cp++ = 'S';
149 	if (flag & STRC)
150 		*cp++ = 'X';
151 	if (flag & SWEXIT && p->p_stat != SZOMB)
152 		*cp++ = 'E';
153 #ifdef NEWVM
154 	if (flag & SPPWAIT)
155 #else
156 	if (flag & SVFORK)
157 #endif
158 		*cp++ = 'V';
159 	if (flag & (SSYS|SLOCK|SULOCK|SKEEP|SPHYSIO))
160 		*cp++ = 'L';
161 	if (k->ki_e->e_flag & EPROC_SLEADER)
162 		*cp++ = 's';
163 	if ((flag & SCTTY) && k->ki_e->e_pgid == k->ki_e->e_tpgid)
164 		*cp++ = '+';
165 	*cp = '\0';
166 	(void) printf("%-*s", v->width, buf);
167 }
168 
169 pri(k, v)
170 	KINFO *k;
171 	VAR *v;
172 {
173 	(void) printf("%*d", v->width, k->ki_p->p_pri - PZERO);
174 }
175 
176 uname(k, v)
177 	KINFO *k;
178 	VAR *v;
179 {
180 #ifndef NEWVM
181 	(void) printf("%-*s", v->width, user_from_uid(k->ki_p->p_uid, 0));
182 #else /* NEWVM */
183 	(void) printf("%-*s", v->width,
184 		user_from_uid(k->ki_e->e_ucred.cr_uid, 0));
185 #endif /* NEWVM */
186 }
187 
188 runame(k, v)
189 	KINFO *k;
190 	VAR *v;
191 {
192 #ifndef NEWVM
193 	(void) printf("%-*s", v->width, user_from_uid(k->ki_p->p_ruid, 0));
194 #else /* NEWVM */
195 	(void) printf("%-*s", v->width,
196 		user_from_uid(k->ki_e->e_pcred.p_ruid, 0));
197 #endif /* NEWVM */
198 }
199 
200 tdev(k, v)
201 	KINFO *k;
202 	VAR *v;
203 {
204 	dev_t dev = k->ki_e->e_tdev;
205 
206 	if (dev == NODEV)
207 		(void) printf("%*s", v->width, "??");
208 	else {
209 		char buff[16];
210 
211 		(void) sprintf(buff, "%d/%d", major(dev), minor(dev));
212 		(void) printf("%*s", v->width, buff);
213 	}
214 }
215 
216 tname(k, v)
217 	KINFO *k;
218 	VAR *v;
219 {
220 	dev_t dev;
221 	char *ttname, *devname();
222 
223 	dev = k->ki_e->e_tdev;
224 	if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
225 		(void) printf("%-*s", v->width, "??");
226 	else {
227 		if (strncmp(ttname, "tty", 3) == 0)
228 			ttname += 3;
229 		(void) printf("%*.*s%c", v->width-1, v->width-1, ttname,
230 			k->ki_e->e_flag & EPROC_CTTY ? ' ' : '-');
231 	}
232 }
233 
234 longtname(k, v)
235 	KINFO *k;
236 	VAR *v;
237 {
238 	dev_t dev;
239 	char *ttname, *devname();
240 
241 	dev = k->ki_e->e_tdev;
242 	if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
243 		(void) printf("%-*s", v->width, "??");
244 	else
245 		(void) printf("%-*s", v->width, ttname);
246 }
247 
248 started(k, v)
249 	KINFO *k;
250 	VAR *v;
251 {
252 	static time_t now;
253 	struct tm *tp;
254 	char buf[100];
255 
256 	if (!k->ki_u) {
257 		(void) printf("%-*s", v->width, "-");
258 		return;
259 	}
260 
261 	tp = localtime(&k->ki_u->u_start.tv_sec);
262 	if (!now)
263 		(void)time(&now);
264 	if (now - k->ki_u->u_start.tv_sec < 24 * SECSPERHOUR) {
265 		static char *fmt = "%l:@M%p";
266 		fmt[3] = '%';			/* I *hate* SCCS... */
267 		(void) strftime(buf, sizeof(buf) - 1, fmt, tp);
268 	} else if (now - k->ki_u->u_start.tv_sec < 7 * SECSPERDAY) {
269 		static char *fmt = "%a@I%p";
270 		fmt[2] = '%';			/* I *hate* SCCS... */
271 		(void) strftime(buf, sizeof(buf) - 1, fmt, tp);
272 	} else
273 		(void) strftime(buf, sizeof(buf) - 1, "%e%b%y", tp);
274 	(void) printf("%-*s", v->width, buf);
275 }
276 
277 lstarted(k, v)
278 	KINFO *k;
279 	VAR *v;
280 {
281 	char buf[100];
282 
283 	if (!k->ki_u) {
284 		(void) printf("%-*s", v->width, "-");
285 		return;
286 	}
287 	(void) strftime(buf, sizeof(buf) -1, "%C",
288 	    localtime(&k->ki_u->u_start.tv_sec));
289 	(void) printf("%-*s", v->width, buf);
290 }
291 
292 wchan(k, v)
293 	KINFO *k;
294 	VAR *v;
295 {
296 	if (k->ki_p->p_wchan) {
297 		if (k->ki_p->p_wmesg)
298 			(void) printf("%-*.*s", v->width, v->width, k->ki_e->e_wmesg);
299 		else
300 			(void) printf("%*x", v->width,
301 			    (int)k->ki_p->p_wchan &~ KERNBASE);
302 	} else
303 		(void) printf("%-*s", v->width, "-");
304 }
305 
306 #define pgtok(a)        (((a)*NBPG)/1024)
307 
308 vsize(k, v)
309 	KINFO *k;
310 	VAR *v;
311 {
312 	(void) printf("%*d", v->width,
313 #ifndef NEWVM
314 	    pgtok(k->ki_p->p_dsize + k->ki_p->p_ssize + k->ki_e->e_xsize));
315 #else /* NEWVM */
316 	    pgtok(k->ki_e->e_vm.vm_dsize + k->ki_e->e_vm.vm_ssize +
317 		k->ki_e->e_vm.vm_tsize));
318 #endif /* NEWVM */
319 }
320 
321 rssize(k, v)
322 	KINFO *k;
323 	VAR *v;
324 {
325 #ifndef NEWVM
326 	(void) printf("%*d", v->width,
327 	    pgtok(k->ki_p->p_rssize + (k->ki_e->e_xccount ?
328 	    (k->ki_e->e_xrssize / k->ki_e->e_xccount) : 0)));
329 #else /* NEWVM */
330 	/* XXX don't have info about shared */
331 	(void) printf("%*d", v->width, pgtok(k->ki_e->e_vm.vm_rssize));
332 #endif /* NEWVM */
333 }
334 
335 p_rssize(k, v)		/* doesn't account for text */
336 	KINFO *k;
337 	VAR *v;
338 {
339 #ifndef NEWVM
340 	(void) printf("%*d", v->width, pgtok(k->ki_p->p_rssize));
341 #else /* NEWVM */
342 	(void) printf("%*d", v->width, pgtok(k->ki_e->e_vm.vm_rssize));
343 #endif /* NEWVM */
344 }
345 
346 cputime(k, v)
347 	KINFO *k;
348 	VAR *v;
349 {
350 	extern int sumrusage;
351 	long secs;
352 	long psecs;	/* "parts" of a second. first micro, then centi */
353 	char obuff[128];
354 
355 	if (k->ki_p->p_stat == SZOMB || k->ki_u == NULL) {
356 		secs = 0;
357 		psecs = 0;
358 	} else {
359 		secs = k->ki_p->p_utime.tv_sec +
360 			k->ki_p->p_stime.tv_sec;
361 		psecs = k->ki_p->p_utime.tv_usec +
362 			k->ki_p->p_stime.tv_usec;
363 		if (sumrusage) {
364 			secs += k->ki_u->u_cru.ru_utime.tv_sec +
365 				k->ki_u->u_cru.ru_stime.tv_sec;
366 			psecs += k->ki_u->u_cru.ru_utime.tv_usec +
367 				k->ki_u->u_cru.ru_stime.tv_usec;
368 		}
369 		/*
370 		 * round and scale to 100's
371 		 */
372 		psecs = (psecs + 5000) / 10000;
373 		secs += psecs / 100;
374 		psecs = psecs % 100;
375 	}
376 	(void) sprintf(obuff, "%3ld:%02ld.%02ld", secs/60, secs%60, psecs);
377 	(void) printf("%*s", v->width, obuff);
378 }
379 
380 double
381 getpcpu(k)
382 	KINFO *k;
383 {
384 	extern fixpt_t ccpu;
385 	extern int fscale, nlistread, rawcpu;
386 	struct proc *p;
387 	static int failure;
388 
389 	if (!nlistread)
390 		failure = donlist();
391 	if (failure)
392 		return (0.0);
393 
394 	p = k->ki_p;
395 #define	fxtofl(fixpt)	((double)(fixpt) / fscale)
396 
397 	/* XXX - I don't like this */
398 	if (p->p_time == 0 || (p->p_flag & SLOAD) == 0)
399 		return (0.0);
400 	if (rawcpu)
401 		return (100.0 * fxtofl(p->p_pctcpu));
402 	return (100.0 * fxtofl(p->p_pctcpu) /
403 		(1.0 - exp(p->p_time * log(fxtofl(ccpu)))));
404 }
405 
406 pcpu(k, v)
407 	KINFO *k;
408 	VAR *v;
409 {
410 	(void) printf("%*.1f", v->width, getpcpu(k));
411 }
412 
413 double
414 getpmem(k)
415 	KINFO *k;
416 {
417 	extern int ecmx, nlistread;
418 	static int failure;
419 	struct proc *p;
420 	struct eproc *e;
421 	double fracmem;
422 	int szptudot;
423 
424 	if (!nlistread)
425 		failure = donlist();
426 	if (failure)
427 		return (0.0);
428 
429 	p = k->ki_p;
430 	e = k->ki_e;
431 	if ((p->p_flag & SLOAD) == 0)
432 		return (0.0);
433 #ifndef NEWVM
434 	szptudot = UPAGES + clrnd(ctopt(p->p_dsize + p->p_ssize + e->e_xsize));
435 	fracmem = ((float)p->p_rssize + szptudot)/CLSIZE/ecmx;
436 	if (p->p_textp && e->e_xccount)
437 		fracmem += ((float)e->e_xrssize)/CLSIZE/e->e_xccount/ecmx;
438 #else /* NEWVM */
439 	/* XXX want pmap ptpages, segtab, etc. (per architecture) */
440 	szptudot = UPAGES;
441 	/* XXX don't have info about shared */
442 	fracmem = ((float)e->e_vm.vm_rssize + szptudot)/CLSIZE/ecmx;
443 #endif /* NEWVM */
444 	return (100.0 * fracmem);
445 }
446 
447 pmem(k, v)
448 	KINFO *k;
449 	VAR *v;
450 {
451 	(void) printf("%*.1f", v->width, getpmem(k));
452 }
453 
454 pagein(k, v)
455 	KINFO *k;
456 	VAR *v;
457 {
458 	(void) printf("%*d", v->width, k->ki_u ? k->ki_u->u_ru.ru_majflt : 0);
459 }
460 
461 maxrss(k, v)
462 	KINFO *k;
463 	VAR *v;
464 {
465 #ifndef NEWVM	/* not yet */
466 	if (k->ki_p->p_maxrss != (RLIM_INFINITY/NBPG))
467 		(void) printf("%*d", v->width, pgtok(k->ki_p->p_maxrss));
468 	else
469 #endif /* NEWVM */
470 		(void) printf("%*s", v->width, "-");
471 }
472 
473 tsize(k, v)
474 	KINFO *k;
475 	VAR *v;
476 {
477 #ifndef NEWVM
478 	(void) printf("%*d", v->width, pgtok(k->ki_e->e_xsize));
479 #else /* NEWVM */
480 	(void) printf("%*d", v->width, pgtok(k->ki_e->e_vm.vm_tsize));
481 #endif /* NEWVM */
482 }
483 
484 #ifndef NEWVM
485 trss(k, v)
486 	KINFO *k;
487 	VAR *v;
488 {
489 	(void) printf("%*d", v->width, pgtok(k->ki_e->e_xrssize));
490 }
491 #endif /* NEWVM */
492 
493 /*
494  * Generic output routines.  Print fields from various prototype
495  * structures.
496  */
497 pvar(k, v)
498 	KINFO *k;
499 	VAR *v;
500 {
501 	printval((char *)((char *)k->ki_p + v->off), v);
502 }
503 
504 evar(k, v)
505 	KINFO *k;
506 	VAR *v;
507 {
508 	printval((char *)((char *)k->ki_e + v->off), v);
509 }
510 
511 uvar(k, v)
512 	KINFO *k;
513 	VAR *v;
514 {
515 	if (k->ki_u)
516 		printval((char *)((char *)k->ki_u + v->off), v);
517 	else
518 		(void) printf("%*s", v->width, "-");
519 }
520 
521 rvar(k, v)
522 	KINFO *k;
523 	VAR *v;
524 {
525 	if (k->ki_u)
526 		printval((char *)((char *)(&k->ki_u->u_ru) + v->off), v);
527 	else
528 		(void) printf("%*s", v->width, "-");
529 }
530 
531 printval(bp, v)
532 	char *bp;
533 	VAR *v;
534 {
535 	static char ofmt[32] = "%";
536 	register char *cp = ofmt+1, *fcp = v->fmt;
537 
538 	if (v->flag & LJUST)
539 		*cp++ = '-';
540 	*cp++ = '*';
541 	while (*cp++ = *fcp++);
542 
543 	switch (v->type) {
544 	case CHAR:
545 		(void) printf(ofmt, v->width, *(char *)bp);
546 		break;
547 	case UCHAR:
548 		(void) printf(ofmt, v->width, *(u_char *)bp);
549 		break;
550 	case SHORT:
551 		(void) printf(ofmt, v->width, *(short *)bp);
552 		break;
553 	case USHORT:
554 		(void) printf(ofmt, v->width, *(u_short *)bp);
555 		break;
556 	case LONG:
557 		(void) printf(ofmt, v->width, *(long *)bp);
558 		break;
559 	case ULONG:
560 		(void) printf(ofmt, v->width, *(u_long *)bp);
561 		break;
562 	case KPTR:
563 		(void) printf(ofmt, v->width, *(u_long *)bp &~ KERNBASE);
564 		break;
565 	default:
566 		error("unknown type %d", v->type);
567 	}
568 }
569