Home | History | Annotate | Line # | Download | only in ps
      1 /*	$NetBSD: print.c,v 1.138 2022/01/26 11:48:53 andvar Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2000, 2007 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Simon Burge.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 /*
     33  * Copyright (c) 1990, 1993, 1994
     34  *	The Regents of the University of California.  All rights reserved.
     35  *
     36  * Redistribution and use in source and binary forms, with or without
     37  * modification, are permitted provided that the following conditions
     38  * are met:
     39  * 1. Redistributions of source code must retain the above copyright
     40  *    notice, this list of conditions and the following disclaimer.
     41  * 2. Redistributions in binary form must reproduce the above copyright
     42  *    notice, this list of conditions and the following disclaimer in the
     43  *    documentation and/or other materials provided with the distribution.
     44  * 3. Neither the name of the University nor the names of its contributors
     45  *    may be used to endorse or promote products derived from this software
     46  *    without specific prior written permission.
     47  *
     48  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     50  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     51  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     52  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     53  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     54  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     55  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     56  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     57  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     58  * SUCH DAMAGE.
     59  */
     60 
     61 #include <sys/cdefs.h>
     62 #ifndef lint
     63 #if 0
     64 static char sccsid[] = "@(#)print.c	8.6 (Berkeley) 4/16/94";
     65 #else
     66 __RCSID("$NetBSD: print.c,v 1.138 2022/01/26 11:48:53 andvar Exp $");
     67 #endif
     68 #endif /* not lint */
     69 
     70 #include <sys/param.h>
     71 #include <sys/time.h>
     72 #include <sys/resource.h>
     73 #include <sys/sysctl.h>
     74 #include <sys/lwp.h>
     75 #include <sys/proc.h>
     76 #include <sys/stat.h>
     77 #include <sys/ucred.h>
     78 #include <sys/sysctl.h>
     79 #include <sys/acct.h>
     80 #include <sys/ktrace.h>
     81 
     82 #include <err.h>
     83 #include <grp.h>
     84 #include <kvm.h>
     85 #include <math.h>
     86 #include <nlist.h>
     87 #include <pwd.h>
     88 #include <stddef.h>
     89 #include <stdio.h>
     90 #include <stdlib.h>
     91 #include <string.h>
     92 #include <time.h>
     93 #include <util.h>
     94 #include <tzfile.h>
     95 #include <unistd.h>
     96 #include <signal.h>
     97 
     98 #include "ps.h"
     99 
    100 static char *cmdpart(char *);
    101 static void  printval(void *, VAR *, enum mode);
    102 static int   titlecmp(char *, char **);
    103 
    104 static void  doubleprintorsetwidth(VAR *, double, int, enum mode);
    105 static void  intprintorsetwidth(VAR *, int, enum mode);
    106 static void  strprintorsetwidth(VAR *, const char *, enum mode);
    107 
    108 static time_t now;
    109 
    110 #define	min(a,b)	((a) <= (b) ? (a) : (b))
    111 
    112 /* pre-NetBSD 5.x support. */
    113 #ifndef LSDEAD
    114 #define LSDEAD 6
    115 #endif
    116 
    117 static void __attribute__((__format__(__strftime__, 3, 0)))
    118 safe_strftime(char *buf, size_t bufsiz, const char *fmt,
    119     const struct tm *tp)
    120 {
    121 	if (tp == NULL || strftime(buf, bufsiz, fmt, tp) == 0)
    122 		strlcpy(buf, "-", sizeof(buf));
    123 }
    124 
    125 static int
    126 iwidth(u_int64_t v)
    127 {
    128 	u_int64_t nlim, lim;
    129 	int w = 1;
    130 
    131 	for (lim = 10; v >= lim; lim = nlim) {
    132 		nlim = lim * 10;
    133 		w++;
    134 		if (nlim < lim)
    135 			break;
    136 	}
    137 	return w;
    138 }
    139 
    140 static char *
    141 cmdpart(char *arg0)
    142 {
    143 	char *cp;
    144 
    145 	return ((cp = strrchr(arg0, '/')) != NULL ? cp + 1 : arg0);
    146 }
    147 
    148 void
    149 printheader(void)
    150 {
    151 	int len;
    152 	VAR *v;
    153 	struct varent *vent;
    154 	static int firsttime = 1;
    155 	static int noheader = 0;
    156 
    157 	/*
    158 	 * If all the columns have user-specified null headers,
    159 	 * don't print the blank header line at all.
    160 	 */
    161 	if (firsttime) {
    162 		SIMPLEQ_FOREACH(vent, &displaylist, next) {
    163 			if (vent->var->header[0])
    164 				break;
    165 		}
    166 		if (vent == NULL) {
    167 			noheader = 1;
    168 			firsttime = 0;
    169 		}
    170 
    171 	}
    172 	if (noheader)
    173 		return;
    174 
    175 	SIMPLEQ_FOREACH(vent, &displaylist, next) {
    176 		v = vent->var;
    177 		if (firsttime) {
    178 			len = strlen(v->header);
    179 			if (len > v->width)
    180 				v->width = len;
    181 			totwidth += v->width + 1;	/* +1 for space */
    182 		}
    183 		if (v->flag & LJUST) {
    184 			if (SIMPLEQ_NEXT(vent, next) == NULL)	/* last one */
    185 				(void)printf("%s", v->header);
    186 			else
    187 				(void)printf("%-*s", v->width,
    188 				    v->header);
    189 		} else
    190 			(void)printf("%*s", v->width, v->header);
    191 		if (SIMPLEQ_NEXT(vent, next) != NULL)
    192 			(void)putchar(' ');
    193 	}
    194 	(void)putchar('\n');
    195 	if (firsttime) {
    196 		firsttime = 0;
    197 		totwidth--;	/* take off last space */
    198 	}
    199 }
    200 
    201 /*
    202  * Return 1 if the command name in the argument vector (u-area) does
    203  * not match the command name (p_comm)
    204  */
    205 static int
    206 titlecmp(char *name, char **argv)
    207 {
    208 	char *title;
    209 	int namelen;
    210 
    211 
    212 	/* no argument vector == no match; system processes/threads do that */
    213 	if (argv == 0 || argv[0] == 0)
    214 		return (1);
    215 
    216 	title = cmdpart(argv[0]);
    217 
    218 	/* the basename matches */
    219 	if (!strcmp(name, title))
    220 		return (0);
    221 
    222 	/* handle login shells, by skipping the leading - */
    223 	if (title[0] == '-' && !strcmp(name, title + 1))
    224 		return (0);
    225 
    226 	namelen = strlen(name);
    227 
    228 	/* handle daemons that report activity as daemonname: activity */
    229 	if (argv[1] == 0 &&
    230 	    !strncmp(name, title, namelen) &&
    231 	    title[namelen + 0] == ':' &&
    232 	    title[namelen + 1] == ' ')
    233 		return (0);
    234 
    235 	return (1);
    236 }
    237 
    238 static void
    239 doubleprintorsetwidth(VAR *v, double val, int prec, enum mode mode)
    240 {
    241 	int fmtlen;
    242 
    243 	if (mode == WIDTHMODE) {
    244 		if (val < 0.0 && val < v->longestnd) {
    245 			fmtlen = (int)log10(-val) + prec + 2;
    246 			v->longestnd = val;
    247 			if (fmtlen > v->width)
    248 				v->width = fmtlen;
    249 		} else if (val > 0.0 && val > v->longestpd) {
    250 			fmtlen = (int)log10(val) + prec + 1;
    251 			v->longestpd = val;
    252 			if (fmtlen > v->width)
    253 				v->width = fmtlen;
    254 		}
    255 	} else {
    256 		(void)printf("%*.*f", v->width, prec, val);
    257 	}
    258 }
    259 
    260 static void
    261 intprintorsetwidth(VAR *v, int val, enum mode mode)
    262 {
    263 	int fmtlen;
    264 
    265 	if (mode == WIDTHMODE) {
    266 		if (val < 0 && val < v->longestn) {
    267 			v->longestn = val;
    268 			fmtlen = iwidth(-val) + 1;
    269 			if (fmtlen > v->width)
    270 				v->width = fmtlen;
    271 		} else if (val > 0 && val > v->longestp) {
    272 			v->longestp = val;
    273 			fmtlen = iwidth(val);
    274 			if (fmtlen > v->width)
    275 				v->width = fmtlen;
    276 		}
    277 	} else
    278 		(void)printf("%*d", v->width, val);
    279 }
    280 
    281 static void
    282 strprintorsetwidth(VAR *v, const char *str, enum mode mode)
    283 {
    284 	int len;
    285 
    286 	if (mode == WIDTHMODE) {
    287 		len = strlen(str);
    288 		if (len > v->width)
    289 			v->width = len;
    290 	} else {
    291 		if (v->flag & LJUST)
    292 			(void)printf("%-*.*s", v->width, v->width, str);
    293 		else
    294 			(void)printf("%*.*s", v->width, v->width, str);
    295 	}
    296 }
    297 
    298 void
    299 command(struct pinfo *pi, VARENT *ve, enum mode mode)
    300 {
    301 	struct kinfo_proc2 *ki = pi->ki;
    302 	VAR *v;
    303 	int left;
    304 	char **argv, **p, *name;
    305 
    306 	if (mode == WIDTHMODE)
    307 		return;
    308 
    309 	v = ve->var;
    310 	if (SIMPLEQ_NEXT(ve, next) != NULL || termwidth != UNLIMITED) {
    311 		if (SIMPLEQ_NEXT(ve, next) == NULL) {
    312 			left = termwidth - (totwidth - v->width);
    313 			if (left < 1) /* already wrapped, just use std width */
    314 				left = v->width;
    315 		} else
    316 			left = v->width;
    317 	} else
    318 		left = -1;
    319 	if (needenv && kd) {
    320 		argv = kvm_getenvv2(kd, ki, termwidth);
    321 		if ((p = argv) != NULL) {
    322 			while (*p) {
    323 				fmt_puts(*p, &left);
    324 				p++;
    325 				fmt_putc(' ', &left);
    326 			}
    327 		}
    328 	}
    329 	if (needcomm) {
    330 		if (pi->prefix)
    331 			(void)fmt_puts(pi->prefix, &left);
    332 		name = ki->p_comm;
    333 		if (!commandonly) {
    334 			argv = kvm_getargv2(kd, ki, termwidth);
    335 			if ((p = argv) != NULL) {
    336 				while (*p) {
    337 					fmt_puts(*p, &left);
    338 					p++;
    339 					fmt_putc(' ', &left);
    340 					if (v->flag & ARGV0)
    341 						break;
    342 				}
    343 				if (!(v->flag & ARGV0) &&
    344 				    titlecmp(name, argv)) {
    345 					/*
    346 					 * append the real command name within
    347 					 * parentheses, if the command name
    348 					 * does not match the one in the
    349 					 * argument vector
    350 					 */
    351 					fmt_putc('(', &left);
    352 					fmt_puts(name, &left);
    353 					fmt_putc(')', &left);
    354 				}
    355 			} else {
    356 				/*
    357 				 * Commands that don't set an argv vector
    358 				 * are printed with square brackets if they
    359 				 * are system commands.  Otherwise they are
    360 				 * printed within parentheses.
    361 				 */
    362 				if (ki->p_flag & P_SYSTEM) {
    363 					fmt_putc('[', &left);
    364 					fmt_puts(name, &left);
    365 					fmt_putc(']', &left);
    366 				} else {
    367 					fmt_putc('(', &left);
    368 					fmt_puts(name, &left);
    369 					fmt_putc(')', &left);
    370 				}
    371 			}
    372 		} else {
    373 			fmt_puts(name, &left);
    374 		}
    375 	}
    376 	if (SIMPLEQ_NEXT(ve, next) != NULL && left > 0)
    377 		(void)printf("%*s", left, "");
    378 }
    379 
    380 void
    381 groups(struct pinfo *pi, VARENT *ve, enum mode mode)
    382 {
    383 	struct kinfo_proc2 *ki = pi->ki;
    384 	VAR *v;
    385 	int left, i;
    386 	char buf[16], *p;
    387 
    388 	if (mode == WIDTHMODE)
    389 		return;
    390 
    391 	v = ve->var;
    392 	if (SIMPLEQ_NEXT(ve, next) != NULL || termwidth != UNLIMITED) {
    393 		if (SIMPLEQ_NEXT(ve, next) == NULL) {
    394 			left = termwidth - (totwidth - v->width);
    395 			if (left < 1) /* already wrapped, just use std width */
    396 				left = v->width;
    397 		} else
    398 			left = v->width;
    399 	} else
    400 		left = -1;
    401 
    402 	if (ki->p_ngroups == 0)
    403 		fmt_putc('-', &left);
    404 
    405 	for (i = 0; i < ki->p_ngroups; i++) {
    406 		(void)snprintf(buf, sizeof(buf), "%d", ki->p_groups[i]);
    407 		if (i)
    408 			fmt_putc(' ', &left);
    409 		for (p = &buf[0]; *p; p++)
    410 			fmt_putc(*p, &left);
    411 	}
    412 
    413 	if (SIMPLEQ_NEXT(ve, next) != NULL && left > 0)
    414 		(void)printf("%*s", left, "");
    415 }
    416 
    417 void
    418 groupnames(struct pinfo *pi, VARENT *ve, enum mode mode)
    419 {
    420 	struct kinfo_proc2 *ki = pi->ki;
    421 	VAR *v;
    422 	int left, i;
    423 	const char *p;
    424 
    425 	if (mode == WIDTHMODE)
    426 		return;
    427 
    428 	v = ve->var;
    429 	if (SIMPLEQ_NEXT(ve, next) != NULL || termwidth != UNLIMITED) {
    430 		if (SIMPLEQ_NEXT(ve, next) == NULL) {
    431 			left = termwidth - (totwidth - v->width);
    432 			if (left < 1) /* already wrapped, just use std width */
    433 				left = v->width;
    434 		} else
    435 			left = v->width;
    436 	} else
    437 		left = -1;
    438 
    439 	if (ki->p_ngroups == 0)
    440 		fmt_putc('-', &left);
    441 
    442 	for (i = 0; i < ki->p_ngroups; i++) {
    443 		if (i)
    444 			fmt_putc(' ', &left);
    445 		for (p = group_from_gid(ki->p_groups[i], 0); *p; p++)
    446 			fmt_putc(*p, &left);
    447 	}
    448 
    449 	if (SIMPLEQ_NEXT(ve, next) != NULL && left > 0)
    450 		(void)printf("%*s", left, "");
    451 }
    452 
    453 void
    454 ucomm(struct pinfo *pi, VARENT *ve, enum mode mode)
    455 {
    456 	struct kinfo_proc2 *k = pi->ki;
    457 	char buf[MAXPATHLEN], *p;
    458 	VAR *v;
    459 
    460 	v = ve->var;
    461 	if (pi->prefix)
    462 		snprintf(p = buf, sizeof(buf), "%s%s", pi->prefix, k->p_comm);
    463 	else
    464 		p = k->p_comm;
    465 	strprintorsetwidth(v, p, mode);
    466 }
    467 
    468 void
    469 emul(struct pinfo *pi, VARENT *ve, enum mode mode)
    470 {
    471 	struct kinfo_proc2 *k = pi->ki;
    472 	VAR *v;
    473 
    474 	v = ve->var;
    475 	strprintorsetwidth(v, k->p_ename, mode);
    476 }
    477 
    478 void
    479 logname(struct pinfo *pi, VARENT *ve, enum mode mode)
    480 {
    481 	struct kinfo_proc2 *k = pi->ki;
    482 	VAR *v;
    483 
    484 	v = ve->var;
    485 	strprintorsetwidth(v, k->p_login, mode);
    486 }
    487 
    488 void
    489 state(struct pinfo *pi, VARENT *ve, enum mode mode)
    490 {
    491 	struct kinfo_proc2 *k = pi->ki;
    492 	int flag, is_zombie;
    493 	char *cp;
    494 	VAR *v;
    495 	char buf[16];
    496 
    497 	is_zombie = 0;
    498 	v = ve->var;
    499 	flag = k->p_flag;
    500 	cp = buf;
    501 
    502 	/*
    503 	 * NOTE: There are historical letters, which are no longer used:
    504 	 *
    505 	 * - W: indicated that process is swapped out.
    506 	 * - L: indicated non-zero l_holdcnt (i.e. that process was
    507 	 *   prevented from swapping-out.
    508 	 *
    509 	 * These letters should not be used for new states to avoid
    510 	 * conflicts with old applications which might depend on them.
    511 	 */
    512 	switch (k->p_stat) {
    513 
    514 	case LSSTOP:
    515 		*cp = 'T';
    516 		break;
    517 
    518 	case LSSLEEP:
    519 		if (flag & L_SINTR)	/* interruptable (long) */
    520 			*cp = (int)k->p_slptime >= maxslp ? 'I' : 'S';
    521 		else
    522 			*cp = 'D';
    523 		break;
    524 
    525 	case LSRUN:
    526 	case LSIDL:
    527 		*cp = 'R';
    528 		break;
    529 
    530 	case LSONPROC:
    531 		*cp = 'O';
    532 		break;
    533 
    534 	case LSZOMB:
    535 		*cp = 'Z';
    536 		is_zombie = 1;
    537 		break;
    538 
    539 	case LSSUSPENDED:
    540 		*cp = 'U';
    541 		break;
    542 
    543 	default:
    544 		*cp = '?';
    545 	}
    546 	cp++;
    547 	if (k->p_nice < NZERO)
    548 		*cp++ = '<';
    549 	else if (k->p_nice > NZERO)
    550 		*cp++ = 'N';
    551 	if (flag & P_TRACED)
    552 		*cp++ = 'X';
    553 	if (flag & P_WEXIT && !is_zombie)
    554 		*cp++ = 'E';
    555 	if (flag & P_PPWAIT)
    556 		*cp++ = 'V';
    557 	if (flag & P_SYSTEM)
    558 		*cp++ = 'K';
    559 	if (k->p_eflag & EPROC_SLEADER)
    560 		*cp++ = 's';
    561 	if (flag & P_SA)
    562 		*cp++ = 'a';
    563 	else if (k->p_nlwps > 1)
    564 		*cp++ = 'l';
    565 	if ((flag & P_CONTROLT) && k->p__pgid == k->p_tpgid)
    566 		*cp++ = '+';
    567 	*cp = '\0';
    568 	strprintorsetwidth(v, buf, mode);
    569 }
    570 
    571 void
    572 lstate(struct pinfo *pi, VARENT *ve, enum mode mode)
    573 {
    574 	struct kinfo_lwp *k = pi->li;
    575 	int flag;
    576 	char *cp;
    577 	VAR *v;
    578 	char buf[16];
    579 
    580 	v = ve->var;
    581 	flag = k->l_flag;
    582 	cp = buf;
    583 
    584 	switch (k->l_stat) {
    585 
    586 	case LSSTOP:
    587 		*cp = 'T';
    588 		break;
    589 
    590 	case LSSLEEP:
    591 		if (flag & L_SINTR)	/* interruptible (long) */
    592 			*cp = (int)k->l_slptime >= maxslp ? 'I' : 'S';
    593 		else
    594 			*cp = 'D';
    595 		break;
    596 
    597 	case LSRUN:
    598 	case LSIDL:
    599 		*cp = 'R';
    600 		break;
    601 
    602 	case LSONPROC:
    603 		*cp = 'O';
    604 		break;
    605 
    606 	case LSZOMB:
    607 	case LSDEAD:
    608 		*cp = 'Z';
    609 		break;
    610 
    611 	case LSSUSPENDED:
    612 		*cp = 'U';
    613 		break;
    614 
    615 	default:
    616 		*cp = '?';
    617 	}
    618 	cp++;
    619 	if (flag & L_SYSTEM)
    620 		*cp++ = 'K';
    621 	if (flag & L_SA)
    622 		*cp++ = 'a';
    623 	if (flag & L_DETACHED)
    624 		*cp++ = '-';
    625 	*cp = '\0';
    626 	strprintorsetwidth(v, buf, mode);
    627 }
    628 
    629 void
    630 pnice(struct pinfo *pi, VARENT *ve, enum mode mode)
    631 {
    632 	struct kinfo_proc2 *k = pi->ki;
    633 	VAR *v;
    634 
    635 	v = ve->var;
    636 	intprintorsetwidth(v, k->p_nice - NZERO, mode);
    637 }
    638 
    639 void
    640 pri(struct pinfo *pi, VARENT *ve, enum mode mode)
    641 {
    642 	struct kinfo_lwp *l = pi->li;
    643 	VAR *v;
    644 
    645 	v = ve->var;
    646 	intprintorsetwidth(v, l->l_priority, mode);
    647 }
    648 
    649 void
    650 usrname(struct pinfo *pi, VARENT *ve, enum mode mode)
    651 {
    652 	struct kinfo_proc2 *k = pi->ki;
    653 	VAR *v;
    654 
    655 	v = ve->var;
    656 	strprintorsetwidth(v, user_from_uid(k->p_uid, 0), mode);
    657 }
    658 
    659 void
    660 runame(struct pinfo *pi, VARENT *ve, enum mode mode)
    661 {
    662 	struct kinfo_proc2 *k = pi->ki;
    663 	VAR *v;
    664 
    665 	v = ve->var;
    666 	strprintorsetwidth(v, user_from_uid(k->p_ruid, 0), mode);
    667 }
    668 
    669 void
    670 svuname(struct pinfo *pi, VARENT *ve, enum mode mode)
    671 {
    672 	struct kinfo_proc2 *k = pi->ki;
    673 	VAR *v;
    674 
    675 	v = ve->var;
    676 	strprintorsetwidth(v, user_from_uid(k->p_svuid, 0), mode);
    677 }
    678 
    679 void
    680 gname(struct pinfo *pi, VARENT *ve, enum mode mode)
    681 {
    682 	struct kinfo_proc2 *k = pi->ki;
    683 	VAR *v;
    684 
    685 	v = ve->var;
    686 	strprintorsetwidth(v, group_from_gid(k->p_gid, 0), mode);
    687 }
    688 
    689 void
    690 rgname(struct pinfo *pi, VARENT *ve, enum mode mode)
    691 {
    692 	struct kinfo_proc2 *k = pi->ki;
    693 	VAR *v;
    694 
    695 	v = ve->var;
    696 	strprintorsetwidth(v, group_from_gid(k->p_rgid, 0), mode);
    697 }
    698 
    699 void
    700 svgname(struct pinfo *pi, VARENT *ve, enum mode mode)
    701 {
    702 	struct kinfo_proc2 *k = pi->ki;
    703 	VAR *v;
    704 
    705 	v = ve->var;
    706 	strprintorsetwidth(v, group_from_gid(k->p_svgid, 0), mode);
    707 }
    708 
    709 void
    710 tdev(struct pinfo *pi, VARENT *ve, enum mode mode)
    711 {
    712 	struct kinfo_proc2 *k = pi->ki;
    713 	VAR *v;
    714 	dev_t dev;
    715 	char buff[16];
    716 
    717 	v = ve->var;
    718 	dev = k->p_tdev;
    719 	if (dev == NODEV) {
    720 		if (mode == PRINTMODE)
    721 			(void)printf("%*s", v->width, "?");
    722 		else
    723 			if (v->width < 2)
    724 				v->width = 2;
    725 	} else {
    726 		(void)snprintf(buff, sizeof(buff),
    727 		    "%lld/%lld", (long long)major(dev), (long long)minor(dev));
    728 		strprintorsetwidth(v, buff, mode);
    729 	}
    730 }
    731 
    732 void
    733 tname(struct pinfo *pi, VARENT *ve, enum mode mode)
    734 {
    735 	struct kinfo_proc2 *k = pi->ki;
    736 	VAR *v;
    737 	dev_t dev;
    738 	const char *ttname;
    739 	int noctty;
    740 
    741 	v = ve->var;
    742 	dev = k->p_tdev;
    743 	if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL) {
    744 		if (mode == PRINTMODE)
    745 			(void)printf("%-*s", v->width, "?");
    746 		else
    747 			if (v->width < 2)
    748 				v->width = 2;
    749 	} else {
    750 		noctty = !(k->p_eflag & EPROC_CTTY) ? 1 : 0;
    751 		if (mode == WIDTHMODE) {
    752 			int fmtlen;
    753 
    754 			fmtlen = strlen(ttname) + noctty;
    755 			if (v->width < fmtlen)
    756 				v->width = fmtlen;
    757 		} else {
    758 			if (noctty)
    759 				(void)printf("%-*s-", v->width - 1, ttname);
    760 			else
    761 				(void)printf("%-*s", v->width, ttname);
    762 		}
    763 	}
    764 }
    765 
    766 void
    767 longtname(struct pinfo *pi, VARENT *ve, enum mode mode)
    768 {
    769 	struct kinfo_proc2 *k = pi->ki;
    770 	VAR *v;
    771 	dev_t dev;
    772 	const char *ttname;
    773 
    774 	v = ve->var;
    775 	dev = k->p_tdev;
    776 	if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL) {
    777 		if (mode == PRINTMODE)
    778 			(void)printf("%-*s", v->width, "?");
    779 		else
    780 			if (v->width < 2)
    781 				v->width = 2;
    782 	} else {
    783 		strprintorsetwidth(v, ttname, mode);
    784 	}
    785 }
    786 
    787 void
    788 started(struct pinfo *pi, VARENT *ve, enum mode mode)
    789 {
    790 	struct kinfo_proc2 *k = pi->ki;
    791 	VAR *v;
    792 	time_t startt;
    793 	struct tm *tp;
    794 	char buf[100], *cp;
    795 
    796 	v = ve->var;
    797 	if (!k->p_uvalid) {
    798 		if (mode == PRINTMODE)
    799 			(void)printf("%*s", v->width, "-");
    800 		return;
    801 	}
    802 
    803 	startt = k->p_ustart_sec;
    804 	tp = localtime(&startt);
    805 	if (now == 0)
    806 		(void)time(&now);
    807 	if (now - k->p_ustart_sec < SECSPERDAY)
    808 		safe_strftime(buf, sizeof(buf) - 1, "%l:%M%p", tp);
    809 	else if (now - k->p_ustart_sec < DAYSPERWEEK * SECSPERDAY)
    810 		safe_strftime(buf, sizeof(buf) - 1, "%a%I%p", tp);
    811 	else
    812 		safe_strftime(buf, sizeof(buf) - 1, "%e%b%y", tp);
    813 	/* %e and %l can start with a space. */
    814 	cp = buf;
    815 	if (*cp == ' ')
    816 		cp++;
    817 	strprintorsetwidth(v, cp, mode);
    818 }
    819 
    820 void
    821 lstarted(struct pinfo *pi, VARENT *ve, enum mode mode)
    822 {
    823 	struct kinfo_proc2 *k = pi->ki;
    824 	VAR *v;
    825 	time_t startt;
    826 	char buf[100];
    827 
    828 	v = ve->var;
    829 	startt = k->p_ustart_sec;
    830 
    831 	if (mode == WIDTHMODE) {
    832 		/*
    833 		 * We only need to set the width once, as we assume
    834 		 * that all times are the same length.  We do need to
    835 		 * check against the header length as well, as "no
    836 		 * header" mode for this variable will set the field
    837 		 * width to the length of the header anyway (ref: the
    838 		 * P1003.1-2004 comment in findvar()).
    839 		 *
    840 		 * XXX: The hardcoded "STARTED" string.  Better or
    841 		 * worse than a "<= 7" or some other arbitrary number?
    842 		 */
    843 		if (v->width > (int)sizeof("STARTED") - 1) {
    844 			return;
    845 		}
    846 	} else {
    847 		if (!k->p_uvalid) {
    848 			(void)printf("%*s", v->width, "-");
    849 			return;
    850 		}
    851 	}
    852 	safe_strftime(buf, sizeof(buf) - 1, "%c", localtime(&startt));
    853 	strprintorsetwidth(v, buf, mode);
    854 }
    855 
    856 void
    857 elapsed(struct pinfo *pi, VARENT *ve, enum mode mode)
    858 {
    859 	struct kinfo_proc2 *k = pi->ki;
    860 	VAR *v;
    861 	int32_t origseconds, secs, mins, hours, days;
    862 	int fmtlen, printed_something;
    863 
    864 	v = ve->var;
    865 	if (k->p_uvalid == 0) {
    866 		origseconds = 0;
    867 	} else {
    868 		if (now == 0)
    869 			(void)time(&now);
    870 		origseconds = now - k->p_ustart_sec;
    871 		if (origseconds < 0) {
    872 			/*
    873 			 * Don't try to be fancy if the machine's
    874 			 * clock has been rewound to before the
    875 			 * process "started".
    876 			 */
    877 			origseconds = 0;
    878 		}
    879 	}
    880 
    881 	secs = origseconds;
    882 	mins = secs / SECSPERMIN;
    883 	secs %= SECSPERMIN;
    884 	hours = mins / MINSPERHOUR;
    885 	mins %= MINSPERHOUR;
    886 	days = hours / HOURSPERDAY;
    887 	hours %= HOURSPERDAY;
    888 
    889 	if (mode == WIDTHMODE) {
    890 		if (origseconds == 0)
    891 			/* non-zero so fmtlen is calculated at least once */
    892 			origseconds = 1;
    893 
    894 		if (origseconds > v->longestp) {
    895 			v->longestp = origseconds;
    896 
    897 			if (days > 0) {
    898 				/* +9 for "-hh:mm:ss" */
    899 				fmtlen = iwidth(days) + 9;
    900 			} else if (hours > 0) {
    901 				/* +6 for "mm:ss" */
    902 				fmtlen = iwidth(hours) + 6;
    903 			} else {
    904 				/* +3 for ":ss" */
    905 				fmtlen = iwidth(mins) + 3;
    906 			}
    907 
    908 			if (fmtlen > v->width)
    909 				v->width = fmtlen;
    910 		}
    911 	} else {
    912 		printed_something = 0;
    913 		fmtlen = v->width;
    914 
    915 		if (days > 0) {
    916 			(void)printf("%*d", fmtlen - 9, days);
    917 			printed_something = 1;
    918 		} else if (fmtlen > 9) {
    919 			(void)printf("%*s", fmtlen - 9, "");
    920 		}
    921 		if (fmtlen > 9)
    922 			fmtlen = 9;
    923 
    924 		if (printed_something) {
    925 			(void)printf("-%.*d", fmtlen - 7, hours);
    926 			printed_something = 1;
    927 		} else if (hours > 0) {
    928 			(void)printf("%*d", fmtlen - 6, hours);
    929 			printed_something = 1;
    930 		} else if (fmtlen > 6) {
    931 			(void)printf("%*s", fmtlen - 6, "");
    932 		}
    933 		if (fmtlen > 6)
    934 			fmtlen = 6;
    935 
    936 		/* Don't need to set fmtlen or printed_something any more... */
    937 		if (printed_something) {
    938 			(void)printf(":%.*d", fmtlen - 4, mins);
    939 		} else if (mins > 0) {
    940 			(void)printf("%*d", fmtlen - 3, mins);
    941 		} else if (fmtlen > 3) {
    942 			(void)printf("%*s", fmtlen - 3, "0");
    943 		}
    944 
    945 		(void)printf(":%.2d", secs);
    946 	}
    947 }
    948 
    949 void
    950 wchan(struct pinfo *pi, VARENT *ve, enum mode mode)
    951 {
    952 	struct kinfo_lwp *l = pi->li;
    953 	VAR *v;
    954 
    955 	v = ve->var;
    956 	if (l->l_wmesg[0]) {
    957 		strprintorsetwidth(v, l->l_wmesg, mode);
    958 		v->width = min(v->width, KI_WMESGLEN);
    959 	} else {
    960 		if (mode == PRINTMODE)
    961 			(void)printf("%-*s", v->width, "-");
    962 	}
    963 }
    964 
    965 #define	pgtok(a)        (((a)*(size_t)getpagesize())/1024)
    966 
    967 void
    968 vsize(struct pinfo *pi, VARENT *ve, enum mode mode)
    969 {
    970 	struct kinfo_proc2 *k = pi->ki;
    971 	VAR *v;
    972 
    973 	v = ve->var;
    974 	intprintorsetwidth(v, pgtok(k->p_vm_msize), mode);
    975 }
    976 
    977 void
    978 rssize(struct pinfo *pi, VARENT *ve, enum mode mode)
    979 {
    980 	struct kinfo_proc2 *k = pi->ki;
    981 	VAR *v;
    982 
    983 	v = ve->var;
    984 	/* XXX don't have info about shared */
    985 	intprintorsetwidth(v, pgtok(k->p_vm_rssize), mode);
    986 }
    987 
    988 void
    989 p_rssize(struct pinfo *pi, VARENT *ve, enum mode mode)	/* doesn't account for text */
    990 {
    991 	struct kinfo_proc2 *k = pi->ki;
    992 	VAR *v;
    993 
    994 	v = ve->var;
    995 	intprintorsetwidth(v, pgtok(k->p_vm_rssize), mode);
    996 }
    997 
    998 void
    999 cpuid(struct pinfo *pi, VARENT *ve, enum mode mode)
   1000 {
   1001 	struct kinfo_lwp *l = pi->li;
   1002 	VAR *v;
   1003 
   1004 	v = ve->var;
   1005 	intprintorsetwidth(v, l->l_cpuid, mode);
   1006 }
   1007 
   1008 static void
   1009 cputime1(int32_t secs, int32_t psecs, VAR *v, enum mode mode)
   1010 {
   1011 	int fmtlen;
   1012 
   1013 	/*
   1014 	 * round and scale to 100's
   1015 	 */
   1016 	psecs = (psecs + 5000) / 10000;
   1017 	secs += psecs / 100;
   1018 	psecs = psecs % 100;
   1019 
   1020 	if (mode == WIDTHMODE) {
   1021 		/*
   1022 		 * Ugg, this is the only field where a value of 0 is longer
   1023 		 * than the column title.
   1024 		 * Use SECSPERMIN, because secs is divided by that when
   1025 		 * passed to iwidth().
   1026 		 */
   1027 		if (secs == 0)
   1028 			secs = SECSPERMIN;
   1029 
   1030 		if (secs > v->longestp) {
   1031 			v->longestp = secs;
   1032 			/* "+6" for the ":%02ld.%02ld" in the printf() below */
   1033 			fmtlen = iwidth(secs / SECSPERMIN) + 6;
   1034 			if (fmtlen > v->width)
   1035 				v->width = fmtlen;
   1036 		}
   1037 	} else {
   1038 		(void)printf("%*ld:%02ld.%02ld", v->width - 6,
   1039 		    (long)(secs / SECSPERMIN), (long)(secs % SECSPERMIN),
   1040 		    (long)psecs);
   1041 	}
   1042 }
   1043 
   1044 void
   1045 cputime(struct pinfo *pi, VARENT *ve, enum mode mode)
   1046 {
   1047 	struct kinfo_proc2 *k = pi->ki;
   1048 	VAR *v;
   1049 	int32_t secs;
   1050 	int32_t psecs;	/* "parts" of a second. first micro, then centi */
   1051 
   1052 	v = ve->var;
   1053 
   1054 	/*
   1055 	 * This counts time spent handling interrupts.  We could
   1056 	 * fix this, but it is not 100% trivial (and interrupt
   1057 	 * time fractions only work on the sparc anyway).	XXX
   1058 	 */
   1059 	secs = k->p_rtime_sec;
   1060 	psecs = k->p_rtime_usec;
   1061 	if (sumrusage) {
   1062 		secs += k->p_uctime_sec;
   1063 		psecs += k->p_uctime_usec;
   1064 	}
   1065 
   1066 	cputime1(secs, psecs, v, mode);
   1067 }
   1068 
   1069 void
   1070 lcputime(struct pinfo *pi, VARENT *ve, enum mode mode)
   1071 {
   1072 	struct kinfo_lwp *l = pi->li;
   1073 	VAR *v;
   1074 	int32_t secs;
   1075 	int32_t psecs;	/* "parts" of a second. first micro, then centi */
   1076 
   1077 	v = ve->var;
   1078 
   1079 	secs = l->l_rtime_sec;
   1080 	psecs = l->l_rtime_usec;
   1081 
   1082 	cputime1(secs, psecs, v, mode);
   1083 }
   1084 
   1085 void
   1086 pcpu(struct pinfo *pi, VARENT *ve, enum mode mode)
   1087 {
   1088 	VAR *v;
   1089 	double dbl;
   1090 
   1091 	v = ve->var;
   1092 	dbl = pi->pcpu;
   1093 	doubleprintorsetwidth(v, dbl, (dbl >= 99.95) ? 0 : 1, mode);
   1094 }
   1095 
   1096 double
   1097 getpmem(const struct kinfo_proc2 *k)
   1098 {
   1099 	double fracmem;
   1100 	int szptudot;
   1101 
   1102 	if (!nlistread)
   1103 		donlist();
   1104 
   1105 	/* XXX want pmap ptpages, segtab, etc. (per architecture) */
   1106 	szptudot = uspace/getpagesize();
   1107 	/* XXX don't have info about shared */
   1108 	fracmem = ((float)k->p_vm_rssize + szptudot)/mempages;
   1109 	return (100.0 * fracmem);
   1110 }
   1111 
   1112 void
   1113 pmem(struct pinfo *pi, VARENT *ve, enum mode mode)
   1114 {
   1115 	struct kinfo_proc2 *k = pi->ki;
   1116 	VAR *v;
   1117 
   1118 	v = ve->var;
   1119 	doubleprintorsetwidth(v, getpmem(k), 1, mode);
   1120 }
   1121 
   1122 void
   1123 pagein(struct pinfo *pi, VARENT *ve, enum mode mode)
   1124 {
   1125 	struct kinfo_proc2 *k = pi->ki;
   1126 	VAR *v;
   1127 
   1128 	v = ve->var;
   1129 	intprintorsetwidth(v, k->p_uvalid ? k->p_uru_majflt : 0, mode);
   1130 }
   1131 
   1132 void
   1133 maxrss(struct pinfo *pi, VARENT *ve, enum mode mode)
   1134 {
   1135 	VAR *v;
   1136 
   1137 	v = ve->var;
   1138 	/* No need to check width! */
   1139 	if (mode == PRINTMODE)
   1140 		(void)printf("%*s", v->width, "-");
   1141 }
   1142 
   1143 void
   1144 tsize(struct pinfo *pi, VARENT *ve, enum mode mode)
   1145 {
   1146 	struct kinfo_proc2 *k = pi->ki;
   1147 	VAR *v;
   1148 
   1149 	v = ve->var;
   1150 	intprintorsetwidth(v, pgtok(k->p_vm_tsize), mode);
   1151 }
   1152 
   1153 static void
   1154 printsig(VAR *v, const sigset_t *s, enum mode mode)
   1155 {
   1156 #define	SIGSETSIZE	__arraycount(s->__bits)
   1157 	if ((v->flag & ALTPR) == 0) {
   1158 		char buf[SIGSETSIZE * 8 + 1];
   1159 		size_t i;
   1160 
   1161 		for (i = 0; i < SIGSETSIZE; i++)
   1162 			(void)snprintf(&buf[i * 8], 9, "%.8x",
   1163 			    s->__bits[(SIGSETSIZE - 1) - i]);
   1164 
   1165 		/* Skip leading zeroes */
   1166 		for (i = 0; buf[i] == '0'; i++)
   1167 			continue;
   1168 
   1169 		if (buf[i] == '\0')
   1170 			i--;
   1171 		strprintorsetwidth(v, buf + i, mode);
   1172 	} else {
   1173 		size_t maxlen = 1024, len = 0;
   1174 		char *buf = emalloc(maxlen);
   1175 		*buf = '\0';
   1176 		for (size_t i = 0; i < SIGSETSIZE; i++) {
   1177 			uint32_t m = s->__bits[i];
   1178 			for (uint32_t j = 0; j < 32; j++) {
   1179 				if ((m & (1 << j)) == 0)
   1180 					continue;
   1181 				const char *n = signalname(j + 1);
   1182 				size_t sn = strlen(n);
   1183 				if (len)
   1184 					sn++;
   1185 				if (len + sn >= maxlen) {
   1186 					maxlen += 1024;
   1187 					buf = erealloc(buf, maxlen);
   1188 				}
   1189 				snprintf(buf + len, sn + 1, "%s%s",
   1190 				    len == 0 ? "" : ",", n);
   1191 				len += sn;
   1192 			}
   1193 		}
   1194 		strprintorsetwidth(v, buf, mode);
   1195 		free(buf);
   1196 #undef SIGSETSIZE
   1197 	}
   1198 }
   1199 
   1200 static void
   1201 printflag(VAR *v, int flag, enum mode mode)
   1202 {
   1203 	char buf[1024];
   1204 	const char *fmt;
   1205 
   1206 	switch (v->type) {
   1207 	case PROCFLAG:
   1208 		fmt = __SYSCTL_PROC_FLAG_BITS;
   1209 		break;
   1210 	case KTRACEFLAG:
   1211 		fmt = __KTRACE_FLAG_BITS;
   1212 		break;
   1213 	case PROCACFLAG:
   1214 		fmt = __ACCT_FLAG_BITS;
   1215 		break;
   1216 	default:
   1217 		err(EXIT_FAILURE, "Bad type %d", v->type);
   1218 	}
   1219 
   1220 	snprintb(buf, sizeof(buf), fmt, (unsigned)flag);
   1221 	strprintorsetwidth(v, buf, mode);
   1222 }
   1223 
   1224 /*
   1225  * Generic output routines.  Print fields from various prototype
   1226  * structures.
   1227  */
   1228 static void
   1229 printval(void *bp, VAR *v, enum mode mode)
   1230 {
   1231 	static char ofmt[32] = "%";
   1232 	int width, vok, fmtlen;
   1233 	const char *fcp;
   1234 	char *cp;
   1235 	int64_t val;
   1236 	u_int64_t uval;
   1237 
   1238 	val = 0;	/* XXXGCC -Wuninitialized [hpcarm] */
   1239 	uval = 0;	/* XXXGCC -Wuninitialized [hpcarm] */
   1240 
   1241 	/*
   1242 	 * Note that the "INF127" check is nonsensical for types
   1243 	 * that are or can be signed.
   1244 	 */
   1245 #define	GET(type)		(*(type *)bp)
   1246 #define	CHK_INF127(n)		(((n) > 127) && (v->flag & INF127) ? 127 : (n))
   1247 
   1248 #define	VSIGN	1
   1249 #define	VUNSIGN	2
   1250 #define	VPTR	3
   1251 
   1252 	if (mode == WIDTHMODE) {
   1253 		vok = 0;
   1254 		switch (v->type) {
   1255 		case CHAR:
   1256 			val = GET(char);
   1257 			vok = VSIGN;
   1258 			break;
   1259 		case UCHAR:
   1260 			uval = CHK_INF127(GET(u_char));
   1261 			vok = VUNSIGN;
   1262 			break;
   1263 		case SHORT:
   1264 			val = GET(short);
   1265 			vok = VSIGN;
   1266 			break;
   1267 		case PROCACFLAG:
   1268 			if (v->flag & ALTPR)
   1269 				break;
   1270 			/*FALLTHROUGH*/
   1271 		case USHORT:
   1272 			uval = CHK_INF127(GET(u_short));
   1273 			vok = VUNSIGN;
   1274 			break;
   1275 		case INT32:
   1276 			val = GET(int32_t);
   1277 			vok = VSIGN;
   1278 			break;
   1279 		case KTRACEFLAG:
   1280 		case PROCFLAG:
   1281 			if (v->flag & ALTPR)
   1282 				break;
   1283 			/*FALLTHROUGH*/
   1284 		case INT:
   1285 			val = GET(int);
   1286 			vok = VSIGN;
   1287 			break;
   1288 		case UINT:
   1289 		case UINT32:
   1290 			uval = CHK_INF127(GET(u_int));
   1291 			vok = VUNSIGN;
   1292 			break;
   1293 		case LONG:
   1294 			val = GET(long);
   1295 			vok = VSIGN;
   1296 			break;
   1297 		case ULONG:
   1298 			uval = CHK_INF127(GET(u_long));
   1299 			vok = VUNSIGN;
   1300 			break;
   1301 		case KPTR:
   1302 			uval = GET(u_int64_t);
   1303 			vok = VPTR;
   1304 			break;
   1305 		case KPTR24:
   1306 			uval = GET(u_int64_t);
   1307 			uval &= 0xffffff;
   1308 			vok = VPTR;
   1309 			break;
   1310 		case INT64:
   1311 			val = GET(int64_t);
   1312 			vok = VSIGN;
   1313 			break;
   1314 		case UINT64:
   1315 			uval = CHK_INF127(GET(u_int64_t));
   1316 			vok = VUNSIGN;
   1317 			break;
   1318 
   1319 		case SIGLIST:
   1320 		default:
   1321 			/* nothing... */;
   1322 		}
   1323 		switch (vok) {
   1324 		case VSIGN:
   1325 			if (val < 0 && val < v->longestn) {
   1326 				v->longestn = val;
   1327 				fmtlen = iwidth(-val) + 1;
   1328 				if (fmtlen > v->width)
   1329 					v->width = fmtlen;
   1330 			} else if (val > 0 && val > v->longestp) {
   1331 				v->longestp = val;
   1332 				fmtlen = iwidth(val);
   1333 				if (fmtlen > v->width)
   1334 					v->width = fmtlen;
   1335 			}
   1336 			return;
   1337 		case VUNSIGN:
   1338 			if (uval > v->longestu) {
   1339 				v->longestu = uval;
   1340 				v->width = iwidth(uval);
   1341 			}
   1342 			return;
   1343 		case VPTR:
   1344 			fmtlen = 0;
   1345 			while (uval > 0) {
   1346 				uval >>= 4;
   1347 				fmtlen++;
   1348 			}
   1349 			if (fmtlen > v->width)
   1350 				v->width = fmtlen;
   1351 			return;
   1352 		}
   1353 	}
   1354 
   1355 	width = v->width;
   1356 	cp = ofmt + 1;
   1357 	fcp = v->fmt;
   1358 	if (v->flag & LJUST)
   1359 		*cp++ = '-';
   1360 	*cp++ = '*';
   1361 	while ((*cp++ = *fcp++) != '\0')
   1362 		continue;
   1363 
   1364 	switch (v->type) {
   1365 	case CHAR:
   1366 		(void)printf(ofmt, width, GET(char));
   1367 		return;
   1368 	case UCHAR:
   1369 		(void)printf(ofmt, width, CHK_INF127(GET(u_char)));
   1370 		return;
   1371 	case SHORT:
   1372 		(void)printf(ofmt, width, GET(short));
   1373 		return;
   1374 	case PROCACFLAG:
   1375 		if (v->flag & ALTPR) {
   1376 			printflag(v, CHK_INF127(GET(u_short)), mode);
   1377 			return;
   1378 		}
   1379 		/*FALLTHROUGH*/
   1380 	case USHORT:
   1381 		(void)printf(ofmt, width, CHK_INF127(GET(u_short)));
   1382 		return;
   1383 	case KTRACEFLAG:
   1384 	case PROCFLAG:
   1385 		if (v->flag & ALTPR) {
   1386 			printflag(v, GET(int), mode);
   1387 			return;
   1388 		}
   1389 		/*FALLTHROUGH*/
   1390 	case INT:
   1391 		(void)printf(ofmt, width, GET(int));
   1392 		return;
   1393 	case UINT:
   1394 		(void)printf(ofmt, width, CHK_INF127(GET(u_int)));
   1395 		return;
   1396 	case LONG:
   1397 		(void)printf(ofmt, width, GET(long));
   1398 		return;
   1399 	case ULONG:
   1400 		(void)printf(ofmt, width, CHK_INF127(GET(u_long)));
   1401 		return;
   1402 	case KPTR:
   1403 		(void)printf(ofmt, width, GET(u_int64_t));
   1404 		return;
   1405 	case KPTR24:
   1406 		(void)printf(ofmt, width, GET(u_int64_t) & 0xffffff);
   1407 		return;
   1408 	case INT32:
   1409 		(void)printf(ofmt, width, GET(int32_t));
   1410 		return;
   1411 	case UINT32:
   1412 		(void)printf(ofmt, width, CHK_INF127(GET(u_int32_t)));
   1413 		return;
   1414 	case INT64:
   1415 		(void)printf(ofmt, width, GET(int64_t));
   1416 		return;
   1417 	case UINT64:
   1418 		(void)printf(ofmt, width, CHK_INF127(GET(u_int64_t)));
   1419 		return;
   1420 	case SIGLIST:
   1421 		printsig(v, (const sigset_t *)(void *)bp, mode);
   1422 		return;
   1423 	default:
   1424 		errx(EXIT_FAILURE, "unknown type %d", v->type);
   1425 	}
   1426 #undef GET
   1427 #undef CHK_INF127
   1428 }
   1429 
   1430 void
   1431 pvar(struct pinfo *pi, VARENT *ve, enum mode mode)
   1432 {
   1433 	VAR *v = ve->var;
   1434 	char *b = (v->flag & LWP) ? (char *)pi->li : (char *)pi->ki;
   1435 
   1436 	if ((v->flag & UAREA) && !pi->ki->p_uvalid) {
   1437 		if (mode == PRINTMODE)
   1438 			(void)printf("%*s", v->width, "-");
   1439 		return;
   1440 	}
   1441 
   1442 	(void)printval(b + v->off, v, mode);
   1443 }
   1444 
   1445 void
   1446 putimeval(struct pinfo *pi, VARENT *ve, enum mode mode)
   1447 {
   1448 	VAR *v = ve->var;
   1449 	struct kinfo_proc2 *k = pi->ki;
   1450 	char *b = (v->flag & LWP) ? (char *)pi->li : (char *)pi->ki;
   1451 	ulong secs = *(uint32_t *)(b + v->off);
   1452 	ulong usec = *(uint32_t *)(b + v->off + sizeof (uint32_t));
   1453 	int fmtlen;
   1454 
   1455 	if (!k->p_uvalid) {
   1456 		if (mode == PRINTMODE)
   1457 			(void)printf("%*s", v->width, "-");
   1458 		return;
   1459 	}
   1460 
   1461 	if (mode == WIDTHMODE) {
   1462 		if (secs == 0)
   1463 			/* non-zero so fmtlen is calculated at least once */
   1464 			secs = 1;
   1465 		if (secs > v->longestu) {
   1466 			v->longestu = secs;
   1467 			if (secs <= 999)
   1468 				/* sss.ssssss */
   1469 				fmtlen = iwidth(secs) + 6 + 1;
   1470 			else
   1471 				/* hh:mm:ss.ss */
   1472 				fmtlen = iwidth((secs + 1) / SECSPERHOUR)
   1473 					+ 2 + 1 + 2 + 1 + 2 + 1;
   1474 			if (fmtlen > v->width)
   1475 				v->width = fmtlen;
   1476 		}
   1477 		return;
   1478 	}
   1479 
   1480 	if (secs < 999)
   1481 		(void)printf( "%*lu.%.6lu", v->width - 6 - 1, secs, usec);
   1482 	else {
   1483 		uint h, m;
   1484 		usec += 5000;
   1485 		if (usec >= 1000000) {
   1486 			usec -= 1000000;
   1487 			secs++;
   1488 		}
   1489 		m = secs / SECSPERMIN;
   1490 		secs -= m * SECSPERMIN;
   1491 		h = m / MINSPERHOUR;
   1492 		m -= h * MINSPERHOUR;
   1493 		(void)printf( "%*u:%.2u:%.2lu.%.2lu", v->width - 9, h, m, secs,
   1494 		    usec / 10000u );
   1495 	}
   1496 }
   1497 
   1498 void
   1499 lname(struct pinfo *pi, VARENT *ve, enum mode mode)
   1500 {
   1501 	struct kinfo_lwp *l = pi->li;
   1502 	VAR *v;
   1503 
   1504 	v = ve->var;
   1505 	if (l->l_name[0] != '\0') {
   1506 		strprintorsetwidth(v, l->l_name, mode);
   1507 		v->width = min(v->width, KI_LNAMELEN);
   1508 	} else {
   1509 		if (mode == PRINTMODE)
   1510 			(void)printf("%-*s", v->width, "-");
   1511 	}
   1512 }
   1513