1 /* $OpenBSD: print.c,v 1.89 2024/04/28 16:43:15 florian Exp $ */
2 /* $NetBSD: print.c,v 1.27 1995/09/29 21:58:12 cgd Exp $ */
3
4 /*-
5 * Copyright (c) 1990, 1993, 1994
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #include <sys/param.h> /* PZERO NODEV */
34 #include <sys/types.h>
35 #include <sys/signal.h>
36 #include <sys/proc.h>
37 #include <sys/stat.h>
38
39 #include <sys/sysctl.h>
40 #define PLEDGENAMES
41 #include <sys/pledge.h>
42
43 #include <err.h>
44 #include <grp.h>
45 #include <kvm.h>
46 #include <math.h>
47 #include <nlist.h>
48 #include <stddef.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <unistd.h>
53 #include <limits.h>
54 #include <pwd.h>
55
56 #include "ps.h"
57
58 extern kvm_t *kd;
59 extern int needenv, needcomm, neednlist, commandonly;
60
61 int mbswprint(const char *, int, int); /* utf8.c */
62
63 static char *cmdpart(char *);
64
65 #define min(a,b) ((a) < (b) ? (a) : (b))
66
67 static char *
cmdpart(char * arg0)68 cmdpart(char *arg0)
69 {
70 char *cp;
71
72 return ((cp = strrchr(arg0, '/')) != NULL ? cp + 1 : arg0);
73 }
74
75 void
printheader(void)76 printheader(void)
77 {
78 VAR *v;
79 struct varent *vent;
80
81 if (!needheader)
82 return;
83 for (vent = vhead; vent; vent = vent->next) {
84 v = vent->var;
85 if (v->flag & LJUST) {
86 if (vent->next == NULL) /* last one */
87 (void)printf("%s", v->header);
88 else
89 (void)printf("%-*s", v->width, v->header);
90 } else
91 (void)printf("%*s", v->width, v->header);
92 if (vent->next != NULL)
93 (void)putchar(' ');
94 }
95 (void)putchar('\n');
96 }
97
98 static int
print_comm_name(const struct kinfo_proc * kp,int left,int trail)99 print_comm_name(const struct kinfo_proc *kp, int left, int trail)
100 {
101 left -= mbswprint(kp->p_comm, left, trail);
102 if (left > 1 && kp->p_name[0] != '\0') {
103 putchar('/');
104 left--;
105 left -= mbswprint(kp->p_name, left, trail);
106 }
107 return left;
108 }
109
110 void
command(const struct pinfo * pi,VARENT * ve)111 command(const struct pinfo *pi, VARENT *ve)
112 {
113 const struct kinfo_proc *kp = pi->ki;
114 VAR *v;
115 int left, wantspace = 0;
116 char **p;
117
118 /*
119 * Determine the available number of display columns.
120 * Always decrement and check after writing.
121 * No check is needed before mbswprint()
122 * and after writing the last data, though.
123 */
124
125 v = ve->var;
126 if (ve->next != NULL || termwidth != UNLIMITED) {
127 if (ve->next == NULL) {
128 left = termwidth - (totwidth - v->width);
129 if (left < 1) /* already wrapped, just use std width */
130 left = v->width;
131 } else
132 left = v->width;
133 } else
134 left = INT_MAX;
135
136 if (needenv && kd != NULL) {
137 char **envp = kvm_getenvv(kd, kp, termwidth);
138 if ((p = envp) != NULL) {
139 while (*p) {
140 if (wantspace) {
141 putchar(' ');
142 left--;
143 }
144 left -= mbswprint(*p, left, 0);
145 if (left == 0)
146 return;
147 p++;
148 wantspace = 1;
149 }
150 }
151 }
152
153 if (needcomm) {
154 if (pi->prefix)
155 left -= mbswprint(pi->prefix, left, 0);
156 if (!commandonly) {
157 char **argv = NULL;
158
159 if (kd != NULL) {
160 argv = kvm_getargv(kd, kp, termwidth);
161 if ((p = argv) != NULL) {
162 while (*p) {
163 if (wantspace) {
164 putchar(' ');
165 left--;
166 }
167 left -= mbswprint(*p, left, 0);
168 if (left == 0)
169 return;
170 p++;
171 wantspace = 1;
172 }
173 }
174 }
175 if (argv == NULL || argv[0] == NULL ||
176 kp->p_name[0] != '\0' ||
177 strcmp(cmdpart(argv[0]), kp->p_comm)) {
178 if (wantspace) {
179 putchar(' ');
180 if (--left == 0)
181 return;
182 }
183 putchar('(');
184 left--;
185 left = print_comm_name(kp, left, 0);
186 if (left == 0)
187 return;
188 putchar(')');
189 left--;
190 }
191 } else {
192 if (wantspace) {
193 putchar(' ');
194 left--;
195 }
196 left = print_comm_name(kp, left, 0);
197 }
198 }
199 if (ve->next != NULL)
200 while (left-- > 0)
201 putchar(' ');
202 }
203
204 void
ucomm(const struct pinfo * pi,VARENT * ve)205 ucomm(const struct pinfo *pi, VARENT *ve)
206 {
207 const struct kinfo_proc *kp = pi->ki;
208 mbswprint(kp->p_comm, ve->var->width, ve->next != NULL);
209 }
210
211 void
curwd(const struct pinfo * pi,VARENT * ve)212 curwd(const struct pinfo *pi, VARENT *ve)
213 {
214 const struct kinfo_proc *kp = pi->ki;
215 int name[] = { CTL_KERN, KERN_PROC_CWD, kp->p_pid };
216 char path[PATH_MAX];
217 size_t pathlen = sizeof path;
218
219 if (!kvm_sysctl_only || sysctl(name, 3, path, &pathlen, NULL, 0) != 0)
220 *path = '\0';
221
222 mbswprint(path, ve->var->width, ve->next != NULL);
223 }
224
225 void
logname(const struct pinfo * pi,VARENT * ve)226 logname(const struct pinfo *pi, VARENT *ve)
227 {
228 const struct kinfo_proc *kp = pi->ki;
229 VAR *v;
230
231 v = ve->var;
232 if (kp->p_login[0]) {
233 int n = min(v->width, LOGIN_NAME_MAX);
234 mbswprint(kp->p_login, n, ve->next != NULL);
235 if (ve->next != NULL)
236 while (n++ < v->width)
237 putchar(' ');
238 } else
239 (void)printf("%-*s", v->width, "-");
240 }
241
242 #define pgtok(a) (((unsigned long long)(a)*getpagesize())/1024)
243
244 void
printstate(const struct pinfo * pi,VARENT * ve)245 printstate(const struct pinfo *pi, VARENT *ve)
246 {
247 const struct kinfo_proc *kp = pi->ki;
248 int flag;
249 char *cp, state = '\0';
250 VAR *v;
251 char buf[16];
252
253 v = ve->var;
254 flag = kp->p_flag;
255 cp = buf;
256
257 switch (kp->p_stat) {
258
259 case SSTOP:
260 *cp = 'T';
261 break;
262
263 case SSLEEP:
264 if (flag & P_SINTR) /* interruptible (long) */
265 *cp = kp->p_slptime >= maxslp ? 'I' : 'S';
266 else
267 *cp = 'D';
268 break;
269
270 case SRUN:
271 case SIDL:
272 case SONPROC:
273 state = *cp = 'R';
274 break;
275
276 case SDEAD:
277 *cp = 'Z';
278 break;
279
280 default:
281 *cp = '?';
282 }
283 cp++;
284
285 if (kp->p_nice < NZERO)
286 *cp++ = '<';
287 else if (kp->p_nice > NZERO)
288 *cp++ = 'N';
289 if (kp->p_psflags & PS_TRACED)
290 *cp++ = 'X';
291 if ((kp->p_psflags & (PS_EXITING | PS_ZOMBIE)) == PS_EXITING)
292 *cp++ = 'E';
293 if (kp->p_psflags & PS_ISPWAIT)
294 *cp++ = 'V';
295 if (flag & P_SYSTEM)
296 *cp++ = 'K';
297 if ((flag & P_SYSTEM) == 0 &&
298 kp->p_rlim_rss_cur / 1024 < pgtok(kp->p_vm_rssize))
299 *cp++ = '>';
300 if (kp->p_eflag & EPROC_SLEADER)
301 *cp++ = 's';
302 if ((kp->p_psflags & PS_CONTROLT) && kp->p__pgid == kp->p_tpgid)
303 *cp++ = '+';
304 if (kp->p_psflags & PS_PLEDGE)
305 *cp++ = 'p';
306 if (kp->p_eflag & EPROC_UNVEIL) {
307 if (kp->p_eflag & EPROC_LKUNVEIL)
308 *cp++ = 'U';
309 else
310 *cp++ = 'u';
311 }
312 if (kp->p_psflags & PS_CHROOT)
313 *cp++ = 'c';
314 *cp = '\0';
315
316 if (state == 'R' && kp->p_cpuid != KI_NOCPU) {
317 char pbuf[16];
318
319 snprintf(pbuf, sizeof pbuf, "/%llu", kp->p_cpuid);
320 *++cp = '\0';
321 strlcat(buf, pbuf, sizeof buf);
322 cp = buf + strlen(buf);
323 }
324
325 (void)printf("%-*s", v->width, buf);
326 }
327
328 void
printpledge(const struct pinfo * pi,VARENT * ve)329 printpledge(const struct pinfo *pi, VARENT *ve)
330 {
331 const struct kinfo_proc *kp = pi->ki;
332 int i;
333 VAR *v;
334 char buf[1024];
335
336 v = ve->var;
337 buf[0] = '\0';
338
339 for (i = 0; pledgenames[i].bits != 0; i++) {
340 if (pledgenames[i].bits & kp->p_pledge) {
341 if (*buf != '\0')
342 strlcat(buf, ",", sizeof buf);
343 strlcat(buf, pledgenames[i].name, sizeof buf);
344 }
345 }
346
347 (void)printf("%-*s", v->width, buf);
348 }
349
350 void
pri(const struct pinfo * pi,VARENT * ve)351 pri(const struct pinfo *pi, VARENT *ve)
352 {
353 const struct kinfo_proc *kp = pi->ki;
354 VAR *v;
355
356 v = ve->var;
357 (void)printf("%*d", v->width, kp->p_priority - PZERO);
358 }
359
360 void
pnice(const struct pinfo * pi,VARENT * ve)361 pnice(const struct pinfo *pi, VARENT *ve)
362 {
363 const struct kinfo_proc *kp = pi->ki;
364 VAR *v;
365
366 v = ve->var;
367 (void)printf("%*d", v->width, kp->p_nice - NZERO);
368 }
369
370 void
euname(const struct pinfo * pi,VARENT * ve)371 euname(const struct pinfo *pi, VARENT *ve)
372 {
373 const struct kinfo_proc *kp = pi->ki;
374
375 mbswprint(user_from_uid(kp->p_uid, 0), ve->var->width,
376 ve->next != NULL);
377 }
378
379 void
runame(const struct pinfo * pi,VARENT * ve)380 runame(const struct pinfo *pi, VARENT *ve)
381 {
382 const struct kinfo_proc *kp = pi->ki;
383
384 mbswprint(user_from_uid(kp->p_ruid, 0), ve->var->width,
385 ve->next != NULL);
386 }
387
388 void
gname(const struct pinfo * pi,VARENT * ve)389 gname(const struct pinfo *pi, VARENT *ve)
390 {
391 const struct kinfo_proc *kp = pi->ki;
392
393 mbswprint(group_from_gid(kp->p_gid, 0), ve->var->width,
394 ve->next != NULL);
395 }
396
397 void
rgname(const struct pinfo * pi,VARENT * ve)398 rgname(const struct pinfo *pi, VARENT *ve)
399 {
400 const struct kinfo_proc *kp = pi->ki;
401
402 mbswprint(group_from_gid(kp->p_rgid, 0), ve->var->width,
403 ve->next != NULL);
404 }
405
406 void
supgid(const struct pinfo * pi,VARENT * ve)407 supgid(const struct pinfo *pi, VARENT *ve)
408 {
409 const struct kinfo_proc *kp = pi->ki;
410 char buf[1024];
411 char *p = buf;
412 ssize_t size = sizeof(buf);
413 int i, len;
414
415 for (i = 0; i < kp->p_ngroups; i++) {
416 len = snprintf(p, size, "%s%u",
417 p == buf ? "" : ",",
418 kp->p_groups[i]);
419 if (len < 0 || len >= size)
420 break;
421 p += len;
422 size -= len;
423 }
424
425 (void)printf("%-*s", ve->var->width, buf);
426 }
427
428 void
supgrp(const struct pinfo * pi,VARENT * ve)429 supgrp(const struct pinfo *pi, VARENT *ve)
430 {
431 const struct kinfo_proc *kp = pi->ki;
432 char buf[1024];
433 char *p = buf;
434 ssize_t size = sizeof(buf);
435 int i, len;
436
437 for (i = 0; i < kp->p_ngroups; i++) {
438 len = snprintf(p, size, "%s%s",
439 p == buf ? "" : ",",
440 group_from_gid(kp->p_groups[i], 0));
441 if (len < 0 || len >= size)
442 break;
443 p += len;
444 size -= len;
445 }
446
447 (void)printf("%-*s", ve->var->width, buf);
448 }
449
450 void
tdev(const struct pinfo * pi,VARENT * ve)451 tdev(const struct pinfo *pi, VARENT *ve)
452 {
453 const struct kinfo_proc *kp = pi->ki;
454 VAR *v;
455 dev_t dev;
456
457 v = ve->var;
458 dev = kp->p_tdev;
459 if (dev == NODEV)
460 (void)printf("%*s", v->width, "??");
461 else {
462 char buff[10+1+10+1];
463
464 (void)snprintf(buff, sizeof(buff),
465 "%u/%u", major(dev), minor(dev));
466 (void)printf("%*s", v->width, buff);
467 }
468 }
469
470 void
tname(const struct pinfo * pi,VARENT * ve)471 tname(const struct pinfo *pi, VARENT *ve)
472 {
473 const struct kinfo_proc *kp = pi->ki;
474 VAR *v;
475 dev_t dev;
476 char *ttname;
477
478 v = ve->var;
479 dev = kp->p_tdev;
480 if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
481 (void)printf("%-*s", v->width, "??");
482 else {
483 if (strncmp(ttname, "tty", 3) == 0)
484 ttname += 3;
485 (void)printf("%*.*s%c", v->width-1, v->width-1, ttname,
486 kp->p_eflag & EPROC_CTTY ? ' ' : '-');
487 }
488 }
489
490 void
longtname(const struct pinfo * pi,VARENT * ve)491 longtname(const struct pinfo *pi, VARENT *ve)
492 {
493 const struct kinfo_proc *kp = pi->ki;
494 VAR *v;
495 dev_t dev;
496 char *ttname;
497
498 v = ve->var;
499 dev = kp->p_tdev;
500 if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
501 (void)printf("%-*s", v->width, "??");
502 else
503 (void)printf("%-*s", v->width, ttname);
504 }
505
506 void
started(const struct pinfo * pi,VARENT * ve)507 started(const struct pinfo *pi, VARENT *ve)
508 {
509 const struct kinfo_proc *kp = pi->ki;
510 VAR *v;
511 static time_t now;
512 time_t startt;
513 struct tm *tp;
514 char buf[100];
515
516 v = ve->var;
517 if (!kp->p_uvalid) {
518 (void)printf("%-*s", v->width, "-");
519 return;
520 }
521
522 #define SECSPERHOUR (60 * 60)
523 #define SECSPERDAY (24 * 60 * 60)
524
525 startt = kp->p_ustart_sec;
526 tp = localtime(&startt);
527 if (tp == NULL) {
528 (void)printf("%-*s", v->width, "-");
529 return;
530 }
531 if (!now)
532 (void)time(&now);
533 if (now - kp->p_ustart_sec < 12 * SECSPERHOUR) {
534 (void)strftime(buf, sizeof(buf) - 1, "%l:%M%p", tp);
535 } else if (now - kp->p_ustart_sec < 7 * SECSPERDAY) {
536 (void)strftime(buf, sizeof(buf) - 1, "%a%I%p", tp);
537 } else
538 (void)strftime(buf, sizeof(buf) - 1, "%e%b%y", tp);
539 (void)printf("%-*s", v->width, buf);
540 }
541
542 void
lstarted(const struct pinfo * pi,VARENT * ve)543 lstarted(const struct pinfo *pi, VARENT *ve)
544 {
545 const struct kinfo_proc *kp = pi->ki;
546 VAR *v;
547 time_t startt;
548 char buf[100];
549
550 v = ve->var;
551 if (!kp->p_uvalid) {
552 (void)printf("%-*s", v->width, "-");
553 return;
554 }
555 startt = kp->p_ustart_sec;
556 (void)strftime(buf, sizeof(buf) -1, "%c",
557 localtime(&startt));
558 (void)printf("%-*s", v->width, buf);
559 }
560
elapsed(const struct pinfo * pi,VARENT * ve)561 void elapsed(const struct pinfo *pi, VARENT *ve)
562 {
563 const struct kinfo_proc *kp = pi->ki;
564 VAR *v;
565 static time_t now;
566 time_t secs;
567 char buf[64];
568 long days, hours, minutes, seconds;
569
570 v = ve->var;
571 if (!kp->p_uvalid) {
572 (void)printf("%*s", v->width, "-");
573 return;
574 }
575
576 if (!now)
577 (void)time(&now);
578 secs = now - kp->p_ustart_sec;
579
580 if (secs < 0) {
581 (void)printf("%*s", v->width, "-");
582 return;
583 }
584
585 days = secs / SECSPERDAY;
586 secs %= SECSPERDAY;
587
588 hours = secs / SECSPERHOUR;
589 secs %= SECSPERHOUR;
590
591 minutes = secs / 60;
592 seconds = secs % 60;
593
594 if (days > 0)
595 (void)snprintf(buf, sizeof(buf), "%ld-%02ld:%02ld:%02ld",
596 days, hours, minutes, seconds);
597 else if (hours > 0)
598 (void)snprintf(buf, sizeof(buf), "%02ld:%02ld:%02ld",
599 hours, minutes, seconds);
600 else
601 (void)snprintf(buf, sizeof(buf), "%02ld:%02ld",
602 minutes, seconds);
603 (void)printf("%*s", v->width, buf);
604 }
605
606 void
wchan(const struct pinfo * pi,VARENT * ve)607 wchan(const struct pinfo *pi, VARENT *ve)
608 {
609 const struct kinfo_proc *kp = pi->ki;
610 VAR *v;
611
612 v = ve->var;
613 if (kp->p_wmesg[0]) {
614 (void)printf("%-*s", (int)v->width, kp->p_wmesg);
615 } else
616 (void)printf("%-*s", v->width, "-");
617 }
618
619 void
vsize(const struct pinfo * pi,VARENT * ve)620 vsize(const struct pinfo *pi, VARENT *ve)
621 {
622 const struct kinfo_proc *kp = pi->ki;
623 VAR *v;
624
625 v = ve->var;
626 (void)printf("%*llu", v->width,
627 pgtok(kp->p_vm_dsize + kp->p_vm_ssize + kp->p_vm_tsize));
628 }
629
630 void
rssize(const struct pinfo * pi,VARENT * ve)631 rssize(const struct pinfo *pi, VARENT *ve)
632 {
633 const struct kinfo_proc *kp = pi->ki;
634 VAR *v;
635
636 v = ve->var;
637 /* XXX don't have info about shared */
638 (void)printf("%*llu", v->width, (kp->p_flag & P_SYSTEM) ? 0 :
639 pgtok(kp->p_vm_rssize));
640 }
641
642 void
p_rssize(const struct pinfo * pi,VARENT * ve)643 p_rssize(const struct pinfo *pi, VARENT *ve)
644 {
645 const struct kinfo_proc *kp = pi->ki;
646 VAR *v;
647
648 v = ve->var;
649 (void)printf("%*llu", v->width, (kp->p_flag & P_SYSTEM) ? 0 :
650 pgtok(kp->p_vm_rssize));
651 }
652
653 void
cputime(const struct pinfo * pi,VARENT * ve)654 cputime(const struct pinfo *pi, VARENT *ve)
655 {
656 const struct kinfo_proc *kp = pi->ki;
657 VAR *v;
658 long secs;
659 long psecs; /* "parts" of a second. first micro, then centi */
660 char obuff[128];
661
662 v = ve->var;
663 if (kp->p_stat == SDEAD || !kp->p_uvalid) {
664 secs = 0;
665 psecs = 0;
666 } else {
667 /*
668 * This counts time spent handling interrupts. XXX
669 */
670 secs = kp->p_rtime_sec;
671 psecs = kp->p_rtime_usec;
672 if (sumrusage) {
673 secs += kp->p_uctime_sec;
674 psecs += kp->p_uctime_usec;
675 }
676 /*
677 * round and scale to 100's
678 */
679 psecs = (psecs + 5000) / 10000;
680 secs += psecs / 100;
681 psecs = psecs % 100;
682 }
683 (void)snprintf(obuff, sizeof(obuff),
684 "%3ld:%02ld.%02ld", secs/60, secs%60, psecs);
685 (void)printf("%*s", v->width, obuff);
686 }
687
688 double
getpcpu(const struct kinfo_proc * kp)689 getpcpu(const struct kinfo_proc *kp)
690 {
691 if (fscale == 0)
692 return (0.0);
693
694 #define fxtofl(fixpt) ((double)(fixpt) / fscale)
695
696 return (100.0 * fxtofl(kp->p_pctcpu));
697 }
698
699 void
pcpu(const struct pinfo * pi,VARENT * ve)700 pcpu(const struct pinfo *pi, VARENT *ve)
701 {
702 VAR *v;
703
704 v = ve->var;
705 (void)printf("%*.1f", v->width, getpcpu(pi->ki));
706 }
707
708 double
getpmem(const struct kinfo_proc * kp)709 getpmem(const struct kinfo_proc *kp)
710 {
711 double fracmem;
712
713 if (mempages == 0)
714 return (0.0);
715
716 if (kp->p_flag & P_SYSTEM)
717 return (0.0);
718 /* XXX don't have info about shared */
719 fracmem = ((float)kp->p_vm_rssize)/mempages;
720 return (100.0 * fracmem);
721 }
722
723 void
pmem(const struct pinfo * pi,VARENT * ve)724 pmem(const struct pinfo *pi, VARENT *ve)
725 {
726 VAR *v;
727
728 v = ve->var;
729 (void)printf("%*.1f", v->width, getpmem(pi->ki));
730 }
731
732 void
pagein(const struct pinfo * pi,VARENT * ve)733 pagein(const struct pinfo *pi, VARENT *ve)
734 {
735 const struct kinfo_proc *kp = pi->ki;
736 VAR *v;
737
738 v = ve->var;
739 (void)printf("%*llu", v->width,
740 kp->p_uvalid ? kp->p_uru_majflt : 0);
741 }
742
743 void
maxrss(const struct pinfo * pi,VARENT * ve)744 maxrss(const struct pinfo *pi, VARENT *ve)
745 {
746 const struct kinfo_proc *kp = pi->ki;
747 VAR *v;
748
749 v = ve->var;
750 (void)printf("%*llu", v->width, kp->p_rlim_rss_cur / 1024);
751 }
752
753 void
tsize(const struct pinfo * pi,VARENT * ve)754 tsize(const struct pinfo *pi, VARENT *ve)
755 {
756 const struct kinfo_proc *kp = pi->ki;
757 VAR *v;
758
759 v = ve->var;
760 (void)printf("%*llu", v->width, pgtok(kp->p_vm_tsize));
761 }
762
763 void
dsize(const struct pinfo * pi,VARENT * ve)764 dsize(const struct pinfo *pi, VARENT *ve)
765 {
766 const struct kinfo_proc *kp = pi->ki;
767 VAR *v;
768
769 v = ve->var;
770 (void)printf("%*llu", v->width, pgtok(kp->p_vm_dsize));
771 }
772
773 void
ssize(const struct pinfo * pi,VARENT * ve)774 ssize(const struct pinfo *pi, VARENT *ve)
775 {
776 const struct kinfo_proc *kp = pi->ki;
777 VAR *v;
778
779 v = ve->var;
780 (void)printf("%*llu", v->width, pgtok(kp->p_vm_ssize));
781 }
782
783 /*
784 * Generic output routines. Print fields from various prototype
785 * structures.
786 */
787 static void
printval(char * bp,VAR * v)788 printval(char *bp, VAR *v)
789 {
790 char ofmt[32];
791
792 snprintf(ofmt, sizeof(ofmt), "%%%s*%s", (v->flag & LJUST) ? "-" : "",
793 v->fmt);
794
795 /*
796 * Note that the "INF127" check is nonsensical for types
797 * that are or can be signed.
798 */
799 #define GET(type) (*(type *)bp)
800 #define CHK_INF127(n) (((n) > 127) && (v->flag & INF127) ? 127 : (n))
801
802 switch (v->type) {
803 case INT8:
804 (void)printf(ofmt, v->width, GET(int8_t));
805 break;
806 case UINT8:
807 (void)printf(ofmt, v->width, CHK_INF127(GET(u_int8_t)));
808 break;
809 case INT16:
810 (void)printf(ofmt, v->width, GET(int16_t));
811 break;
812 case UINT16:
813 (void)printf(ofmt, v->width, CHK_INF127(GET(u_int16_t)));
814 break;
815 case INT32:
816 (void)printf(ofmt, v->width, GET(int32_t));
817 break;
818 case UINT32:
819 (void)printf(ofmt, v->width, CHK_INF127(GET(u_int32_t)));
820 break;
821 case INT64:
822 (void)printf(ofmt, v->width, GET(int64_t));
823 break;
824 case UINT64:
825 (void)printf(ofmt, v->width, CHK_INF127(GET(u_int64_t)));
826 break;
827 default:
828 errx(1, "unknown type %d", v->type);
829 }
830 #undef GET
831 #undef CHK_INF127
832 }
833
834 void
pvar(const struct pinfo * pi,VARENT * ve)835 pvar(const struct pinfo *pi, VARENT *ve)
836 {
837 const struct kinfo_proc *kp = pi->ki;
838 VAR *v;
839
840 v = ve->var;
841 if ((v->flag & USER) && !kp->p_uvalid)
842 (void)printf("%*s", v->width, "-");
843 else
844 printval((char *)kp + v->off, v);
845 }
846