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