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