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