Commit | Line | Data |
---|---|---|
984263bc MD |
1 | /*- |
2 | * Copyright (c) 1990, 1993, 1994 | |
3 | * The Regents of the University of California. 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. | |
dc71b7ab | 13 | * 3. Neither the name of the University nor the names of its contributors |
984263bc MD |
14 | * may be used to endorse or promote products derived from this software |
15 | * without specific prior written permission. | |
16 | * | |
17 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
27 | * SUCH DAMAGE. | |
1de703da MD |
28 | * |
29 | * @(#)print.c 8.6 (Berkeley) 4/16/94 | |
30 | * $FreeBSD: src/bin/ps/print.c,v 1.36.2.4 2002/11/30 13:00:14 tjr Exp $ | |
b0f7704a | 31 | * $DragonFly: src/bin/ps/print.c,v 1.34 2008/11/10 14:56:33 swildner Exp $ |
984263bc MD |
32 | */ |
33 | ||
e0ecab34 | 34 | #include <sys/user.h> |
984263bc MD |
35 | #include <sys/param.h> |
36 | #include <sys/time.h> | |
37 | #include <sys/resource.h> | |
984263bc MD |
38 | #include <sys/stat.h> |
39 | ||
40 | #include <sys/ucred.h> | |
984263bc | 41 | #include <sys/sysctl.h> |
17c88c3a | 42 | #include <sys/rtprio.h> |
2b3f93ea | 43 | #include <sys/caps.h> |
984263bc MD |
44 | #include <vm/vm.h> |
45 | ||
46 | #include <err.h> | |
47 | #include <langinfo.h> | |
48 | #include <locale.h> | |
49 | #include <math.h> | |
50 | #include <nlist.h> | |
5b0d3e5e | 51 | #include <pwd.h> |
984263bc MD |
52 | #include <stddef.h> |
53 | #include <stdio.h> | |
54 | #include <stdlib.h> | |
55 | #include <unistd.h> | |
56 | #include <string.h> | |
57 | #include <vis.h> | |
58 | ||
59 | #include "ps.h" | |
60 | ||
96d518a8 | 61 | static const char *make_printable(const char *str); |
0ca59c34 | 62 | static const char *make_printable2(const char *str); |
e08f663e | 63 | static void put64(u_int64_t n, int w, int type); |
96d518a8 | 64 | |
0ca59c34 SZ |
65 | #define SHOW_THRNAME(k) \ |
66 | (showtid && KI_PROC(k, pid) != -1 && KI_PROC(k, nthreads) > 1) | |
67 | ||
984263bc | 68 | void |
b5744197 | 69 | printheader(void) |
984263bc | 70 | { |
c443019b | 71 | const VAR *v; |
984263bc MD |
72 | struct varent *vent; |
73 | int allempty; | |
74 | ||
75 | allempty = 1; | |
023c70f2 JS |
76 | STAILQ_FOREACH(vent, &var_head, link) { |
77 | if (*vent->header != '\0') { | |
984263bc MD |
78 | allempty = 0; |
79 | break; | |
80 | } | |
023c70f2 | 81 | } |
984263bc MD |
82 | if (allempty) |
83 | return; | |
023c70f2 | 84 | STAILQ_FOREACH(vent, &var_head, link) { |
984263bc MD |
85 | v = vent->var; |
86 | if (v->flag & LJUST) { | |
023c70f2 JS |
87 | if (STAILQ_NEXT(vent, link) == NULL) /* last one */ |
88 | printf("%s", vent->header); | |
984263bc | 89 | else |
023c70f2 | 90 | printf("%-*s", vent->width, vent->header); |
984263bc | 91 | } else |
023c70f2 JS |
92 | printf("%*s", vent->width, vent->header); |
93 | if (STAILQ_NEXT(vent, link) != NULL) | |
f9af826d | 94 | putchar(' '); |
984263bc | 95 | } |
f9af826d | 96 | putchar('\n'); |
984263bc MD |
97 | } |
98 | ||
99 | void | |
023c70f2 | 100 | command(const KINFO *k, const struct varent *vent) |
984263bc | 101 | { |
984263bc | 102 | int left; |
ee5f7d37 | 103 | int indent; |
984263bc MD |
104 | char *cp, *vis_env, *vis_args; |
105 | ||
984263bc | 106 | if (cflag) { |
023c70f2 | 107 | /* Don't pad the last field. */ |
0ca59c34 SZ |
108 | if (STAILQ_NEXT(vent, link) == NULL) { |
109 | if (SHOW_THRNAME(k)) { | |
110 | printf("%s/%s", | |
111 | make_printable(KI_PROC(k, comm)), | |
112 | make_printable2(KI_LWP(k, comm))); | |
113 | } else { | |
114 | printf("%s", make_printable(KI_PROC(k, comm))); | |
115 | } | |
116 | } else { | |
117 | if (SHOW_THRNAME(k)) { | |
118 | printf("%-*s/%s", vent->width, | |
119 | make_printable(KI_PROC(k, comm)), | |
120 | make_printable2(KI_LWP(k, comm))); | |
121 | } else { | |
122 | printf("%-*s", vent->width, | |
123 | make_printable(KI_PROC(k, comm))); | |
124 | } | |
125 | } | |
984263bc MD |
126 | return; |
127 | } | |
128 | ||
129 | if ((vis_args = malloc(strlen(k->ki_args) * 4 + 1)) == NULL) | |
130 | err(1, NULL); | |
131 | strvis(vis_args, k->ki_args, VIS_TAB | VIS_NL | VIS_NOSLASH); | |
132 | if (k->ki_env) { | |
133 | if ((vis_env = malloc(strlen(k->ki_env) * 4 + 1)) == NULL) | |
134 | err(1, NULL); | |
135 | strvis(vis_env, k->ki_env, VIS_TAB | VIS_NL | VIS_NOSLASH); | |
ee5f7d37 | 136 | } else { |
984263bc | 137 | vis_env = NULL; |
ee5f7d37 MD |
138 | } |
139 | ||
140 | indent = k->ki_indent; | |
141 | if (indent < 0) | |
142 | indent = 0; | |
984263bc | 143 | |
023c70f2 | 144 | if (STAILQ_NEXT(vent, link) == NULL) { |
984263bc MD |
145 | /* last field */ |
146 | if (termwidth == UNLIMITED) { | |
147 | if (vis_env) | |
f9af826d | 148 | printf("%s ", vis_env); |
ee5f7d37 MD |
149 | while (indent) { |
150 | putchar(' '); | |
151 | --indent; | |
152 | } | |
f9af826d | 153 | printf("%s", vis_args); |
984263bc | 154 | } else { |
023c70f2 | 155 | left = termwidth - (totwidth - vent->width); |
984263bc | 156 | if (left < 1) /* already wrapped, just use std width */ |
023c70f2 | 157 | left = vent->width; |
ee5f7d37 MD |
158 | while (indent && left > 1) { |
159 | putchar(' '); | |
160 | --indent; | |
161 | --left; | |
162 | } | |
984263bc MD |
163 | if ((cp = vis_env) != NULL) { |
164 | while (--left >= 0 && *cp) | |
f9af826d | 165 | putchar(*cp++); |
984263bc MD |
166 | if (--left >= 0) |
167 | putchar(' '); | |
168 | } | |
169 | for (cp = vis_args; --left >= 0 && *cp != '\0';) | |
f9af826d | 170 | putchar(*cp++); |
984263bc MD |
171 | } |
172 | } else | |
173 | /* XXX env? */ | |
023c70f2 | 174 | printf("%-*.*s", vent->width, vent->width, vis_args); |
984263bc MD |
175 | free(vis_args); |
176 | if (vis_env != NULL) | |
177 | free(vis_env); | |
178 | } | |
179 | ||
180 | void | |
023c70f2 | 181 | ucomm(const KINFO *k, const struct varent *vent) |
984263bc | 182 | { |
6d44fd16 | 183 | /* Do not pad the last field */ |
0ca59c34 SZ |
184 | if (STAILQ_NEXT(vent, link) == NULL) { |
185 | if (SHOW_THRNAME(k)) { | |
186 | printf("%s/%s", make_printable(KI_PROC(k, comm)), | |
187 | make_printable2(KI_LWP(k, comm))); | |
188 | } else { | |
189 | printf("%s", make_printable(KI_PROC(k, comm))); | |
190 | } | |
191 | } else { | |
192 | if (SHOW_THRNAME(k)) { | |
193 | printf("%-*s/%s", vent->width, | |
194 | make_printable(KI_PROC(k, comm)), | |
195 | make_printable2(KI_LWP(k, comm))); | |
196 | } else { | |
197 | printf("%-*s", vent->width, | |
198 | make_printable(KI_PROC(k, comm))); | |
199 | } | |
200 | } | |
984263bc MD |
201 | } |
202 | ||
203 | void | |
023c70f2 | 204 | logname(const KINFO *k, const struct varent *vent) |
984263bc | 205 | { |
5dfd06ac | 206 | const char *s = KI_PROC(k, login); |
984263bc | 207 | |
023c70f2 | 208 | printf("%-*s", vent->width, *s != '\0' ? s : "-"); |
984263bc MD |
209 | } |
210 | ||
211 | void | |
023c70f2 | 212 | state(const KINFO *k, const struct varent *vent) |
984263bc | 213 | { |
984263bc MD |
214 | int flag; |
215 | char *cp; | |
984263bc MD |
216 | char buf[16]; |
217 | ||
7477b0f6 | 218 | flag = KI_PROC(k, flags); |
984263bc MD |
219 | cp = buf; |
220 | ||
5dfd06ac | 221 | switch (KI_PROC(k, stat)) { |
984263bc MD |
222 | |
223 | case SSTOP: | |
224 | *cp = 'T'; | |
225 | break; | |
226 | ||
164b8401 SS |
227 | case SACTIVE: |
228 | switch (KI_LWP(k, stat)) { | |
229 | case LSSLEEP: | |
4576f6e6 MD |
230 | if (KI_LWP(k, flags) & LWP_SINTR) { |
231 | /* interruptable wait short/long */ | |
164b8401 | 232 | *cp = KI_LWP(k, slptime) >= MAXSLP ? 'I' : 'S'; |
4576f6e6 | 233 | } |
164b8401 | 234 | else if (KI_LWP(k, tdflags) & TDF_SINTR) |
4576f6e6 | 235 | *cp = 'S'; /* interruptable lwkt wait */ |
2ad39b18 | 236 | else if (KI_PROC(k, paddr)) |
4576f6e6 | 237 | *cp = 'D'; /* uninterruptable wait */ |
164b8401 | 238 | else |
4576f6e6 | 239 | *cp = 'B'; /* uninterruptable lwkt wait */ |
4db97fbc | 240 | /* FALLTHROUGH */ |
984263bc | 241 | |
164b8401 | 242 | case LSRUN: |
4e1c727b MD |
243 | if (KI_LWP(k, stat) == LSRUN) { |
244 | *cp = 'R'; | |
245 | if (!(KI_LWP(k, tdflags) & | |
246 | (TDF_RUNNING | TDF_RUNQ))) | |
247 | *++cp = 'Q'; | |
248 | } | |
249 | /*if (KI_LWP(k, tdflags) & (TDF_RUNNING | TDF_RUNQ))*/ { | |
164b8401 SS |
250 | ++cp; |
251 | sprintf(cp, "%d", KI_LWP(k, cpuid)); | |
252 | while (cp[1]) | |
253 | ++cp; | |
254 | } | |
255 | break; | |
984263bc | 256 | |
164b8401 SS |
257 | case LSSTOP: |
258 | /* shouldn't happen anyways */ | |
259 | *cp = 'T'; | |
260 | break; | |
261 | } | |
984263bc MD |
262 | break; |
263 | ||
416d05d7 SS |
264 | case SZOMB: |
265 | *cp = 'Z'; | |
266 | break; | |
267 | ||
984263bc MD |
268 | default: |
269 | *cp = '?'; | |
270 | } | |
164b8401 | 271 | |
984263bc | 272 | cp++; |
344ad853 | 273 | if (flag & P_SWAPPEDOUT) |
984263bc | 274 | *cp++ = 'W'; |
5dfd06ac | 275 | if (KI_PROC(k, nice) < NZERO) |
984263bc | 276 | *cp++ = '<'; |
5dfd06ac | 277 | else if (KI_PROC(k, nice) > NZERO) |
984263bc MD |
278 | *cp++ = 'N'; |
279 | if (flag & P_TRACED) | |
280 | *cp++ = 'X'; | |
416d05d7 | 281 | if (flag & P_WEXIT && KI_PROC(k, stat) != SZOMB) |
984263bc MD |
282 | *cp++ = 'E'; |
283 | if (flag & P_PPWAIT) | |
284 | *cp++ = 'V'; | |
779c5f44 MD |
285 | #if 0 |
286 | /* removed, no longer interesting */ | |
5dfd06ac | 287 | if ((flag & P_SYSTEM) || KI_PROC(k, lock) > 0) |
984263bc | 288 | *cp++ = 'L'; |
779c5f44 | 289 | #endif |
2b3f93ea | 290 | |
18988e7a MD |
291 | if (flag & P_JAILED) |
292 | *cp++ = 'J'; | |
2b3f93ea MD |
293 | if (__KP_SYSCAP_GET(KI_PROC(k, syscaps), SYSCAP_RESTRICTEDROOT) == |
294 | (__SYSCAP_SELF | __SYSCAP_EXEC) && | |
295 | __KP_SYSCAP_GET(KI_PROC(k, syscaps), SYSCAP_SENSITIVEROOT) == | |
296 | (__SYSCAP_SELF | __SYSCAP_EXEC)) | |
297 | { | |
298 | *cp++ = 'Y'; | |
299 | } else | |
300 | if (__KP_SYSCAP_GET(KI_PROC(k, syscaps), SYSCAP_RESTRICTEDROOT) == | |
301 | (__SYSCAP_SELF | __SYSCAP_EXEC)) | |
302 | { | |
303 | *cp++ = 'y'; | |
304 | } | |
5dfd06ac | 305 | if (KI_PROC(k, auxflags) & KI_SLEADER) |
984263bc | 306 | *cp++ = 's'; |
5dfd06ac | 307 | if ((flag & P_CONTROLT) && KI_PROC(k, pgid) == KI_PROC(k, tpgid)) |
984263bc | 308 | *cp++ = '+'; |
984263bc | 309 | *cp = '\0'; |
023c70f2 | 310 | printf("%-*s", vent->width, buf); |
984263bc MD |
311 | } |
312 | ||
cb56579b MD |
313 | /* |
314 | * Normalized priority (lower is better). For pure threads | |
315 | * output a negated LWKT priority (so lower still means better). | |
352f5709 MD |
316 | * |
317 | * XXX bsd4 scheduler specific. | |
cb56579b | 318 | */ |
984263bc | 319 | void |
023c70f2 | 320 | pri(const KINFO *k, const struct varent *vent) |
984263bc | 321 | { |
5dfd06ac SS |
322 | if (KI_LWP(k, pid) != -1) |
323 | printf("%*d", vent->width, KI_LWP(k, prio)); | |
cb56579b | 324 | else |
b580dce7 | 325 | printf("%*d", vent->width, -(KI_LWP(k, tdprio))); |
cb56579b MD |
326 | } |
327 | ||
328 | void | |
329 | tdpri(const KINFO *k, const struct varent *vent) | |
330 | { | |
331 | char buf[32]; | |
5dfd06ac | 332 | int val = KI_LWP(k, tdprio); |
cb56579b | 333 | |
b580dce7 | 334 | snprintf(buf, sizeof(buf), "%2d", val); |
cb56579b | 335 | printf("%*s", vent->width, buf); |
984263bc MD |
336 | } |
337 | ||
338 | void | |
023c70f2 | 339 | uname(const KINFO *k, const struct varent *vent) |
984263bc | 340 | { |
023c70f2 | 341 | printf("%-*s", vent->width, |
5dfd06ac | 342 | user_from_uid(KI_PROC(k, uid), 0)); |
984263bc MD |
343 | } |
344 | ||
345 | int | |
c443019b | 346 | s_uname(const KINFO *k) |
984263bc | 347 | { |
5dfd06ac | 348 | return (strlen(user_from_uid(KI_PROC(k, uid), 0))); |
984263bc MD |
349 | } |
350 | ||
351 | void | |
023c70f2 | 352 | runame(const KINFO *k, const struct varent *vent) |
984263bc | 353 | { |
023c70f2 | 354 | printf("%-*s", vent->width, |
5dfd06ac | 355 | user_from_uid(KI_PROC(k, ruid), 0)); |
984263bc MD |
356 | } |
357 | ||
358 | int | |
c443019b | 359 | s_runame(const KINFO *k) |
984263bc | 360 | { |
5dfd06ac | 361 | return (strlen(user_from_uid(KI_PROC(k, ruid), 0))); |
984263bc MD |
362 | } |
363 | ||
364 | void | |
023c70f2 | 365 | tdev(const KINFO *k, const struct varent *vent) |
984263bc | 366 | { |
984263bc MD |
367 | dev_t dev; |
368 | char buff[16]; | |
369 | ||
5dfd06ac | 370 | dev = KI_PROC(k, tdev); |
984263bc | 371 | if (dev == NODEV) |
023c70f2 | 372 | printf("%*s", vent->width, "??"); |
984263bc | 373 | else { |
023c70f2 JS |
374 | snprintf(buff, sizeof(buff), "%d/%d", major(dev), minor(dev)); |
375 | printf("%*s", vent->width, buff); | |
984263bc MD |
376 | } |
377 | } | |
378 | ||
379 | void | |
023c70f2 | 380 | tname(const KINFO *k, const struct varent *vent) |
984263bc | 381 | { |
984263bc | 382 | dev_t dev; |
023c70f2 | 383 | const char *ttname; |
984263bc | 384 | |
5dfd06ac | 385 | dev = KI_PROC(k, tdev); |
984263bc | 386 | if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL) |
023c70f2 | 387 | printf("%*s ", vent->width-1, "??"); |
984263bc MD |
388 | else { |
389 | if (strncmp(ttname, "tty", 3) == 0 || | |
390 | strncmp(ttname, "cua", 3) == 0) | |
391 | ttname += 3; | |
371de718 SS |
392 | if (strncmp(ttname, "pts/", 4) == 0) |
393 | ttname += 4; | |
023c70f2 | 394 | printf("%*.*s%c", vent->width-1, vent->width-1, ttname, |
5dfd06ac | 395 | KI_PROC(k, auxflags) & KI_CTTY ? ' ' : '-'); |
984263bc MD |
396 | } |
397 | } | |
398 | ||
399 | void | |
023c70f2 | 400 | longtname(const KINFO *k, const struct varent *vent) |
984263bc | 401 | { |
984263bc | 402 | dev_t dev; |
023c70f2 | 403 | const char *ttname; |
984263bc | 404 | |
5dfd06ac | 405 | dev = KI_PROC(k, tdev); |
984263bc | 406 | if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL) |
023c70f2 | 407 | printf("%-*s", vent->width, "??"); |
984263bc | 408 | else |
023c70f2 | 409 | printf("%-*s", vent->width, ttname); |
984263bc MD |
410 | } |
411 | ||
412 | void | |
023c70f2 | 413 | started(const KINFO *k, const struct varent *vent) |
984263bc | 414 | { |
984263bc MD |
415 | static time_t now; |
416 | time_t then; | |
417 | struct tm *tp; | |
418 | char buf[100]; | |
419 | static int use_ampm = -1; | |
420 | ||
984263bc MD |
421 | if (use_ampm < 0) |
422 | use_ampm = (*nl_langinfo(T_FMT_AMPM) != '\0'); | |
423 | ||
5dfd06ac | 424 | then = KI_PROC(k, start).tv_sec; |
d9fa5f67 SS |
425 | if (then < btime.tv_sec) { |
426 | then = btime.tv_sec; | |
0d4b6715 HP |
427 | } |
428 | ||
984263bc MD |
429 | tp = localtime(&then); |
430 | if (!now) | |
f9af826d | 431 | time(&now); |
d9fa5f67 | 432 | if (now - then < 24 * 3600) { |
f9af826d | 433 | strftime(buf, sizeof(buf) - 1, |
984263bc | 434 | use_ampm ? "%l:%M%p" : "%k:%M ", tp); |
d9fa5f67 | 435 | } else if (now - then < 7 * 86400) { |
f9af826d | 436 | strftime(buf, sizeof(buf) - 1, |
984263bc MD |
437 | use_ampm ? "%a%I%p" : "%a%H ", tp); |
438 | } else | |
f9af826d | 439 | strftime(buf, sizeof(buf) - 1, "%e%b%y", tp); |
023c70f2 | 440 | printf("%-*s", vent->width, buf); |
984263bc MD |
441 | } |
442 | ||
443 | void | |
023c70f2 | 444 | lstarted(const KINFO *k, const struct varent *vent) |
984263bc | 445 | { |
984263bc MD |
446 | time_t then; |
447 | char buf[100]; | |
448 | ||
5dfd06ac | 449 | then = KI_PROC(k, start).tv_sec; |
f9af826d | 450 | strftime(buf, sizeof(buf) -1, "%c", localtime(&then)); |
023c70f2 | 451 | printf("%-*s", vent->width, buf); |
984263bc MD |
452 | } |
453 | ||
454 | void | |
023c70f2 | 455 | wchan(const KINFO *k, const struct varent *vent) |
984263bc | 456 | { |
4576f6e6 MD |
457 | if (*KI_LWP(k, wmesg)) { |
458 | printf("%-*.*s", vent->width, vent->width, | |
459 | KI_LWP(k, wmesg)); | |
460 | } else { | |
023c70f2 | 461 | printf("%-*s", vent->width, "-"); |
4576f6e6 | 462 | } |
984263bc MD |
463 | } |
464 | ||
e08f663e MD |
465 | static u_int64_t |
466 | pgtob(u_int64_t pg) | |
467 | { | |
468 | static size_t pgsize; | |
469 | ||
470 | if (pgsize == 0) | |
471 | pgsize = getpagesize(); | |
472 | return(pg * pgsize); | |
473 | } | |
984263bc MD |
474 | |
475 | void | |
023c70f2 | 476 | vsize(const KINFO *k, const struct varent *vent) |
984263bc | 477 | { |
e08f663e | 478 | put64((uintmax_t)KI_PROC(k, vm_map_size)/1024, vent->width, 'k'); |
984263bc MD |
479 | } |
480 | ||
481 | void | |
023c70f2 | 482 | rssize(const KINFO *k, const struct varent *vent) |
984263bc | 483 | { |
984263bc | 484 | /* XXX don't have info about shared */ |
e08f663e | 485 | put64(pgtob(KI_PROC(k, vm_rssize))/1024, vent->width, 'k'); |
984263bc MD |
486 | } |
487 | ||
e08f663e | 488 | /* doesn't account for text */ |
984263bc | 489 | void |
e08f663e | 490 | p_rssize(const KINFO *k, const struct varent *vent) |
984263bc | 491 | { |
e08f663e | 492 | put64(pgtob(KI_PROC(k, vm_rssize))/1024, vent->width, 'k'); |
984263bc MD |
493 | } |
494 | ||
495 | void | |
023c70f2 | 496 | cputime(const KINFO *k, const struct varent *vent) |
984263bc | 497 | { |
984263bc MD |
498 | long secs; |
499 | long psecs; /* "parts" of a second. first micro, then centi */ | |
164b8401 | 500 | u_int64_t timeus; |
984263bc | 501 | char obuff[128]; |
023c70f2 | 502 | static char decimal_point = '\0'; |
984263bc | 503 | |
023c70f2 | 504 | if (decimal_point == '\0') |
984263bc | 505 | decimal_point = localeconv()->decimal_point[0]; |
023c70f2 | 506 | |
164b8401 SS |
507 | /* |
508 | * This counts time spent handling interrupts. We could | |
509 | * fix this, but it is not 100% trivial (and interrupt | |
510 | * time fractions only work on the sparc anyway). XXX | |
511 | */ | |
512 | timeus = KI_LWP(k, uticks) + KI_LWP(k, sticks) + | |
513 | KI_LWP(k, iticks); | |
514 | secs = timeus / 1000000; | |
515 | psecs = timeus % 1000000; | |
516 | if (sumrusage) { | |
517 | secs += KI_PROC(k, cru).ru_utime.tv_sec + | |
518 | KI_PROC(k, cru).ru_stime.tv_sec; | |
519 | psecs += KI_PROC(k, cru).ru_utime.tv_usec + | |
520 | KI_PROC(k, cru).ru_stime.tv_usec; | |
984263bc | 521 | } |
164b8401 SS |
522 | /* |
523 | * round and scale to 100's | |
524 | */ | |
525 | psecs = (psecs + 5000) / 10000; | |
526 | secs += psecs / 100; | |
527 | psecs = psecs % 100; | |
539ed642 MD |
528 | #if 1 |
529 | if (secs >= 86400) { | |
530 | snprintf(obuff, sizeof(obuff), "%3ldd%02ld:%02ld", | |
531 | secs / 86400, secs / (60 * 60) % 24, secs / 60 % 60); | |
532 | } else if (secs >= 100 * 60) { | |
533 | snprintf(obuff, sizeof(obuff), "%2ld:%02ld:%02ld", | |
534 | secs / 60 / 60, secs / 60 % 60, secs % 60); | |
535 | } else | |
536 | #endif | |
537 | { | |
538 | snprintf(obuff, sizeof(obuff), "%3ld:%02ld%c%02ld", | |
539 | secs / 60, secs % 60, | |
540 | decimal_point, psecs); | |
541 | } | |
023c70f2 | 542 | printf("%*s", vent->width, obuff); |
984263bc MD |
543 | } |
544 | ||
545 | double | |
c443019b | 546 | getpcpu(const KINFO *k) |
984263bc | 547 | { |
984263bc MD |
548 | static int failure; |
549 | ||
550 | if (!nlistread) | |
551 | failure = donlist(); | |
552 | if (failure) | |
553 | return (0.0); | |
554 | ||
984263bc MD |
555 | #define fxtofl(fixpt) ((double)(fixpt) / fscale) |
556 | ||
557 | /* XXX - I don't like this */ | |
08f2f1bb | 558 | if (KI_PROC(k, swtime) == 0 || (KI_PROC(k, flags) & P_SWAPPEDOUT)) |
984263bc | 559 | return (0.0); |
0274e76b | 560 | return (100.0 * fxtofl(KI_LWP(k, pctcpu))); |
984263bc MD |
561 | } |
562 | ||
563 | void | |
023c70f2 | 564 | pcpu(const KINFO *k, const struct varent *vent) |
984263bc | 565 | { |
023c70f2 | 566 | printf("%*.1f", vent->width, getpcpu(k)); |
984263bc MD |
567 | } |
568 | ||
17c88c3a | 569 | void |
023c70f2 | 570 | pnice(const KINFO *k, const struct varent *vent) |
17c88c3a | 571 | { |
c443019b | 572 | int niceval; |
17c88c3a | 573 | |
5dfd06ac | 574 | switch (KI_LWP(k, rtprio).type) { |
17c88c3a | 575 | case RTP_PRIO_REALTIME: |
5dfd06ac | 576 | niceval = PRIO_MIN - 1 - RTP_PRIO_MAX + KI_LWP(k, rtprio).prio; |
17c88c3a MD |
577 | break; |
578 | case RTP_PRIO_IDLE: | |
5dfd06ac | 579 | niceval = PRIO_MAX + 1 + KI_LWP(k, rtprio).prio; |
17c88c3a MD |
580 | break; |
581 | case RTP_PRIO_THREAD: | |
5dfd06ac | 582 | niceval = PRIO_MIN - 1 - RTP_PRIO_MAX - KI_LWP(k, rtprio).prio; |
17c88c3a MD |
583 | break; |
584 | default: | |
5dfd06ac | 585 | niceval = KI_PROC(k, nice) - NZERO; |
17c88c3a MD |
586 | break; |
587 | } | |
023c70f2 | 588 | printf("%*d", vent->width, niceval); |
17c88c3a MD |
589 | } |
590 | ||
591 | ||
984263bc | 592 | double |
c443019b | 593 | getpmem(const KINFO *k) |
984263bc MD |
594 | { |
595 | static int failure; | |
984263bc MD |
596 | double fracmem; |
597 | int szptudot; | |
598 | ||
599 | if (!nlistread) | |
600 | failure = donlist(); | |
601 | if (failure) | |
602 | return (0.0); | |
603 | ||
5dfd06ac | 604 | if (KI_PROC(k, flags) & P_SWAPPEDOUT) |
984263bc MD |
605 | return (0.0); |
606 | /* XXX want pmap ptpages, segtab, etc. (per architecture) */ | |
607 | szptudot = UPAGES; | |
608 | /* XXX don't have info about shared */ | |
5dfd06ac | 609 | fracmem = ((float)KI_PROC(k, vm_rssize) + szptudot)/mempages; |
984263bc MD |
610 | return (100.0 * fracmem); |
611 | } | |
612 | ||
613 | void | |
023c70f2 | 614 | pmem(const KINFO *k, const struct varent *vent) |
984263bc | 615 | { |
023c70f2 | 616 | printf("%*.1f", vent->width, getpmem(k)); |
984263bc MD |
617 | } |
618 | ||
619 | void | |
023c70f2 | 620 | pagein(const KINFO *k, const struct varent *vent) |
984263bc | 621 | { |
5dfd06ac | 622 | printf("%*ld", vent->width, KI_LWP(k, ru).ru_majflt); |
984263bc MD |
623 | } |
624 | ||
c443019b | 625 | /* ARGSUSED */ |
984263bc | 626 | void |
023c70f2 | 627 | maxrss(const KINFO *k __unused, const struct varent *vent) |
984263bc | 628 | { |
5dfd06ac | 629 | printf("%*ld", vent->width, KI_PROC(k, ru).ru_maxrss); |
984263bc MD |
630 | } |
631 | ||
632 | void | |
023c70f2 | 633 | tsize(const KINFO *k, const struct varent *vent) |
984263bc | 634 | { |
e08f663e | 635 | put64(pgtob(KI_PROC(k, vm_tsize))/1024, vent->width, 'k'); |
984263bc MD |
636 | } |
637 | ||
638 | void | |
023c70f2 | 639 | rtprior(const KINFO *k, const struct varent *vent) |
984263bc | 640 | { |
984263bc MD |
641 | struct rtprio *prtp; |
642 | char str[8]; | |
643 | unsigned prio, type; | |
644 | ||
5dfd06ac | 645 | prtp = &KI_LWP(k, rtprio); |
984263bc MD |
646 | prio = prtp->prio; |
647 | type = prtp->type; | |
648 | switch (type) { | |
649 | case RTP_PRIO_REALTIME: | |
650 | snprintf(str, sizeof(str), "real:%u", prio); | |
651 | break; | |
652 | case RTP_PRIO_NORMAL: | |
653 | strncpy(str, "normal", sizeof(str)); | |
654 | break; | |
655 | case RTP_PRIO_IDLE: | |
656 | snprintf(str, sizeof(str), "idle:%u", prio); | |
657 | break; | |
658 | default: | |
659 | snprintf(str, sizeof(str), "%u:%u", type, prio); | |
660 | break; | |
661 | } | |
662 | str[sizeof(str) - 1] = '\0'; | |
023c70f2 | 663 | printf("%*s", vent->width, str); |
984263bc MD |
664 | } |
665 | ||
666 | /* | |
667 | * Generic output routines. Print fields from various prototype | |
668 | * structures. | |
669 | */ | |
670 | static void | |
023c70f2 | 671 | printval(const char *bp, const struct varent *vent) |
984263bc MD |
672 | { |
673 | static char ofmt[32] = "%"; | |
c443019b CP |
674 | const char *fcp; |
675 | char *cp; | |
984263bc MD |
676 | |
677 | cp = ofmt + 1; | |
023c70f2 JS |
678 | fcp = vent->var->fmt; |
679 | if (vent->var->flag & LJUST) | |
984263bc MD |
680 | *cp++ = '-'; |
681 | *cp++ = '*'; | |
682 | while ((*cp++ = *fcp++)); | |
683 | ||
023c70f2 | 684 | switch (vent->var->type) { |
984263bc | 685 | case CHAR: |
023c70f2 | 686 | printf(ofmt, vent->width, *(const char *)bp); |
984263bc MD |
687 | break; |
688 | case UCHAR: | |
023c70f2 | 689 | printf(ofmt, vent->width, *(const u_char *)bp); |
984263bc MD |
690 | break; |
691 | case SHORT: | |
023c70f2 | 692 | printf(ofmt, vent->width, *(const short *)bp); |
984263bc MD |
693 | break; |
694 | case USHORT: | |
023c70f2 | 695 | printf(ofmt, vent->width, *(const u_short *)bp); |
984263bc MD |
696 | break; |
697 | case INT: | |
023c70f2 | 698 | printf(ofmt, vent->width, *(const int *)bp); |
984263bc MD |
699 | break; |
700 | case UINT: | |
023c70f2 | 701 | printf(ofmt, vent->width, *(const u_int *)bp); |
984263bc MD |
702 | break; |
703 | case LONG: | |
023c70f2 | 704 | printf(ofmt, vent->width, *(const long *)bp); |
984263bc MD |
705 | break; |
706 | case ULONG: | |
023c70f2 | 707 | printf(ofmt, vent->width, *(const u_long *)bp); |
984263bc MD |
708 | break; |
709 | case KPTR: | |
023c70f2 | 710 | printf(ofmt, vent->width, *(const u_long *)bp); |
984263bc MD |
711 | break; |
712 | default: | |
023c70f2 | 713 | errx(1, "unknown type %d", vent->var->type); |
984263bc MD |
714 | } |
715 | } | |
716 | ||
717 | void | |
023c70f2 | 718 | pvar(const KINFO *k, const struct varent *vent) |
984263bc | 719 | { |
5dfd06ac | 720 | printval((char *)((char *)k->ki_proc + vent->var->off), vent); |
984263bc MD |
721 | } |
722 | ||
27df5e1e | 723 | void |
5dfd06ac | 724 | lpest(const KINFO *k, const struct varent *vent) |
27df5e1e MD |
725 | { |
726 | int val; | |
727 | ||
5dfd06ac | 728 | val = *(int *)((char *)&k->ki_proc->kp_lwp + vent->var->off); |
27df5e1e MD |
729 | val = val / 128; |
730 | printval((char *)&val, vent); | |
731 | } | |
732 | ||
733 | ||
17c88c3a | 734 | void |
5dfd06ac | 735 | lpvar(const KINFO *k, const struct varent *vent) |
17c88c3a | 736 | { |
5dfd06ac | 737 | printval((char *)((char *)&k->ki_proc->kp_lwp + vent->var->off), vent); |
984263bc MD |
738 | } |
739 | ||
740 | void | |
023c70f2 | 741 | rvar(const KINFO *k, const struct varent *vent) |
984263bc | 742 | { |
5dfd06ac | 743 | printval(((const char *)&KI_LWP(k, ru) + vent->var->off), vent); |
984263bc | 744 | } |
96d518a8 MD |
745 | |
746 | static const char * | |
747 | make_printable(const char *str) | |
748 | { | |
749 | static char *cpy; | |
750 | int len; | |
751 | ||
752 | if (cpy) | |
753 | free(cpy); | |
754 | len = strlen(str); | |
755 | if ((cpy = malloc(len * 4 + 1)) == NULL) | |
756 | err(1, NULL); | |
757 | strvis(cpy, str, VIS_TAB | VIS_NL | VIS_NOSLASH); | |
758 | return(cpy); | |
759 | } | |
e08f663e | 760 | |
0ca59c34 SZ |
761 | static const char * |
762 | make_printable2(const char *str) | |
763 | { | |
764 | static char *cpy2; | |
765 | int len; | |
766 | ||
767 | if (cpy2) | |
768 | free(cpy2); | |
769 | len = strlen(str); | |
770 | if ((cpy2 = malloc(len * 4 + 1)) == NULL) | |
771 | err(1, NULL); | |
772 | strvis(cpy2, str, VIS_TAB | VIS_NL | VIS_NOSLASH); | |
773 | return(cpy2); | |
774 | } | |
775 | ||
e08f663e MD |
776 | /* |
777 | * Output a number, divide down as needed to fit within the | |
778 | * field. This function differs from the code used by systat | |
779 | * in that it tries to differentiate the display by always | |
780 | * using a decimal point for excessively large numbers so | |
781 | * the human eye naturally notices the difference. | |
782 | */ | |
783 | static void | |
784 | put64(u_int64_t n, int w, int type) | |
785 | { | |
786 | char b[128]; | |
787 | u_int64_t d; | |
788 | u_int64_t u; | |
789 | size_t len; | |
790 | int ntype; | |
791 | ||
792 | snprintf(b, sizeof(b), "%*jd", w, (uintmax_t)n); | |
793 | len = strlen(b); | |
794 | if (len <= (size_t)w) { | |
795 | fwrite(b, len, 1, stdout); | |
796 | return; | |
797 | } | |
798 | ||
799 | if (type == 'D') | |
800 | u = 1000; | |
801 | else | |
802 | u = 1024; | |
803 | ||
804 | ntype = 0; | |
805 | for (d = 1; n / d >= 100000; d *= u) { | |
806 | switch(type) { | |
807 | case 'D': | |
808 | case 0: | |
809 | type = 'k'; | |
810 | ntype = 'M'; | |
811 | break; | |
812 | case 'k': | |
813 | type = 'M'; | |
814 | ntype = 'G'; | |
815 | break; | |
816 | case 'M': | |
817 | type = 'G'; | |
818 | ntype = 'T'; | |
819 | break; | |
820 | case 'G': | |
821 | type = 'T'; | |
822 | ntype = 'X'; | |
823 | break; | |
824 | case 'T': | |
825 | type = 'X'; | |
826 | ntype = '?'; | |
827 | break; | |
828 | default: | |
829 | type = '?'; | |
830 | break; | |
831 | } | |
832 | } | |
833 | if (w > 4 && n / d >= u) { | |
834 | snprintf(b, sizeof(b), "%*ju.%02u%c", | |
835 | w - 4, | |
836 | (uintmax_t)(n / (d * u)), | |
837 | (u_int)(n / (d * u / 100) % 100), | |
838 | ntype); | |
839 | } else { | |
840 | snprintf(b, sizeof(b), "%*jd%c", | |
841 | w - 1, (uintmax_t)n / d, type); | |
842 | } | |
843 | len = strlen(b); | |
844 | fwrite(b, len, 1, stdout); | |
845 | } |