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