nrelease - fix/improve livecd
[dragonfly.git] / bin / ps / print.c
CommitLineData
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 61static const char *make_printable(const char *str);
0ca59c34 62static const char *make_printable2(const char *str);
e08f663e 63static 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 68void
b5744197 69printheader(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
99void
023c70f2 100command(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
180void
023c70f2 181ucomm(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
203void
023c70f2 204logname(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
211void
023c70f2 212state(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 319void
023c70f2 320pri(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
328void
329tdpri(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
338void
023c70f2 339uname(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
345int
c443019b 346s_uname(const KINFO *k)
984263bc 347{
5dfd06ac 348 return (strlen(user_from_uid(KI_PROC(k, uid), 0)));
984263bc
MD
349}
350
351void
023c70f2 352runame(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
358int
c443019b 359s_runame(const KINFO *k)
984263bc 360{
5dfd06ac 361 return (strlen(user_from_uid(KI_PROC(k, ruid), 0)));
984263bc
MD
362}
363
364void
023c70f2 365tdev(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
379void
023c70f2 380tname(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
399void
023c70f2 400longtname(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
412void
023c70f2 413started(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
443void
023c70f2 444lstarted(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
454void
023c70f2 455wchan(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
465static u_int64_t
466pgtob(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
475void
023c70f2 476vsize(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
481void
023c70f2 482rssize(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 489void
e08f663e 490p_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
495void
023c70f2 496cputime(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
545double
c443019b 546getpcpu(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
563void
023c70f2 564pcpu(const KINFO *k, const struct varent *vent)
984263bc 565{
023c70f2 566 printf("%*.1f", vent->width, getpcpu(k));
984263bc
MD
567}
568
17c88c3a 569void
023c70f2 570pnice(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 592double
c443019b 593getpmem(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
613void
023c70f2 614pmem(const KINFO *k, const struct varent *vent)
984263bc 615{
023c70f2 616 printf("%*.1f", vent->width, getpmem(k));
984263bc
MD
617}
618
619void
023c70f2 620pagein(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 626void
023c70f2 627maxrss(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
632void
023c70f2 633tsize(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
638void
023c70f2 639rtprior(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 */
670static void
023c70f2 671printval(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
717void
023c70f2 718pvar(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 723void
5dfd06ac 724lpest(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 734void
5dfd06ac 735lpvar(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
740void
023c70f2 741rvar(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
746static const char *
747make_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
761static const char *
762make_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 */
783static void
784put64(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}