print.c revision 1.10 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.10 1994/05/05 02:04:30 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_pri - 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_utime.tv_sec +
425 k->ki_p->p_stime.tv_sec;
426 psecs = k->ki_p->p_utime.tv_usec +
427 k->ki_p->p_stime.tv_usec;
428 if (sumrusage) {
429 secs += k->ki_u->u_cru.ru_utime.tv_sec +
430 k->ki_u->u_cru.ru_stime.tv_sec;
431 psecs += k->ki_u->u_cru.ru_utime.tv_usec +
432 k->ki_u->u_cru.ru_stime.tv_usec;
433 }
434 /*
435 * round and scale to 100's
436 */
437 psecs = (psecs + 5000) / 10000;
438 secs += psecs / 100;
439 psecs = psecs % 100;
440 }
441 (void) sprintf(obuff, "%3ld:%02ld.%02ld", secs/60, secs%60, psecs);
442 (void) printf("%*s", v->width, obuff);
443 }
444
445 double
446 getpcpu(k)
447 KINFO *k;
448 {
449 extern fixpt_t ccpu;
450 extern int fscale, nlistread, rawcpu;
451 struct proc *p;
452 static int failure;
453
454 if (!nlistread)
455 failure = donlist();
456 if (failure)
457 return (0.0);
458
459 p = k->ki_p;
460 #define fxtofl(fixpt) ((double)(fixpt) / fscale)
461
462 /* XXX - I don't like this */
463 if (p->p_time == 0 || (p->p_stat == SZOMB) || (p->p_flag & P_INMEM) == 0)
464 return (0.0);
465 if (rawcpu)
466 return (100.0 * fxtofl(p->p_pctcpu));
467 return (100.0 * fxtofl(p->p_pctcpu) /
468 (1.0 - exp(p->p_time * log(fxtofl(ccpu)))));
469 }
470
471 pcpu(k, v)
472 KINFO *k;
473 VAR *v;
474 {
475 (void) printf("%*.1f", v->width, getpcpu(k));
476 }
477
478 double
479 getpmem(k)
480 KINFO *k;
481 {
482 extern int mempages, nlistread;
483 static int failure;
484 struct proc *p;
485 struct eproc *e;
486 double fracmem;
487 int szptudot;
488
489 if (!nlistread)
490 failure = donlist();
491 if (failure)
492 return (0.0);
493
494 p = k->ki_p;
495 e = k->ki_e;
496 if ((p->p_flag & P_INMEM) == 0 || (p->p_stat == SZOMB))
497 return (0.0);
498 #ifndef NEWVM
499 szptudot = UPAGES + clrnd(ctopt(p->p_dsize + p->p_ssize + e->e_xsize));
500 fracmem = ((float)p->p_rssize + szptudot)/CLSIZE/mempages;
501 if (p->p_textp && e->e_xccount)
502 fracmem += ((float)e->e_xrssize)/CLSIZE/e->e_xccount/mempages;
503 #else /* NEWVM */
504 /* XXX want pmap ptpages, segtab, etc. (per architecture) */
505 szptudot = UPAGES;
506 /* XXX don't have info about shared */
507 fracmem = ((float)e->e_vm.vm_rssize + szptudot)/CLSIZE/mempages;
508 #endif /* NEWVM */
509 return (100.0 * fracmem);
510 }
511
512 pmem(k, v)
513 KINFO *k;
514 VAR *v;
515 {
516 (void) printf("%*.1f", v->width, getpmem(k));
517 }
518
519 pagein(k, v)
520 KINFO *k;
521 VAR *v;
522 {
523 (void) printf("%*d", v->width, k->ki_u ? k->ki_u->u_ru.ru_majflt : 0);
524 }
525
526 maxrss(k, v)
527 KINFO *k;
528 VAR *v;
529 {
530 #ifndef NEWVM /* not yet */
531 if (k->ki_p->p_maxrss != (RLIM_INFINITY/NBPG))
532 (void) printf("%*d", v->width, pgtok(k->ki_p->p_maxrss));
533 else
534 #endif /* NEWVM */
535 (void) printf("%*s", v->width, "-");
536 }
537
538 tsize(k, v)
539 KINFO *k;
540 VAR *v;
541 {
542 #ifndef NEWVM
543 (void) printf("%*d", v->width, pgtok(k->ki_e->e_xsize));
544 #else /* NEWVM */
545 (void) printf("%*d", v->width, pgtok(k->ki_e->e_vm.vm_tsize));
546 #endif /* NEWVM */
547 }
548
549 #ifndef NEWVM
550 trss(k, v)
551 KINFO *k;
552 VAR *v;
553 {
554 (void) printf("%*d", v->width, pgtok(k->ki_e->e_xrssize));
555 }
556 #endif /* NEWVM */
557
558 /*
559 * Generic output routines. Print fields from various prototype
560 * structures.
561 */
562 pvar(k, v)
563 KINFO *k;
564 VAR *v;
565 {
566 printval((char *)((char *)k->ki_p + v->off), v);
567 }
568
569 evar(k, v)
570 KINFO *k;
571 VAR *v;
572 {
573 printval((char *)((char *)k->ki_e + v->off), v);
574 }
575
576 uvar(k, v)
577 KINFO *k;
578 VAR *v;
579 {
580 if (k->ki_u)
581 printval((char *)((char *)k->ki_u + v->off), v);
582 else
583 (void) printf("%*s", v->width, "-");
584 }
585
586 rvar(k, v)
587 KINFO *k;
588 VAR *v;
589 {
590 if (k->ki_u)
591 printval((char *)((char *)(&k->ki_u->u_ru) + v->off), v);
592 else
593 (void) printf("%*s", v->width, "-");
594 }
595
596 printval(bp, v)
597 char *bp;
598 VAR *v;
599 {
600 static char ofmt[32] = "%";
601 register char *cp = ofmt+1, *fcp = v->fmt;
602
603 if (v->flag & LJUST)
604 *cp++ = '-';
605 *cp++ = '*';
606 while (*cp++ = *fcp++);
607
608 switch (v->type) {
609 case CHAR:
610 (void) printf(ofmt, v->width, *(char *)bp);
611 break;
612 case UCHAR:
613 (void) printf(ofmt, v->width, *(u_char *)bp);
614 break;
615 case SHORT:
616 (void) printf(ofmt, v->width, *(short *)bp);
617 break;
618 case USHORT:
619 (void) printf(ofmt, v->width, *(u_short *)bp);
620 break;
621 case LONG:
622 (void) printf(ofmt, v->width, *(long *)bp);
623 break;
624 case ULONG:
625 (void) printf(ofmt, v->width, *(u_long *)bp);
626 break;
627 case KPTR:
628 (void) printf(ofmt, v->width, *(u_long *)bp &~ KERNBASE);
629 break;
630 default:
631 err("unknown type %d", v->type);
632 }
633 }
634