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