1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1990, 1993, 1994
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#if 0
33#ifndef lint
34static char sccsid[] = "@(#)print.c	8.6 (Berkeley) 4/16/94";
35#endif /* not lint */
36#endif
37
38#include <sys/cdefs.h>
39__FBSDID("$FreeBSD$");
40
41#include <sys/param.h>
42#include <sys/time.h>
43#include <sys/resource.h>
44#include <sys/proc.h>
45#include <sys/stat.h>
46
47#include <sys/mac.h>
48#include <sys/user.h>
49#include <sys/sysctl.h>
50#include <sys/vmmeter.h>
51
52#include <err.h>
53#include <grp.h>
54#include <jail.h>
55#include <langinfo.h>
56#include <locale.h>
57#include <math.h>
58#include <nlist.h>
59#include <pwd.h>
60#include <stddef.h>
61#include <stdint.h>
62#include <stdio.h>
63#include <stdlib.h>
64#include <string.h>
65#include <unistd.h>
66#include <vis.h>
67#include <libxo/xo.h>
68
69#include "ps.h"
70
71#define	COMMAND_WIDTH	16
72#define	ARGUMENTS_WIDTH	16
73
74#define	ps_pgtok(a)	(((a) * getpagesize()) / 1024)
75
76void
77printheader(void)
78{
79	VAR *v;
80	struct varent *vent;
81
82	STAILQ_FOREACH(vent, &varlist, next_ve)
83		if (*vent->header != '\0')
84			break;
85	if (!vent)
86		return;
87
88	STAILQ_FOREACH(vent, &varlist, next_ve) {
89		v = vent->var;
90		if (v->flag & LJUST) {
91			if (STAILQ_NEXT(vent, next_ve) == NULL)	/* last one */
92				xo_emit("{T:/%s}", vent->header);
93			else
94				xo_emit("{T:/%-*s}", v->width, vent->header);
95		} else
96			xo_emit("{T:/%*s}", v->width, vent->header);
97		if (STAILQ_NEXT(vent, next_ve) != NULL)
98			xo_emit("{P: }");
99	}
100	xo_emit("\n");
101}
102
103char *
104arguments(KINFO *k, VARENT *ve)
105{
106	char *vis_args;
107
108	if ((vis_args = malloc(strlen(k->ki_args) * 4 + 1)) == NULL)
109		xo_errx(1, "malloc failed");
110	strvis(vis_args, k->ki_args, VIS_TAB | VIS_NL | VIS_NOSLASH);
111
112	if (STAILQ_NEXT(ve, next_ve) != NULL && strlen(vis_args) > ARGUMENTS_WIDTH)
113		vis_args[ARGUMENTS_WIDTH] = '\0';
114
115	return (vis_args);
116}
117
118char *
119command(KINFO *k, VARENT *ve)
120{
121	char *vis_args, *vis_env, *str;
122
123	if (cflag) {
124		/* If it is the last field, then don't pad */
125		if (STAILQ_NEXT(ve, next_ve) == NULL) {
126			asprintf(&str, "%s%s%s%s%s",
127			    k->ki_d.prefix ? k->ki_d.prefix : "",
128			    k->ki_p->ki_comm,
129			    (showthreads && k->ki_p->ki_numthreads > 1) ? "/" : "",
130			    (showthreads && k->ki_p->ki_numthreads > 1) ? k->ki_p->ki_tdname : "",
131			    (showthreads && k->ki_p->ki_numthreads > 1) ? k->ki_p->ki_moretdname : "");
132		} else
133			str = strdup(k->ki_p->ki_comm);
134
135		return (str);
136	}
137	if ((vis_args = malloc(strlen(k->ki_args) * 4 + 1)) == NULL)
138		xo_errx(1, "malloc failed");
139	strvis(vis_args, k->ki_args, VIS_TAB | VIS_NL | VIS_NOSLASH);
140
141	if (STAILQ_NEXT(ve, next_ve) == NULL) {
142		/* last field */
143
144		if (k->ki_env) {
145			if ((vis_env = malloc(strlen(k->ki_env) * 4 + 1))
146			    == NULL)
147				xo_errx(1, "malloc failed");
148			strvis(vis_env, k->ki_env,
149			    VIS_TAB | VIS_NL | VIS_NOSLASH);
150		} else
151			vis_env = NULL;
152
153		asprintf(&str, "%s%s%s%s",
154		    k->ki_d.prefix ? k->ki_d.prefix : "",
155		    vis_env ? vis_env : "",
156		    vis_env ? " " : "",
157		    vis_args);
158
159		if (vis_env != NULL)
160			free(vis_env);
161		free(vis_args);
162	} else {
163		/* ki_d.prefix & ki_env aren't shown for interim fields */
164		str = vis_args;
165
166		if (strlen(str) > COMMAND_WIDTH)
167			str[COMMAND_WIDTH] = '\0';
168	}
169
170	return (str);
171}
172
173char *
174ucomm(KINFO *k, VARENT *ve)
175{
176	char *str;
177
178	if (STAILQ_NEXT(ve, next_ve) == NULL) {	/* last field, don't pad */
179		asprintf(&str, "%s%s%s%s%s",
180		    k->ki_d.prefix ? k->ki_d.prefix : "",
181		    k->ki_p->ki_comm,
182		    (showthreads && k->ki_p->ki_numthreads > 1) ? "/" : "",
183		    (showthreads && k->ki_p->ki_numthreads > 1) ? k->ki_p->ki_tdname : "",
184		    (showthreads && k->ki_p->ki_numthreads > 1) ? k->ki_p->ki_moretdname : "");
185	} else {
186		if (showthreads && k->ki_p->ki_numthreads > 1)
187			asprintf(&str, "%s/%s%s", k->ki_p->ki_comm,
188			    k->ki_p->ki_tdname, k->ki_p->ki_moretdname);
189		else
190			str = strdup(k->ki_p->ki_comm);
191	}
192	return (str);
193}
194
195char *
196tdnam(KINFO *k, VARENT *ve __unused)
197{
198	char *str;
199
200	if (showthreads && k->ki_p->ki_numthreads > 1)
201		asprintf(&str, "%s%s", k->ki_p->ki_tdname,
202		    k->ki_p->ki_moretdname);
203	else
204		str = strdup("      ");
205
206	return (str);
207}
208
209char *
210logname(KINFO *k, VARENT *ve __unused)
211{
212
213	if (*k->ki_p->ki_login == '\0')
214		return (NULL);
215	return (strdup(k->ki_p->ki_login));
216}
217
218char *
219state(KINFO *k, VARENT *ve __unused)
220{
221	long flag, tdflags;
222	char *cp, *buf;
223
224	buf = malloc(16);
225	if (buf == NULL)
226		xo_errx(1, "malloc failed");
227
228	flag = k->ki_p->ki_flag;
229	tdflags = k->ki_p->ki_tdflags;	/* XXXKSE */
230	cp = buf;
231
232	switch (k->ki_p->ki_stat) {
233
234	case SSTOP:
235		*cp = 'T';
236		break;
237
238	case SSLEEP:
239		if (tdflags & TDF_SINTR)	/* interruptable (long) */
240			*cp = k->ki_p->ki_slptime >= MAXSLP ? 'I' : 'S';
241		else
242			*cp = 'D';
243		break;
244
245	case SRUN:
246	case SIDL:
247		*cp = 'R';
248		break;
249
250	case SWAIT:
251		*cp = 'W';
252		break;
253
254	case SLOCK:
255		*cp = 'L';
256		break;
257
258	case SZOMB:
259		*cp = 'Z';
260		break;
261
262	default:
263		*cp = '?';
264	}
265	cp++;
266	if (!(flag & P_INMEM))
267		*cp++ = 'W';
268	if (k->ki_p->ki_nice < NZERO || k->ki_p->ki_pri.pri_class == PRI_REALTIME)
269		*cp++ = '<';
270	else if (k->ki_p->ki_nice > NZERO || k->ki_p->ki_pri.pri_class == PRI_IDLE)
271		*cp++ = 'N';
272	if (flag & P_TRACED)
273		*cp++ = 'X';
274	if (flag & P_WEXIT && k->ki_p->ki_stat != SZOMB)
275		*cp++ = 'E';
276	if (flag & P_PPWAIT)
277		*cp++ = 'V';
278	if ((flag & P_SYSTEM) || k->ki_p->ki_lock > 0)
279		*cp++ = 'L';
280	if ((k->ki_p->ki_cr_flags & CRED_FLAG_CAPMODE) != 0)
281		*cp++ = 'C';
282	if (k->ki_p->ki_kiflag & KI_SLEADER)
283		*cp++ = 's';
284	if ((flag & P_CONTROLT) && k->ki_p->ki_pgid == k->ki_p->ki_tpgid)
285		*cp++ = '+';
286	if (flag & P_JAILED)
287		*cp++ = 'J';
288	*cp = '\0';
289	return (buf);
290}
291
292#define	scalepri(x)	((x) - PZERO)
293
294char *
295pri(KINFO *k, VARENT *ve __unused)
296{
297	char *str;
298
299	asprintf(&str, "%d", scalepri(k->ki_p->ki_pri.pri_level));
300	return (str);
301}
302
303char *
304upr(KINFO *k, VARENT *ve __unused)
305{
306	char *str;
307
308	asprintf(&str, "%d", scalepri(k->ki_p->ki_pri.pri_user));
309	return (str);
310}
311#undef scalepri
312
313char *
314uname(KINFO *k, VARENT *ve __unused)
315{
316
317	return (strdup(user_from_uid(k->ki_p->ki_uid, 0)));
318}
319
320char *
321egroupname(KINFO *k, VARENT *ve __unused)
322{
323
324	return (strdup(group_from_gid(k->ki_p->ki_groups[0], 0)));
325}
326
327char *
328rgroupname(KINFO *k, VARENT *ve __unused)
329{
330
331	return (strdup(group_from_gid(k->ki_p->ki_rgid, 0)));
332}
333
334char *
335runame(KINFO *k, VARENT *ve __unused)
336{
337
338	return (strdup(user_from_uid(k->ki_p->ki_ruid, 0)));
339}
340
341char *
342tdev(KINFO *k, VARENT *ve __unused)
343{
344	dev_t dev;
345	char *str;
346
347	dev = k->ki_p->ki_tdev;
348	if (dev == NODEV)
349		str = strdup("-");
350	else
351		asprintf(&str, "%#jx", (uintmax_t)dev);
352
353	return (str);
354}
355
356char *
357tname(KINFO *k, VARENT *ve __unused)
358{
359	dev_t dev;
360	char *ttname, *str;
361
362	dev = k->ki_p->ki_tdev;
363	if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
364		str = strdup("- ");
365	else {
366		if (strncmp(ttname, "tty", 3) == 0 ||
367		    strncmp(ttname, "cua", 3) == 0)
368			ttname += 3;
369		if (strncmp(ttname, "pts/", 4) == 0)
370			ttname += 4;
371		asprintf(&str, "%s%c", ttname,
372		    k->ki_p->ki_kiflag & KI_CTTY ? ' ' : '-');
373	}
374
375	return (str);
376}
377
378char *
379longtname(KINFO *k, VARENT *ve __unused)
380{
381	dev_t dev;
382	const char *ttname;
383
384	dev = k->ki_p->ki_tdev;
385	if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
386		ttname = "-";
387
388	return (strdup(ttname));
389}
390
391char *
392started(KINFO *k, VARENT *ve __unused)
393{
394	time_t then;
395	struct tm *tp;
396	size_t buflen = 100;
397	char *buf;
398
399	if (!k->ki_valid)
400		return (NULL);
401
402	buf = malloc(buflen);
403	if (buf == NULL)
404		xo_errx(1, "malloc failed");
405
406	then = k->ki_p->ki_start.tv_sec;
407	tp = localtime(&then);
408	if (now - k->ki_p->ki_start.tv_sec < 24 * 3600) {
409		(void)strftime(buf, buflen, "%H:%M  ", tp);
410	} else if (now - k->ki_p->ki_start.tv_sec < 7 * 86400) {
411		(void)strftime(buf, buflen, "%a%H  ", tp);
412	} else
413		(void)strftime(buf, buflen, "%e%b%y", tp);
414	return (buf);
415}
416
417char *
418lstarted(KINFO *k, VARENT *ve __unused)
419{
420	time_t then;
421	char *buf;
422	size_t buflen = 100;
423
424	if (!k->ki_valid)
425		return (NULL);
426
427	buf = malloc(buflen);
428	if (buf == NULL)
429		xo_errx(1, "malloc failed");
430
431	then = k->ki_p->ki_start.tv_sec;
432	(void)strftime(buf, buflen, "%c", localtime(&then));
433	return (buf);
434}
435
436char *
437lockname(KINFO *k, VARENT *ve __unused)
438{
439	char *str;
440
441	if (k->ki_p->ki_kiflag & KI_LOCKBLOCK) {
442		if (k->ki_p->ki_lockname[0] != 0)
443			str = strdup(k->ki_p->ki_lockname);
444		else
445			str = strdup("???");
446	} else
447		str = NULL;
448
449	return (str);
450}
451
452char *
453wchan(KINFO *k, VARENT *ve __unused)
454{
455	char *str;
456
457	if (k->ki_p->ki_wchan) {
458		if (k->ki_p->ki_wmesg[0] != 0)
459			str = strdup(k->ki_p->ki_wmesg);
460		else
461			asprintf(&str, "%lx", (long)k->ki_p->ki_wchan);
462	} else
463		str = NULL;
464
465	return (str);
466}
467
468char *
469nwchan(KINFO *k, VARENT *ve __unused)
470{
471	char *str;
472
473	if (k->ki_p->ki_wchan)
474		asprintf(&str, "%0lx", (long)k->ki_p->ki_wchan);
475	else
476		str = NULL;
477
478	return (str);
479}
480
481char *
482mwchan(KINFO *k, VARENT *ve __unused)
483{
484	char *str;
485
486	if (k->ki_p->ki_wchan) {
487		if (k->ki_p->ki_wmesg[0] != 0)
488			str = strdup(k->ki_p->ki_wmesg);
489		else
490                        asprintf(&str, "%lx", (long)k->ki_p->ki_wchan);
491	} else if (k->ki_p->ki_kiflag & KI_LOCKBLOCK) {
492		if (k->ki_p->ki_lockname[0]) {
493			str = strdup(k->ki_p->ki_lockname);
494		} else
495			str = strdup("???");
496	} else
497		str = NULL;
498
499	return (str);
500}
501
502char *
503vsize(KINFO *k, VARENT *ve __unused)
504{
505	char *str;
506
507	asprintf(&str, "%lu", (u_long)(k->ki_p->ki_size / 1024));
508	return (str);
509}
510
511static char *
512printtime(KINFO *k, VARENT *ve __unused, long secs, long psecs)
513/* psecs is "parts" of a second. first micro, then centi */
514{
515	static char decimal_point;
516	char *str;
517
518	if (decimal_point == '\0')
519		decimal_point = localeconv()->decimal_point[0];
520	if (!k->ki_valid) {
521		secs = 0;
522		psecs = 0;
523	} else {
524		/* round and scale to 100's */
525		psecs = (psecs + 5000) / 10000;
526		secs += psecs / 100;
527		psecs = psecs % 100;
528	}
529	asprintf(&str, "%ld:%02ld%c%02ld",
530	    secs / 60, secs % 60, decimal_point, psecs);
531	return (str);
532}
533
534char *
535cputime(KINFO *k, VARENT *ve)
536{
537	long secs, psecs;
538
539	/*
540	 * This counts time spent handling interrupts.  We could
541	 * fix this, but it is not 100% trivial (and interrupt
542	 * time fractions only work on the sparc anyway).	XXX
543	 */
544	secs = k->ki_p->ki_runtime / 1000000;
545	psecs = k->ki_p->ki_runtime % 1000000;
546	if (sumrusage) {
547		secs += k->ki_p->ki_childtime.tv_sec;
548		psecs += k->ki_p->ki_childtime.tv_usec;
549	}
550	return (printtime(k, ve, secs, psecs));
551}
552
553char *
554cpunum(KINFO *k, VARENT *ve __unused)
555{
556	char *cpu;
557
558	if (k->ki_p->ki_stat == SRUN && k->ki_p->ki_oncpu != NOCPU) {
559		asprintf(&cpu, "%d", k->ki_p->ki_oncpu);
560	} else {
561		asprintf(&cpu, "%d", k->ki_p->ki_lastcpu);
562	}
563	return (cpu);
564}
565
566char *
567systime(KINFO *k, VARENT *ve)
568{
569	long secs, psecs;
570
571	secs = k->ki_p->ki_rusage.ru_stime.tv_sec;
572	psecs = k->ki_p->ki_rusage.ru_stime.tv_usec;
573	if (sumrusage) {
574		secs += k->ki_p->ki_childstime.tv_sec;
575		psecs += k->ki_p->ki_childstime.tv_usec;
576	}
577	return (printtime(k, ve, secs, psecs));
578}
579
580char *
581usertime(KINFO *k, VARENT *ve)
582{
583	long secs, psecs;
584
585	secs = k->ki_p->ki_rusage.ru_utime.tv_sec;
586	psecs = k->ki_p->ki_rusage.ru_utime.tv_usec;
587	if (sumrusage) {
588		secs += k->ki_p->ki_childutime.tv_sec;
589		psecs += k->ki_p->ki_childutime.tv_usec;
590	}
591	return (printtime(k, ve, secs, psecs));
592}
593
594char *
595elapsed(KINFO *k, VARENT *ve __unused)
596{
597	time_t val;
598	int days, hours, mins, secs;
599	char *str;
600
601	if (!k->ki_valid)
602		return (NULL);
603	val = now - k->ki_p->ki_start.tv_sec;
604	days = val / (24 * 60 * 60);
605	val %= 24 * 60 * 60;
606	hours = val / (60 * 60);
607	val %= 60 * 60;
608	mins = val / 60;
609	secs = val % 60;
610	if (days != 0)
611		asprintf(&str, "%3d-%02d:%02d:%02d", days, hours, mins, secs);
612	else if (hours != 0)
613		asprintf(&str, "%02d:%02d:%02d", hours, mins, secs);
614	else
615		asprintf(&str, "%02d:%02d", mins, secs);
616
617	return (str);
618}
619
620char *
621elapseds(KINFO *k, VARENT *ve __unused)
622{
623	time_t val;
624	char *str;
625
626	if (!k->ki_valid)
627		return (NULL);
628	val = now - k->ki_p->ki_start.tv_sec;
629	asprintf(&str, "%jd", (intmax_t)val);
630	return (str);
631}
632
633double
634getpcpu(const KINFO *k)
635{
636	static int failure;
637
638	if (!nlistread)
639		failure = donlist();
640	if (failure)
641		return (0.0);
642
643#define	fxtofl(fixpt)	((double)(fixpt) / fscale)
644
645	/* XXX - I don't like this */
646	if (k->ki_p->ki_swtime == 0 || (k->ki_p->ki_flag & P_INMEM) == 0)
647		return (0.0);
648	if (rawcpu)
649		return (100.0 * fxtofl(k->ki_p->ki_pctcpu));
650	return (100.0 * fxtofl(k->ki_p->ki_pctcpu) /
651		(1.0 - exp(k->ki_p->ki_swtime * log(fxtofl(ccpu)))));
652}
653
654char *
655pcpu(KINFO *k, VARENT *ve __unused)
656{
657	char *str;
658
659	asprintf(&str, "%.1f", getpcpu(k));
660	return (str);
661}
662
663static double
664getpmem(KINFO *k)
665{
666	static int failure;
667	double fracmem;
668
669	if (!nlistread)
670		failure = donlist();
671	if (failure)
672		return (0.0);
673
674	if ((k->ki_p->ki_flag & P_INMEM) == 0)
675		return (0.0);
676	/* XXX want pmap ptpages, segtab, etc. (per architecture) */
677	/* XXX don't have info about shared */
678	fracmem = ((double)k->ki_p->ki_rssize) / mempages;
679	return (100.0 * fracmem);
680}
681
682char *
683pmem(KINFO *k, VARENT *ve __unused)
684{
685	char *str;
686
687	asprintf(&str, "%.1f", getpmem(k));
688	return (str);
689}
690
691char *
692pagein(KINFO *k, VARENT *ve __unused)
693{
694	char *str;
695
696	asprintf(&str, "%ld", k->ki_valid ? k->ki_p->ki_rusage.ru_majflt : 0);
697	return (str);
698}
699
700/* ARGSUSED */
701char *
702maxrss(KINFO *k __unused, VARENT *ve __unused)
703{
704
705	/* XXX not yet */
706	return (NULL);
707}
708
709char *
710priorityr(KINFO *k, VARENT *ve __unused)
711{
712	struct priority *lpri;
713	char *str;
714	unsigned class, level;
715
716	lpri = &k->ki_p->ki_pri;
717	class = lpri->pri_class;
718	level = lpri->pri_level;
719	switch (class) {
720	case RTP_PRIO_REALTIME:
721	/* alias for PRI_REALTIME */
722		asprintf(&str, "real:%u", level - PRI_MIN_REALTIME);
723		break;
724	case RTP_PRIO_NORMAL:
725	/* alias for PRI_TIMESHARE */
726		if (level >= PRI_MIN_TIMESHARE)
727			asprintf(&str, "normal:%u", level - PRI_MIN_TIMESHARE);
728		else
729			asprintf(&str, "kernel:%u", level - PRI_MIN_KERN);
730		break;
731	case RTP_PRIO_IDLE:
732	/* alias for PRI_IDLE */
733		asprintf(&str, "idle:%u", level - PRI_MIN_IDLE);
734		break;
735	case RTP_PRIO_ITHD:
736	/* alias for PRI_ITHD */
737		asprintf(&str, "intr:%u", level - PRI_MIN_ITHD);
738		break;
739	default:
740		asprintf(&str, "%u:%u", class, level);
741		break;
742	}
743	return (str);
744}
745
746/*
747 * Generic output routines.  Print fields from various prototype
748 * structures.
749 */
750static char *
751printval(void *bp, VAR *v)
752{
753	static char ofmt[32] = "%";
754	const char *fcp;
755	char *cp, *str;
756
757	cp = ofmt + 1;
758	fcp = v->fmt;
759	while ((*cp++ = *fcp++));
760
761#define	CHKINF127(n)	(((n) > 127) && (v->flag & INF127) ? 127 : (n))
762
763	switch (v->type) {
764	case CHAR:
765		(void)asprintf(&str, ofmt, *(char *)bp);
766		break;
767	case UCHAR:
768		(void)asprintf(&str, ofmt, *(u_char *)bp);
769		break;
770	case SHORT:
771		(void)asprintf(&str, ofmt, *(short *)bp);
772		break;
773	case USHORT:
774		(void)asprintf(&str, ofmt, *(u_short *)bp);
775		break;
776	case INT:
777		(void)asprintf(&str, ofmt, *(int *)bp);
778		break;
779	case UINT:
780		(void)asprintf(&str, ofmt, CHKINF127(*(u_int *)bp));
781		break;
782	case LONG:
783		(void)asprintf(&str, ofmt, *(long *)bp);
784		break;
785	case ULONG:
786		(void)asprintf(&str, ofmt, *(u_long *)bp);
787		break;
788	case KPTR:
789		(void)asprintf(&str, ofmt, *(u_long *)bp);
790		break;
791	case PGTOK:
792		(void)asprintf(&str, ofmt, ps_pgtok(*(u_long *)bp));
793		break;
794	}
795
796	return (str);
797}
798
799char *
800kvar(KINFO *k, VARENT *ve)
801{
802	VAR *v;
803
804	v = ve->var;
805	return (printval((char *)((char *)k->ki_p + v->off), v));
806}
807
808char *
809rvar(KINFO *k, VARENT *ve)
810{
811	VAR *v;
812
813	v = ve->var;
814	if (!k->ki_valid)
815		return (NULL);
816	return (printval((char *)((char *)(&k->ki_p->ki_rusage) + v->off), v));
817}
818
819char *
820emulname(KINFO *k, VARENT *ve __unused)
821{
822
823	return (strdup(k->ki_p->ki_emul));
824}
825
826char *
827label(KINFO *k, VARENT *ve __unused)
828{
829	char *string;
830	mac_t proclabel;
831	int error;
832
833	string = NULL;
834	if (mac_prepare_process_label(&proclabel) == -1) {
835		xo_warn("mac_prepare_process_label");
836		goto out;
837	}
838	error = mac_get_pid(k->ki_p->ki_pid, proclabel);
839	if (error == 0) {
840		if (mac_to_text(proclabel, &string) == -1)
841			string = NULL;
842	}
843	mac_free(proclabel);
844out:
845	return (string);
846}
847
848char *
849loginclass(KINFO *k, VARENT *ve __unused)
850{
851
852	/*
853	 * Don't display login class for system processes;
854	 * login classes are used for resource limits,
855	 * and limits don't apply to system processes.
856	 */
857	if (k->ki_p->ki_flag & P_SYSTEM) {
858		return (strdup("-"));
859	}
860	return (strdup(k->ki_p->ki_loginclass));
861}
862
863char *
864jailname(KINFO *k, VARENT *ve __unused)
865{
866	char *name;
867
868	if (k->ki_p->ki_jid == 0)
869		return (strdup("-"));
870	name = jail_getname(k->ki_p->ki_jid);
871	if (name == NULL)
872		return (strdup("-"));
873	return (name);
874}
875