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.
13 * 3. Neither the name of the University nor the names of its contributors
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.
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 $
31 * $DragonFly: src/bin/ps/print.c,v 1.34 2008/11/10 14:56:33 swildner Exp $
32 */
33
34 #include <sys/user.h>
35 #include <sys/param.h>
36 #include <sys/time.h>
37 #include <sys/resource.h>
38 #include <sys/stat.h>
39
40 #include <sys/ucred.h>
41 #include <sys/sysctl.h>
42 #include <sys/rtprio.h>
43 #include <sys/caps.h>
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>
51 #include <pwd.h>
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
61 static const char *make_printable(const char *str);
62 static const char *make_printable2(const char *str);
63 static void put64(u_int64_t n, int w, int type);
64
65 #define SHOW_THRNAME(k) \
66 (showtid && KI_PROC(k, pid) != -1 && KI_PROC(k, nthreads) > 1)
67
68 void
printheader(void)69 printheader(void)
70 {
71 const VAR *v;
72 struct varent *vent;
73 int allempty;
74
75 allempty = 1;
76 STAILQ_FOREACH(vent, &var_head, link) {
77 if (*vent->header != '\0') {
78 allempty = 0;
79 break;
80 }
81 }
82 if (allempty)
83 return;
84 STAILQ_FOREACH(vent, &var_head, link) {
85 v = vent->var;
86 if (v->flag & LJUST) {
87 if (STAILQ_NEXT(vent, link) == NULL) /* last one */
88 printf("%s", vent->header);
89 else
90 printf("%-*s", vent->width, vent->header);
91 } else
92 printf("%*s", vent->width, vent->header);
93 if (STAILQ_NEXT(vent, link) != NULL)
94 putchar(' ');
95 }
96 putchar('\n');
97 }
98
99 void
command(const KINFO * k,const struct varent * vent)100 command(const KINFO *k, const struct varent *vent)
101 {
102 int left;
103 int indent;
104 char *cp, *vis_env, *vis_args;
105
106 if (cflag) {
107 /* Don't pad the last field. */
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 }
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);
136 } else {
137 vis_env = NULL;
138 }
139
140 indent = k->ki_indent;
141 if (indent < 0)
142 indent = 0;
143
144 if (STAILQ_NEXT(vent, link) == NULL) {
145 /* last field */
146 if (termwidth == UNLIMITED) {
147 if (vis_env)
148 printf("%s ", vis_env);
149 while (indent) {
150 putchar(' ');
151 --indent;
152 }
153 printf("%s", vis_args);
154 } else {
155 left = termwidth - (totwidth - vent->width);
156 if (left < 1) /* already wrapped, just use std width */
157 left = vent->width;
158 while (indent && left > 1) {
159 putchar(' ');
160 --indent;
161 --left;
162 }
163 if ((cp = vis_env) != NULL) {
164 while (--left >= 0 && *cp)
165 putchar(*cp++);
166 if (--left >= 0)
167 putchar(' ');
168 }
169 for (cp = vis_args; --left >= 0 && *cp != '\0';)
170 putchar(*cp++);
171 }
172 } else
173 /* XXX env? */
174 printf("%-*.*s", vent->width, vent->width, vis_args);
175 free(vis_args);
176 if (vis_env != NULL)
177 free(vis_env);
178 }
179
180 void
ucomm(const KINFO * k,const struct varent * vent)181 ucomm(const KINFO *k, const struct varent *vent)
182 {
183 /* Do not pad the last field */
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 }
201 }
202
203 void
logname(const KINFO * k,const struct varent * vent)204 logname(const KINFO *k, const struct varent *vent)
205 {
206 const char *s = KI_PROC(k, login);
207
208 printf("%-*s", vent->width, *s != '\0' ? s : "-");
209 }
210
211 void
state(const KINFO * k,const struct varent * vent)212 state(const KINFO *k, const struct varent *vent)
213 {
214 int flag;
215 char *cp;
216 char buf[16];
217
218 flag = KI_PROC(k, flags);
219 cp = buf;
220
221 switch (KI_PROC(k, stat)) {
222
223 case SSTOP:
224 *cp = 'T';
225 break;
226
227 case SACTIVE:
228 switch (KI_LWP(k, stat)) {
229 case LSSLEEP:
230 if (KI_LWP(k, flags) & LWP_SINTR) {
231 /* interruptable wait short/long */
232 *cp = KI_LWP(k, slptime) >= MAXSLP ? 'I' : 'S';
233 }
234 else if (KI_LWP(k, tdflags) & TDF_SINTR)
235 *cp = 'S'; /* interruptable lwkt wait */
236 else if (KI_PROC(k, paddr))
237 *cp = 'D'; /* uninterruptable wait */
238 else
239 *cp = 'B'; /* uninterruptable lwkt wait */
240 /* FALLTHROUGH */
241
242 case LSRUN:
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))*/ {
250 ++cp;
251 sprintf(cp, "%d", KI_LWP(k, cpuid));
252 while (cp[1])
253 ++cp;
254 }
255 break;
256
257 case LSSTOP:
258 /* shouldn't happen anyways */
259 *cp = 'T';
260 break;
261 }
262 break;
263
264 case SZOMB:
265 *cp = 'Z';
266 break;
267
268 default:
269 *cp = '?';
270 }
271
272 cp++;
273 if (flag & P_SWAPPEDOUT)
274 *cp++ = 'W';
275 if (KI_PROC(k, nice) < NZERO)
276 *cp++ = '<';
277 else if (KI_PROC(k, nice) > NZERO)
278 *cp++ = 'N';
279 if (flag & P_TRACED)
280 *cp++ = 'X';
281 if (flag & P_WEXIT && KI_PROC(k, stat) != SZOMB)
282 *cp++ = 'E';
283 if (flag & P_PPWAIT)
284 *cp++ = 'V';
285 #if 0
286 /* removed, no longer interesting */
287 if ((flag & P_SYSTEM) || KI_PROC(k, lock) > 0)
288 *cp++ = 'L';
289 #endif
290
291 if (flag & P_JAILED)
292 *cp++ = 'J';
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 }
305 if (KI_PROC(k, auxflags) & KI_SLEADER)
306 *cp++ = 's';
307 if ((flag & P_CONTROLT) && KI_PROC(k, pgid) == KI_PROC(k, tpgid))
308 *cp++ = '+';
309 *cp = '\0';
310 printf("%-*s", vent->width, buf);
311 }
312
313 /*
314 * Normalized priority (lower is better). For pure threads
315 * output a negated LWKT priority (so lower still means better).
316 *
317 * XXX bsd4 scheduler specific.
318 */
319 void
pri(const KINFO * k,const struct varent * vent)320 pri(const KINFO *k, const struct varent *vent)
321 {
322 if (KI_LWP(k, pid) != -1)
323 printf("%*d", vent->width, KI_LWP(k, prio));
324 else
325 printf("%*d", vent->width, -(KI_LWP(k, tdprio)));
326 }
327
328 void
tdpri(const KINFO * k,const struct varent * vent)329 tdpri(const KINFO *k, const struct varent *vent)
330 {
331 char buf[32];
332 int val = KI_LWP(k, tdprio);
333
334 snprintf(buf, sizeof(buf), "%2d", val);
335 printf("%*s", vent->width, buf);
336 }
337
338 void
uname(const KINFO * k,const struct varent * vent)339 uname(const KINFO *k, const struct varent *vent)
340 {
341 printf("%-*s", vent->width,
342 user_from_uid(KI_PROC(k, uid), 0));
343 }
344
345 int
s_uname(const KINFO * k)346 s_uname(const KINFO *k)
347 {
348 return (strlen(user_from_uid(KI_PROC(k, uid), 0)));
349 }
350
351 void
runame(const KINFO * k,const struct varent * vent)352 runame(const KINFO *k, const struct varent *vent)
353 {
354 printf("%-*s", vent->width,
355 user_from_uid(KI_PROC(k, ruid), 0));
356 }
357
358 int
s_runame(const KINFO * k)359 s_runame(const KINFO *k)
360 {
361 return (strlen(user_from_uid(KI_PROC(k, ruid), 0)));
362 }
363
364 void
tdev(const KINFO * k,const struct varent * vent)365 tdev(const KINFO *k, const struct varent *vent)
366 {
367 dev_t dev;
368 char buff[16];
369
370 dev = KI_PROC(k, tdev);
371 if (dev == NODEV)
372 printf("%*s", vent->width, "??");
373 else {
374 snprintf(buff, sizeof(buff), "%d/%d", major(dev), minor(dev));
375 printf("%*s", vent->width, buff);
376 }
377 }
378
379 void
tname(const KINFO * k,const struct varent * vent)380 tname(const KINFO *k, const struct varent *vent)
381 {
382 dev_t dev;
383 const char *ttname;
384
385 dev = KI_PROC(k, tdev);
386 if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
387 printf("%*s ", vent->width-1, "??");
388 else {
389 if (strncmp(ttname, "tty", 3) == 0 ||
390 strncmp(ttname, "cua", 3) == 0)
391 ttname += 3;
392 if (strncmp(ttname, "pts/", 4) == 0)
393 ttname += 4;
394 printf("%*.*s%c", vent->width-1, vent->width-1, ttname,
395 KI_PROC(k, auxflags) & KI_CTTY ? ' ' : '-');
396 }
397 }
398
399 void
longtname(const KINFO * k,const struct varent * vent)400 longtname(const KINFO *k, const struct varent *vent)
401 {
402 dev_t dev;
403 const char *ttname;
404
405 dev = KI_PROC(k, tdev);
406 if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
407 printf("%-*s", vent->width, "??");
408 else
409 printf("%-*s", vent->width, ttname);
410 }
411
412 void
started(const KINFO * k,const struct varent * vent)413 started(const KINFO *k, const struct varent *vent)
414 {
415 static time_t now;
416 time_t then;
417 struct tm *tp;
418 char buf[100];
419 static int use_ampm = -1;
420
421 if (use_ampm < 0)
422 use_ampm = (*nl_langinfo(T_FMT_AMPM) != '\0');
423
424 then = KI_PROC(k, start).tv_sec;
425 if (then < btime.tv_sec) {
426 then = btime.tv_sec;
427 }
428
429 tp = localtime(&then);
430 if (!now)
431 time(&now);
432 if (now - then < 24 * 3600) {
433 strftime(buf, sizeof(buf) - 1,
434 use_ampm ? "%l:%M%p" : "%k:%M ", tp);
435 } else if (now - then < 7 * 86400) {
436 strftime(buf, sizeof(buf) - 1,
437 use_ampm ? "%a%I%p" : "%a%H ", tp);
438 } else
439 strftime(buf, sizeof(buf) - 1, "%e%b%y", tp);
440 printf("%-*s", vent->width, buf);
441 }
442
443 void
lstarted(const KINFO * k,const struct varent * vent)444 lstarted(const KINFO *k, const struct varent *vent)
445 {
446 time_t then;
447 char buf[100];
448
449 then = KI_PROC(k, start).tv_sec;
450 strftime(buf, sizeof(buf) -1, "%c", localtime(&then));
451 printf("%-*s", vent->width, buf);
452 }
453
454 void
wchan(const KINFO * k,const struct varent * vent)455 wchan(const KINFO *k, const struct varent *vent)
456 {
457 if (*KI_LWP(k, wmesg)) {
458 printf("%-*.*s", vent->width, vent->width,
459 KI_LWP(k, wmesg));
460 } else {
461 printf("%-*s", vent->width, "-");
462 }
463 }
464
465 static u_int64_t
pgtob(u_int64_t pg)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 }
474
475 void
vsize(const KINFO * k,const struct varent * vent)476 vsize(const KINFO *k, const struct varent *vent)
477 {
478 put64((uintmax_t)KI_PROC(k, vm_map_size)/1024, vent->width, 'k');
479 }
480
481 void
rssize(const KINFO * k,const struct varent * vent)482 rssize(const KINFO *k, const struct varent *vent)
483 {
484 /* XXX don't have info about shared */
485 put64(pgtob(KI_PROC(k, vm_rssize))/1024, vent->width, 'k');
486 }
487
488 /* doesn't account for text */
489 void
p_rssize(const KINFO * k,const struct varent * vent)490 p_rssize(const KINFO *k, const struct varent *vent)
491 {
492 put64(pgtob(KI_PROC(k, vm_rssize))/1024, vent->width, 'k');
493 }
494
495 void
cputime(const KINFO * k,const struct varent * vent)496 cputime(const KINFO *k, const struct varent *vent)
497 {
498 long secs;
499 long psecs; /* "parts" of a second. first micro, then centi */
500 u_int64_t timeus;
501 char obuff[128];
502 static char decimal_point = '\0';
503
504 if (decimal_point == '\0')
505 decimal_point = localeconv()->decimal_point[0];
506
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;
521 }
522 /*
523 * round and scale to 100's
524 */
525 psecs = (psecs + 5000) / 10000;
526 secs += psecs / 100;
527 psecs = psecs % 100;
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 }
542 printf("%*s", vent->width, obuff);
543 }
544
545 double
getpcpu(const KINFO * k)546 getpcpu(const KINFO *k)
547 {
548 static int failure;
549
550 if (!nlistread)
551 failure = donlist();
552 if (failure)
553 return (0.0);
554
555 #define fxtofl(fixpt) ((double)(fixpt) / fscale)
556
557 /* XXX - I don't like this */
558 if (KI_PROC(k, swtime) == 0 || (KI_PROC(k, flags) & P_SWAPPEDOUT))
559 return (0.0);
560 return (100.0 * fxtofl(KI_LWP(k, pctcpu)));
561 }
562
563 void
pcpu(const KINFO * k,const struct varent * vent)564 pcpu(const KINFO *k, const struct varent *vent)
565 {
566 printf("%*.1f", vent->width, getpcpu(k));
567 }
568
569 void
pnice(const KINFO * k,const struct varent * vent)570 pnice(const KINFO *k, const struct varent *vent)
571 {
572 int niceval;
573
574 switch (KI_LWP(k, rtprio).type) {
575 case RTP_PRIO_REALTIME:
576 niceval = PRIO_MIN - 1 - RTP_PRIO_MAX + KI_LWP(k, rtprio).prio;
577 break;
578 case RTP_PRIO_IDLE:
579 niceval = PRIO_MAX + 1 + KI_LWP(k, rtprio).prio;
580 break;
581 case RTP_PRIO_THREAD:
582 niceval = PRIO_MIN - 1 - RTP_PRIO_MAX - KI_LWP(k, rtprio).prio;
583 break;
584 default:
585 niceval = KI_PROC(k, nice) - NZERO;
586 break;
587 }
588 printf("%*d", vent->width, niceval);
589 }
590
591
592 double
getpmem(const KINFO * k)593 getpmem(const KINFO *k)
594 {
595 static int failure;
596 double fracmem;
597 int szptudot;
598
599 if (!nlistread)
600 failure = donlist();
601 if (failure)
602 return (0.0);
603
604 if (KI_PROC(k, flags) & P_SWAPPEDOUT)
605 return (0.0);
606 /* XXX want pmap ptpages, segtab, etc. (per architecture) */
607 szptudot = UPAGES;
608 /* XXX don't have info about shared */
609 fracmem = ((float)KI_PROC(k, vm_rssize) + szptudot)/mempages;
610 return (100.0 * fracmem);
611 }
612
613 void
pmem(const KINFO * k,const struct varent * vent)614 pmem(const KINFO *k, const struct varent *vent)
615 {
616 printf("%*.1f", vent->width, getpmem(k));
617 }
618
619 void
pagein(const KINFO * k,const struct varent * vent)620 pagein(const KINFO *k, const struct varent *vent)
621 {
622 printf("%*ld", vent->width, KI_LWP(k, ru).ru_majflt);
623 }
624
625 /* ARGSUSED */
626 void
maxrss(const KINFO * k __unused,const struct varent * vent)627 maxrss(const KINFO *k __unused, const struct varent *vent)
628 {
629 printf("%*ld", vent->width, KI_PROC(k, ru).ru_maxrss);
630 }
631
632 void
tsize(const KINFO * k,const struct varent * vent)633 tsize(const KINFO *k, const struct varent *vent)
634 {
635 put64(pgtob(KI_PROC(k, vm_tsize))/1024, vent->width, 'k');
636 }
637
638 void
rtprior(const KINFO * k,const struct varent * vent)639 rtprior(const KINFO *k, const struct varent *vent)
640 {
641 struct rtprio *prtp;
642 char str[8];
643 unsigned prio, type;
644
645 prtp = &KI_LWP(k, rtprio);
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';
663 printf("%*s", vent->width, str);
664 }
665
666 /*
667 * Generic output routines. Print fields from various prototype
668 * structures.
669 */
670 static void
printval(const char * bp,const struct varent * vent)671 printval(const char *bp, const struct varent *vent)
672 {
673 static char ofmt[32] = "%";
674 const char *fcp;
675 char *cp;
676
677 cp = ofmt + 1;
678 fcp = vent->var->fmt;
679 if (vent->var->flag & LJUST)
680 *cp++ = '-';
681 *cp++ = '*';
682 while ((*cp++ = *fcp++));
683
684 switch (vent->var->type) {
685 case CHAR:
686 printf(ofmt, vent->width, *(const char *)bp);
687 break;
688 case UCHAR:
689 printf(ofmt, vent->width, *(const u_char *)bp);
690 break;
691 case SHORT:
692 printf(ofmt, vent->width, *(const short *)bp);
693 break;
694 case USHORT:
695 printf(ofmt, vent->width, *(const u_short *)bp);
696 break;
697 case INT:
698 printf(ofmt, vent->width, *(const int *)bp);
699 break;
700 case UINT:
701 printf(ofmt, vent->width, *(const u_int *)bp);
702 break;
703 case LONG:
704 printf(ofmt, vent->width, *(const long *)bp);
705 break;
706 case ULONG:
707 printf(ofmt, vent->width, *(const u_long *)bp);
708 break;
709 case KPTR:
710 printf(ofmt, vent->width, *(const u_long *)bp);
711 break;
712 default:
713 errx(1, "unknown type %d", vent->var->type);
714 }
715 }
716
717 void
pvar(const KINFO * k,const struct varent * vent)718 pvar(const KINFO *k, const struct varent *vent)
719 {
720 printval((char *)((char *)k->ki_proc + vent->var->off), vent);
721 }
722
723 void
lpest(const KINFO * k,const struct varent * vent)724 lpest(const KINFO *k, const struct varent *vent)
725 {
726 int val;
727
728 val = *(int *)((char *)&k->ki_proc->kp_lwp + vent->var->off);
729 val = val / 128;
730 printval((char *)&val, vent);
731 }
732
733
734 void
lpvar(const KINFO * k,const struct varent * vent)735 lpvar(const KINFO *k, const struct varent *vent)
736 {
737 printval((char *)((char *)&k->ki_proc->kp_lwp + vent->var->off), vent);
738 }
739
740 void
rvar(const KINFO * k,const struct varent * vent)741 rvar(const KINFO *k, const struct varent *vent)
742 {
743 printval(((const char *)&KI_LWP(k, ru) + vent->var->off), vent);
744 }
745
746 static const char *
make_printable(const char * str)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 }
760
761 static const char *
make_printable2(const char * str)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
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
put64(u_int64_t n,int w,int type)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 }
846