xref: /openbsd-src/bin/ps/print.c (revision 8550894424f8a4aa4aafb6cd57229dd6ed7cd9dd)
1 /*	$OpenBSD: print.c,v 1.85 2023/01/07 05:24:59 guenther 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 static int
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 (!now)
528 		(void)time(&now);
529 	if (now - kp->p_ustart_sec < 12 * SECSPERHOUR) {
530 		(void)strftime(buf, sizeof(buf) - 1, "%l:%M%p", tp);
531 	} else if (now - kp->p_ustart_sec < 7 * SECSPERDAY) {
532 		(void)strftime(buf, sizeof(buf) - 1, "%a%I%p", tp);
533 	} else
534 		(void)strftime(buf, sizeof(buf) - 1, "%e%b%y", tp);
535 	(void)printf("%-*s", v->width, buf);
536 }
537 
538 void
539 lstarted(const struct pinfo *pi, VARENT *ve)
540 {
541 	const struct kinfo_proc *kp = pi->ki;
542 	VAR *v;
543 	time_t startt;
544 	char buf[100];
545 
546 	v = ve->var;
547 	if (!kp->p_uvalid) {
548 		(void)printf("%-*s", v->width, "-");
549 		return;
550 	}
551 	startt = kp->p_ustart_sec;
552 	(void)strftime(buf, sizeof(buf) -1, "%c",
553 	    localtime(&startt));
554 	(void)printf("%-*s", v->width, buf);
555 }
556 
557 void elapsed(const struct pinfo *pi, VARENT *ve)
558 {
559 	const struct kinfo_proc *kp = pi->ki;
560 	VAR *v;
561 	static time_t now;
562 	time_t secs;
563 	char buf[64];
564 	long days, hours, minutes, seconds;
565 
566 	v = ve->var;
567 	if (!kp->p_uvalid) {
568 		(void)printf("%*s", v->width, "-");
569 		return;
570 	}
571 
572 	if (!now)
573 		(void)time(&now);
574 	secs = now - kp->p_ustart_sec;
575 
576 	if (secs < 0) {
577 		(void)printf("%*s", v->width, "-");
578 		return;
579 	}
580 
581 	days = secs / SECSPERDAY;
582 	secs %= SECSPERDAY;
583 
584 	hours = secs / SECSPERHOUR;
585 	secs %= SECSPERHOUR;
586 
587 	minutes = secs / 60;
588 	seconds = secs % 60;
589 
590 	if (days > 0)
591 		(void)snprintf(buf, sizeof(buf), "%ld-%02ld:%02ld:%02ld",
592 		    days, hours, minutes, seconds);
593 	else if (hours > 0)
594 		(void)snprintf(buf, sizeof(buf), "%02ld:%02ld:%02ld",
595 		    hours, minutes, seconds);
596 	else
597 		(void)snprintf(buf, sizeof(buf), "%02ld:%02ld",
598 		    minutes, seconds);
599 	(void)printf("%*s", v->width, buf);
600 }
601 
602 void
603 wchan(const struct pinfo *pi, VARENT *ve)
604 {
605 	const struct kinfo_proc *kp = pi->ki;
606 	VAR *v;
607 
608 	v = ve->var;
609 	if (kp->p_wmesg[0]) {
610 		(void)printf("%-*s", (int)v->width, kp->p_wmesg);
611 	} else
612 		(void)printf("%-*s", v->width, "-");
613 }
614 
615 void
616 vsize(const struct pinfo *pi, VARENT *ve)
617 {
618 	const struct kinfo_proc *kp = pi->ki;
619 	VAR *v;
620 
621 	v = ve->var;
622 	(void)printf("%*llu", v->width,
623 	    pgtok(kp->p_vm_dsize + kp->p_vm_ssize + kp->p_vm_tsize));
624 }
625 
626 void
627 rssize(const struct pinfo *pi, VARENT *ve)
628 {
629 	const struct kinfo_proc *kp = pi->ki;
630 	VAR *v;
631 
632 	v = ve->var;
633 	/* XXX don't have info about shared */
634 	(void)printf("%*llu", v->width, (kp->p_flag & P_SYSTEM) ? 0 :
635 	    pgtok(kp->p_vm_rssize));
636 }
637 
638 void
639 p_rssize(const struct pinfo *pi, VARENT *ve)
640 {
641 	const struct kinfo_proc *kp = pi->ki;
642 	VAR *v;
643 
644 	v = ve->var;
645 	(void)printf("%*llu", v->width, (kp->p_flag & P_SYSTEM) ? 0 :
646 	    pgtok(kp->p_vm_rssize));
647 }
648 
649 void
650 cputime(const struct pinfo *pi, VARENT *ve)
651 {
652 	const struct kinfo_proc *kp = pi->ki;
653 	VAR *v;
654 	long secs;
655 	long psecs;	/* "parts" of a second. first micro, then centi */
656 	char obuff[128];
657 
658 	v = ve->var;
659 	if (kp->p_stat == SDEAD || !kp->p_uvalid) {
660 		secs = 0;
661 		psecs = 0;
662 	} else {
663 		/*
664 		 * This counts time spent handling interrupts.  XXX
665 		 */
666 		secs = kp->p_rtime_sec;
667 		psecs = kp->p_rtime_usec;
668 		if (sumrusage) {
669 			secs += kp->p_uctime_sec;
670 			psecs += kp->p_uctime_usec;
671 		}
672 		/*
673 		 * round and scale to 100's
674 		 */
675 		psecs = (psecs + 5000) / 10000;
676 		secs += psecs / 100;
677 		psecs = psecs % 100;
678 	}
679 	(void)snprintf(obuff, sizeof(obuff),
680 	    "%3ld:%02ld.%02ld", secs/60, secs%60, psecs);
681 	(void)printf("%*s", v->width, obuff);
682 }
683 
684 double
685 getpcpu(const struct kinfo_proc *kp)
686 {
687 	if (fscale == 0)
688 		return (0.0);
689 
690 #define	fxtofl(fixpt)	((double)(fixpt) / fscale)
691 
692 	return (100.0 * fxtofl(kp->p_pctcpu));
693 }
694 
695 void
696 pcpu(const struct pinfo *pi, VARENT *ve)
697 {
698 	VAR *v;
699 
700 	v = ve->var;
701 	(void)printf("%*.1f", v->width, getpcpu(pi->ki));
702 }
703 
704 double
705 getpmem(const struct kinfo_proc *kp)
706 {
707 	double fracmem;
708 
709 	if (mempages == 0)
710 		return (0.0);
711 
712 	if (kp->p_flag & P_SYSTEM)
713 		return (0.0);
714 	/* XXX don't have info about shared */
715 	fracmem = ((float)kp->p_vm_rssize)/mempages;
716 	return (100.0 * fracmem);
717 }
718 
719 void
720 pmem(const struct pinfo *pi, VARENT *ve)
721 {
722 	VAR *v;
723 
724 	v = ve->var;
725 	(void)printf("%*.1f", v->width, getpmem(pi->ki));
726 }
727 
728 void
729 pagein(const struct pinfo *pi, VARENT *ve)
730 {
731 	const struct kinfo_proc *kp = pi->ki;
732 	VAR *v;
733 
734 	v = ve->var;
735 	(void)printf("%*llu", v->width,
736 	    kp->p_uvalid ? kp->p_uru_majflt : 0);
737 }
738 
739 void
740 maxrss(const struct pinfo *pi, VARENT *ve)
741 {
742 	const struct kinfo_proc *kp = pi->ki;
743 	VAR *v;
744 
745 	v = ve->var;
746 	(void)printf("%*llu", v->width, kp->p_rlim_rss_cur / 1024);
747 }
748 
749 void
750 tsize(const struct pinfo *pi, VARENT *ve)
751 {
752 	const struct kinfo_proc *kp = pi->ki;
753 	VAR *v;
754 
755 	v = ve->var;
756 	(void)printf("%*llu", v->width, pgtok(kp->p_vm_tsize));
757 }
758 
759 void
760 dsize(const struct pinfo *pi, VARENT *ve)
761 {
762 	const struct kinfo_proc *kp = pi->ki;
763 	VAR *v;
764 
765 	v = ve->var;
766 	(void)printf("%*llu", v->width, pgtok(kp->p_vm_dsize));
767 }
768 
769 void
770 ssize(const struct pinfo *pi, VARENT *ve)
771 {
772 	const struct kinfo_proc *kp = pi->ki;
773 	VAR *v;
774 
775 	v = ve->var;
776 	(void)printf("%*llu", v->width, pgtok(kp->p_vm_ssize));
777 }
778 
779 /*
780  * Generic output routines.  Print fields from various prototype
781  * structures.
782  */
783 static void
784 printval(char *bp, VAR *v)
785 {
786 	char ofmt[32];
787 
788 	snprintf(ofmt, sizeof(ofmt), "%%%s*%s", (v->flag & LJUST) ? "-" : "",
789 	    v->fmt);
790 
791 	/*
792 	 * Note that the "INF127" check is nonsensical for types
793 	 * that are or can be signed.
794 	 */
795 #define	GET(type)		(*(type *)bp)
796 #define	CHK_INF127(n)		(((n) > 127) && (v->flag & INF127) ? 127 : (n))
797 
798 	switch (v->type) {
799 	case INT8:
800 		(void)printf(ofmt, v->width, GET(int8_t));
801 		break;
802 	case UINT8:
803 		(void)printf(ofmt, v->width, CHK_INF127(GET(u_int8_t)));
804 		break;
805 	case INT16:
806 		(void)printf(ofmt, v->width, GET(int16_t));
807 		break;
808 	case UINT16:
809 		(void)printf(ofmt, v->width, CHK_INF127(GET(u_int16_t)));
810 		break;
811 	case INT32:
812 		(void)printf(ofmt, v->width, GET(int32_t));
813 		break;
814 	case UINT32:
815 		(void)printf(ofmt, v->width, CHK_INF127(GET(u_int32_t)));
816 		break;
817 	case INT64:
818 		(void)printf(ofmt, v->width, GET(int64_t));
819 		break;
820 	case UINT64:
821 		(void)printf(ofmt, v->width, CHK_INF127(GET(u_int64_t)));
822 		break;
823 	default:
824 		errx(1, "unknown type %d", v->type);
825 	}
826 #undef GET
827 #undef CHK_INF127
828 }
829 
830 void
831 pvar(const struct pinfo *pi, VARENT *ve)
832 {
833 	const struct kinfo_proc *kp = pi->ki;
834 	VAR *v;
835 
836 	v = ve->var;
837 	if ((v->flag & USER) && !kp->p_uvalid)
838 		(void)printf("%*s", v->width, "-");
839 	else
840 		printval((char *)kp + v->off, v);
841 }
842