xref: /openbsd-src/bin/ps/print.c (revision 3374c67d44f9b75b98444cbf63020f777792342e)
1 /*	$OpenBSD: print.c,v 1.84 2022/09/20 10:01:51 job 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 *
68 cmdpart(char *arg0)
69 {
70 	char *cp;
71 
72 	return ((cp = strrchr(arg0, '/')) != NULL ? cp + 1 : arg0);
73 }
74 
75 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 void
99 command(const struct pinfo *pi, VARENT *ve)
100 {
101 	const struct kinfo_proc *kp = pi->ki;
102 	VAR *v;
103 	int left, wantspace = 0;
104 	char **p;
105 
106 	/*
107 	 * Determine the available number of display columns.
108 	 * Always decrement and check after writing.
109 	 * No check is needed before mbswprint()
110 	 * and after writing the last data, though.
111 	 */
112 
113 	v = ve->var;
114 	if (ve->next != NULL || termwidth != UNLIMITED) {
115 		if (ve->next == NULL) {
116 			left = termwidth - (totwidth - v->width);
117 			if (left < 1) /* already wrapped, just use std width */
118 				left = v->width;
119 		} else
120 			left = v->width;
121 	} else
122 		left = INT_MAX;
123 
124 	if (needenv && kd != NULL) {
125 		char **envp = kvm_getenvv(kd, kp, termwidth);
126 		if ((p = envp) != NULL) {
127 			while (*p) {
128 				if (wantspace) {
129 					putchar(' ');
130 					left--;
131 				}
132 				left -= mbswprint(*p, left, 0);
133 				if (left == 0)
134 					return;
135 				p++;
136 				wantspace = 1;
137 			}
138 		}
139 	}
140 
141 	if (needcomm) {
142 		if (pi->prefix)
143 			left -= mbswprint(pi->prefix, left, 0);
144 		if (!commandonly) {
145 			char **argv = NULL;
146 
147 			if (kd != NULL) {
148 				argv = kvm_getargv(kd, kp, termwidth);
149 				if ((p = argv) != NULL) {
150 					while (*p) {
151 						if (wantspace) {
152 							putchar(' ');
153 							left--;
154 						}
155 						left -= mbswprint(*p, left, 0);
156 						if (left == 0)
157 							return;
158 						p++;
159 						wantspace = 1;
160 					}
161 				}
162 			}
163 			if (argv == NULL || argv[0] == NULL ||
164 			    strcmp(cmdpart(argv[0]), kp->p_comm)) {
165 				if (wantspace) {
166 					putchar(' ');
167 					if (--left == 0)
168 						return;
169 				}
170 				putchar('(');
171 				left--;
172 				left -= mbswprint(kp->p_comm, left, 0);
173 				if (left == 0)
174 					return;
175 				putchar(')');
176 				left--;
177 			}
178 		} else {
179 			if (wantspace) {
180 				putchar(' ');
181 				left--;
182 			}
183 			left -= mbswprint(kp->p_comm, left, 0);
184 		}
185 	}
186 	if (ve->next != NULL)
187 		while (left-- > 0)
188 			putchar(' ');
189 }
190 
191 void
192 ucomm(const struct pinfo *pi, VARENT *ve)
193 {
194 	const struct kinfo_proc *kp = pi->ki;
195 	mbswprint(kp->p_comm, ve->var->width, ve->next != NULL);
196 }
197 
198 void
199 curwd(const struct pinfo *pi, VARENT *ve)
200 {
201 	const struct kinfo_proc *kp = pi->ki;
202 	int name[] = { CTL_KERN, KERN_PROC_CWD, kp->p_pid };
203 	char path[PATH_MAX];
204 	size_t pathlen = sizeof path;
205 
206 	if (!kvm_sysctl_only || sysctl(name, 3, path, &pathlen, NULL, 0) != 0)
207 		*path = '\0';
208 
209 	mbswprint(path, ve->var->width, ve->next != NULL);
210 }
211 
212 void
213 logname(const struct pinfo *pi, VARENT *ve)
214 {
215 	const struct kinfo_proc *kp = pi->ki;
216 	VAR *v;
217 
218 	v = ve->var;
219 	if (kp->p_login[0]) {
220 		int n = min(v->width, LOGIN_NAME_MAX);
221 		mbswprint(kp->p_login, n, ve->next != NULL);
222 		if (ve->next != NULL)
223 			while (n++ < v->width)
224 				putchar(' ');
225 	} else
226 		(void)printf("%-*s", v->width, "-");
227 }
228 
229 #define pgtok(a)	(((unsigned long long)(a)*getpagesize())/1024)
230 
231 void
232 printstate(const struct pinfo *pi, VARENT *ve)
233 {
234 	const struct kinfo_proc *kp = pi->ki;
235 	int flag;
236 	char *cp, state = '\0';
237 	VAR *v;
238 	char buf[16];
239 
240 	v = ve->var;
241 	flag = kp->p_flag;
242 	cp = buf;
243 
244 	switch (kp->p_stat) {
245 
246 	case SSTOP:
247 		*cp = 'T';
248 		break;
249 
250 	case SSLEEP:
251 		if (flag & P_SINTR)	/* interruptible (long) */
252 			*cp = kp->p_slptime >= maxslp ? 'I' : 'S';
253 		else
254 			*cp = 'D';
255 		break;
256 
257 	case SRUN:
258 	case SIDL:
259 	case SONPROC:
260 		state = *cp = 'R';
261 		break;
262 
263 	case SDEAD:
264 		*cp = 'Z';
265 		break;
266 
267 	default:
268 		*cp = '?';
269 	}
270 	cp++;
271 
272 	if (kp->p_nice < NZERO)
273 		*cp++ = '<';
274 	else if (kp->p_nice > NZERO)
275 		*cp++ = 'N';
276 	if (kp->p_psflags & PS_TRACED)
277 		*cp++ = 'X';
278 	if ((kp->p_psflags & (PS_EXITING | PS_ZOMBIE)) == PS_EXITING)
279 		*cp++ = 'E';
280 	if (kp->p_psflags & PS_ISPWAIT)
281 		*cp++ = 'V';
282 	if (flag & P_SYSTEM)
283 		*cp++ = 'K';
284 	if ((flag & P_SYSTEM) == 0 &&
285 	    kp->p_rlim_rss_cur / 1024 < pgtok(kp->p_vm_rssize))
286 		*cp++ = '>';
287 	if (kp->p_eflag & EPROC_SLEADER)
288 		*cp++ = 's';
289 	if ((kp->p_psflags & PS_CONTROLT) && kp->p__pgid == kp->p_tpgid)
290 		*cp++ = '+';
291 	if (kp->p_psflags & PS_PLEDGE)
292 		*cp++ = 'p';
293 	if (kp->p_eflag & EPROC_UNVEIL) {
294 		if (kp->p_eflag & EPROC_LKUNVEIL)
295 			*cp++ = 'U';
296 		else
297 			*cp++ = 'u';
298 	}
299 	if (kp->p_psflags & PS_CHROOT)
300 		*cp++ = 'c';
301 	*cp = '\0';
302 
303 	if (state == 'R' && kp->p_cpuid != KI_NOCPU) {
304 		char pbuf[16];
305 
306 		snprintf(pbuf, sizeof pbuf, "/%llu", kp->p_cpuid);
307 		*++cp = '\0';
308 		strlcat(buf, pbuf, sizeof buf);
309 		cp = buf + strlen(buf);
310 	}
311 
312 	(void)printf("%-*s", v->width, buf);
313 }
314 
315 void
316 printpledge(const struct pinfo *pi, VARENT *ve)
317 {
318 	const struct kinfo_proc *kp = pi->ki;
319 	int i;
320 	VAR *v;
321 	char buf[1024];
322 
323 	v = ve->var;
324 	buf[0] = '\0';
325 
326 	for (i = 0; pledgenames[i].bits != 0; i++) {
327 		if (pledgenames[i].bits & kp->p_pledge) {
328 			if (*buf != '\0')
329 				strlcat(buf, ",", sizeof buf);
330 			strlcat(buf, pledgenames[i].name, sizeof buf);
331 		}
332 	}
333 
334 	(void)printf("%-*s", v->width, buf);
335 }
336 
337 void
338 pri(const struct pinfo *pi, VARENT *ve)
339 {
340 	const struct kinfo_proc *kp = pi->ki;
341 	VAR *v;
342 
343 	v = ve->var;
344 	(void)printf("%*d", v->width, kp->p_priority - PZERO);
345 }
346 
347 void
348 pnice(const struct pinfo *pi, VARENT *ve)
349 {
350 	const struct kinfo_proc *kp = pi->ki;
351 	VAR *v;
352 
353 	v = ve->var;
354 	(void)printf("%*d", v->width, kp->p_nice - NZERO);
355 }
356 
357 void
358 euname(const struct pinfo *pi, VARENT *ve)
359 {
360 	const struct kinfo_proc *kp = pi->ki;
361 
362 	mbswprint(user_from_uid(kp->p_uid, 0), ve->var->width,
363 	    ve->next != NULL);
364 }
365 
366 void
367 runame(const struct pinfo *pi, VARENT *ve)
368 {
369 	const struct kinfo_proc *kp = pi->ki;
370 
371 	mbswprint(user_from_uid(kp->p_ruid, 0), ve->var->width,
372 	    ve->next != NULL);
373 }
374 
375 void
376 gname(const struct pinfo *pi, VARENT *ve)
377 {
378 	const struct kinfo_proc *kp = pi->ki;
379 
380 	mbswprint(group_from_gid(kp->p_gid, 0), ve->var->width,
381 	    ve->next != NULL);
382 }
383 
384 void
385 rgname(const struct pinfo *pi, VARENT *ve)
386 {
387 	const struct kinfo_proc *kp = pi->ki;
388 
389 	mbswprint(group_from_gid(kp->p_rgid, 0), ve->var->width,
390 	    ve->next != NULL);
391 }
392 
393 void
394 supgid(const struct pinfo *pi, VARENT *ve)
395 {
396 	const struct kinfo_proc *kp = pi->ki;
397 	char buf[1024];
398 	char *p = buf;
399 	ssize_t size = sizeof(buf);
400 	int i, len;
401 
402 	for (i = 0; i < kp->p_ngroups; i++) {
403 		len = snprintf(p, size, "%s%u",
404 		    p == buf ? "" : ",",
405 		    kp->p_groups[i]);
406 		if (len < 0 || len >= size)
407 			break;
408 		p += len;
409 		size -= len;
410 	}
411 
412 	(void)printf("%-*s", ve->var->width, buf);
413 }
414 
415 void
416 supgrp(const struct pinfo *pi, VARENT *ve)
417 {
418 	const struct kinfo_proc *kp = pi->ki;
419 	char buf[1024];
420 	char *p = buf;
421 	ssize_t size = sizeof(buf);
422 	int i, len;
423 
424 	for (i = 0; i < kp->p_ngroups; i++) {
425 		len = snprintf(p, size, "%s%s",
426 		    p == buf ? "" : ",",
427 		    group_from_gid(kp->p_groups[i], 0));
428 		if (len < 0 || len >= size)
429 			break;
430 		p += len;
431 		size -= len;
432 	}
433 
434 	(void)printf("%-*s", ve->var->width, buf);
435 }
436 
437 void
438 tdev(const struct pinfo *pi, VARENT *ve)
439 {
440 	const struct kinfo_proc *kp = pi->ki;
441 	VAR *v;
442 	dev_t dev;
443 
444 	v = ve->var;
445 	dev = kp->p_tdev;
446 	if (dev == NODEV)
447 		(void)printf("%*s", v->width, "??");
448 	else {
449 		char buff[10+1+10+1];
450 
451 		(void)snprintf(buff, sizeof(buff),
452 		    "%u/%u", major(dev), minor(dev));
453 		(void)printf("%*s", v->width, buff);
454 	}
455 }
456 
457 void
458 tname(const struct pinfo *pi, VARENT *ve)
459 {
460 	const struct kinfo_proc *kp = pi->ki;
461 	VAR *v;
462 	dev_t dev;
463 	char *ttname;
464 
465 	v = ve->var;
466 	dev = kp->p_tdev;
467 	if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
468 		(void)printf("%-*s", v->width, "??");
469 	else {
470 		if (strncmp(ttname, "tty", 3) == 0)
471 			ttname += 3;
472 		(void)printf("%*.*s%c", v->width-1, v->width-1, ttname,
473 			kp->p_eflag & EPROC_CTTY ? ' ' : '-');
474 	}
475 }
476 
477 void
478 longtname(const struct pinfo *pi, VARENT *ve)
479 {
480 	const struct kinfo_proc *kp = pi->ki;
481 	VAR *v;
482 	dev_t dev;
483 	char *ttname;
484 
485 	v = ve->var;
486 	dev = kp->p_tdev;
487 	if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
488 		(void)printf("%-*s", v->width, "??");
489 	else
490 		(void)printf("%-*s", v->width, ttname);
491 }
492 
493 void
494 started(const struct pinfo *pi, VARENT *ve)
495 {
496 	const struct kinfo_proc *kp = pi->ki;
497 	VAR *v;
498 	static time_t now;
499 	time_t startt;
500 	struct tm *tp;
501 	char buf[100];
502 
503 	v = ve->var;
504 	if (!kp->p_uvalid) {
505 		(void)printf("%-*s", v->width, "-");
506 		return;
507 	}
508 
509 #define SECSPERHOUR	(60 * 60)
510 #define SECSPERDAY	(24 * 60 * 60)
511 
512 	startt = kp->p_ustart_sec;
513 	tp = localtime(&startt);
514 	if (!now)
515 		(void)time(&now);
516 	if (now - kp->p_ustart_sec < 12 * SECSPERHOUR) {
517 		(void)strftime(buf, sizeof(buf) - 1, "%l:%M%p", tp);
518 	} else if (now - kp->p_ustart_sec < 7 * SECSPERDAY) {
519 		(void)strftime(buf, sizeof(buf) - 1, "%a%I%p", tp);
520 	} else
521 		(void)strftime(buf, sizeof(buf) - 1, "%e%b%y", tp);
522 	(void)printf("%-*s", v->width, buf);
523 }
524 
525 void
526 lstarted(const struct pinfo *pi, VARENT *ve)
527 {
528 	const struct kinfo_proc *kp = pi->ki;
529 	VAR *v;
530 	time_t startt;
531 	char buf[100];
532 
533 	v = ve->var;
534 	if (!kp->p_uvalid) {
535 		(void)printf("%-*s", v->width, "-");
536 		return;
537 	}
538 	startt = kp->p_ustart_sec;
539 	(void)strftime(buf, sizeof(buf) -1, "%c",
540 	    localtime(&startt));
541 	(void)printf("%-*s", v->width, buf);
542 }
543 
544 void elapsed(const struct pinfo *pi, VARENT *ve)
545 {
546 	const struct kinfo_proc *kp = pi->ki;
547 	VAR *v;
548 	static time_t now;
549 	time_t secs;
550 	char buf[64];
551 	long days, hours, minutes, seconds;
552 
553 	v = ve->var;
554 	if (!kp->p_uvalid) {
555 		(void)printf("%*s", v->width, "-");
556 		return;
557 	}
558 
559 	if (!now)
560 		(void)time(&now);
561 	secs = now - kp->p_ustart_sec;
562 
563 	if (secs < 0) {
564 		(void)printf("%*s", v->width, "-");
565 		return;
566 	}
567 
568 	days = secs / SECSPERDAY;
569 	secs %= SECSPERDAY;
570 
571 	hours = secs / SECSPERHOUR;
572 	secs %= SECSPERHOUR;
573 
574 	minutes = secs / 60;
575 	seconds = secs % 60;
576 
577 	if (days > 0)
578 		(void)snprintf(buf, sizeof(buf), "%ld-%02ld:%02ld:%02ld",
579 		    days, hours, minutes, seconds);
580 	else if (hours > 0)
581 		(void)snprintf(buf, sizeof(buf), "%02ld:%02ld:%02ld",
582 		    hours, minutes, seconds);
583 	else
584 		(void)snprintf(buf, sizeof(buf), "%02ld:%02ld",
585 		    minutes, seconds);
586 	(void)printf("%*s", v->width, buf);
587 }
588 
589 void
590 wchan(const struct pinfo *pi, VARENT *ve)
591 {
592 	const struct kinfo_proc *kp = pi->ki;
593 	VAR *v;
594 
595 	v = ve->var;
596 	if (kp->p_wmesg[0]) {
597 		(void)printf("%-*s", (int)v->width, kp->p_wmesg);
598 	} else
599 		(void)printf("%-*s", v->width, "-");
600 }
601 
602 void
603 vsize(const struct pinfo *pi, VARENT *ve)
604 {
605 	const struct kinfo_proc *kp = pi->ki;
606 	VAR *v;
607 
608 	v = ve->var;
609 	(void)printf("%*llu", v->width,
610 	    pgtok(kp->p_vm_dsize + kp->p_vm_ssize + kp->p_vm_tsize));
611 }
612 
613 void
614 rssize(const struct pinfo *pi, VARENT *ve)
615 {
616 	const struct kinfo_proc *kp = pi->ki;
617 	VAR *v;
618 
619 	v = ve->var;
620 	/* XXX don't have info about shared */
621 	(void)printf("%*llu", v->width, (kp->p_flag & P_SYSTEM) ? 0 :
622 	    pgtok(kp->p_vm_rssize));
623 }
624 
625 void
626 p_rssize(const struct pinfo *pi, VARENT *ve)
627 {
628 	const struct kinfo_proc *kp = pi->ki;
629 	VAR *v;
630 
631 	v = ve->var;
632 	(void)printf("%*llu", v->width, (kp->p_flag & P_SYSTEM) ? 0 :
633 	    pgtok(kp->p_vm_rssize));
634 }
635 
636 void
637 cputime(const struct pinfo *pi, VARENT *ve)
638 {
639 	const struct kinfo_proc *kp = pi->ki;
640 	VAR *v;
641 	long secs;
642 	long psecs;	/* "parts" of a second. first micro, then centi */
643 	char obuff[128];
644 
645 	v = ve->var;
646 	if (kp->p_stat == SDEAD || !kp->p_uvalid) {
647 		secs = 0;
648 		psecs = 0;
649 	} else {
650 		/*
651 		 * This counts time spent handling interrupts.  XXX
652 		 */
653 		secs = kp->p_rtime_sec;
654 		psecs = kp->p_rtime_usec;
655 		if (sumrusage) {
656 			secs += kp->p_uctime_sec;
657 			psecs += kp->p_uctime_usec;
658 		}
659 		/*
660 		 * round and scale to 100's
661 		 */
662 		psecs = (psecs + 5000) / 10000;
663 		secs += psecs / 100;
664 		psecs = psecs % 100;
665 	}
666 	(void)snprintf(obuff, sizeof(obuff),
667 	    "%3ld:%02ld.%02ld", secs/60, secs%60, psecs);
668 	(void)printf("%*s", v->width, obuff);
669 }
670 
671 double
672 getpcpu(const struct kinfo_proc *kp)
673 {
674 	if (fscale == 0)
675 		return (0.0);
676 
677 #define	fxtofl(fixpt)	((double)(fixpt) / fscale)
678 
679 	return (100.0 * fxtofl(kp->p_pctcpu));
680 }
681 
682 void
683 pcpu(const struct pinfo *pi, VARENT *ve)
684 {
685 	VAR *v;
686 
687 	v = ve->var;
688 	(void)printf("%*.1f", v->width, getpcpu(pi->ki));
689 }
690 
691 double
692 getpmem(const struct kinfo_proc *kp)
693 {
694 	double fracmem;
695 
696 	if (mempages == 0)
697 		return (0.0);
698 
699 	if (kp->p_flag & P_SYSTEM)
700 		return (0.0);
701 	/* XXX don't have info about shared */
702 	fracmem = ((float)kp->p_vm_rssize)/mempages;
703 	return (100.0 * fracmem);
704 }
705 
706 void
707 pmem(const struct pinfo *pi, VARENT *ve)
708 {
709 	VAR *v;
710 
711 	v = ve->var;
712 	(void)printf("%*.1f", v->width, getpmem(pi->ki));
713 }
714 
715 void
716 pagein(const struct pinfo *pi, VARENT *ve)
717 {
718 	const struct kinfo_proc *kp = pi->ki;
719 	VAR *v;
720 
721 	v = ve->var;
722 	(void)printf("%*llu", v->width,
723 	    kp->p_uvalid ? kp->p_uru_majflt : 0);
724 }
725 
726 void
727 maxrss(const struct pinfo *pi, VARENT *ve)
728 {
729 	const struct kinfo_proc *kp = pi->ki;
730 	VAR *v;
731 
732 	v = ve->var;
733 	(void)printf("%*llu", v->width, kp->p_rlim_rss_cur / 1024);
734 }
735 
736 void
737 tsize(const struct pinfo *pi, VARENT *ve)
738 {
739 	const struct kinfo_proc *kp = pi->ki;
740 	VAR *v;
741 
742 	v = ve->var;
743 	(void)printf("%*llu", v->width, pgtok(kp->p_vm_tsize));
744 }
745 
746 void
747 dsize(const struct pinfo *pi, VARENT *ve)
748 {
749 	const struct kinfo_proc *kp = pi->ki;
750 	VAR *v;
751 
752 	v = ve->var;
753 	(void)printf("%*llu", v->width, pgtok(kp->p_vm_dsize));
754 }
755 
756 void
757 ssize(const struct pinfo *pi, VARENT *ve)
758 {
759 	const struct kinfo_proc *kp = pi->ki;
760 	VAR *v;
761 
762 	v = ve->var;
763 	(void)printf("%*llu", v->width, pgtok(kp->p_vm_ssize));
764 }
765 
766 /*
767  * Generic output routines.  Print fields from various prototype
768  * structures.
769  */
770 static void
771 printval(char *bp, VAR *v)
772 {
773 	char ofmt[32];
774 
775 	snprintf(ofmt, sizeof(ofmt), "%%%s*%s", (v->flag & LJUST) ? "-" : "",
776 	    v->fmt);
777 
778 	/*
779 	 * Note that the "INF127" check is nonsensical for types
780 	 * that are or can be signed.
781 	 */
782 #define	GET(type)		(*(type *)bp)
783 #define	CHK_INF127(n)		(((n) > 127) && (v->flag & INF127) ? 127 : (n))
784 
785 	switch (v->type) {
786 	case INT8:
787 		(void)printf(ofmt, v->width, GET(int8_t));
788 		break;
789 	case UINT8:
790 		(void)printf(ofmt, v->width, CHK_INF127(GET(u_int8_t)));
791 		break;
792 	case INT16:
793 		(void)printf(ofmt, v->width, GET(int16_t));
794 		break;
795 	case UINT16:
796 		(void)printf(ofmt, v->width, CHK_INF127(GET(u_int16_t)));
797 		break;
798 	case INT32:
799 		(void)printf(ofmt, v->width, GET(int32_t));
800 		break;
801 	case UINT32:
802 		(void)printf(ofmt, v->width, CHK_INF127(GET(u_int32_t)));
803 		break;
804 	case INT64:
805 		(void)printf(ofmt, v->width, GET(int64_t));
806 		break;
807 	case UINT64:
808 		(void)printf(ofmt, v->width, CHK_INF127(GET(u_int64_t)));
809 		break;
810 	default:
811 		errx(1, "unknown type %d", v->type);
812 	}
813 #undef GET
814 #undef CHK_INF127
815 }
816 
817 void
818 pvar(const struct pinfo *pi, VARENT *ve)
819 {
820 	const struct kinfo_proc *kp = pi->ki;
821 	VAR *v;
822 
823 	v = ve->var;
824 	if ((v->flag & USER) && !kp->p_uvalid)
825 		(void)printf("%*s", v->width, "-");
826 	else
827 		printval((char *)kp + v->off, v);
828 }
829