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