]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - bin/ps/print.c
MFC r309676
[FreeBSD/stable/10.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  * 4. 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
65 #include "ps.h"
66
67 #define COMMAND_WIDTH   16
68 #define ARGUMENTS_WIDTH 16
69
70 #define ps_pgtok(a)     (((a) * getpagesize()) / 1024)
71
72 void
73 printheader(void)
74 {
75         VAR *v;
76         struct varent *vent;
77
78         STAILQ_FOREACH(vent, &varlist, next_ve)
79                 if (*vent->header != '\0')
80                         break;
81         if (!vent)
82                 return;
83
84         STAILQ_FOREACH(vent, &varlist, next_ve) {
85                 v = vent->var;
86                 if (v->flag & LJUST) {
87                         if (STAILQ_NEXT(vent, next_ve) == NULL) /* last one */
88                                 (void)printf("%s", vent->header);
89                         else
90                                 (void)printf("%-*s", v->width, vent->header);
91                 } else
92                         (void)printf("%*s", v->width, vent->header);
93                 if (STAILQ_NEXT(vent, next_ve) != NULL)
94                         (void)putchar(' ');
95         }
96         (void)putchar('\n');
97 }
98
99 char *
100 arguments(KINFO *k, VARENT *ve)
101 {
102         char *vis_args;
103
104         if ((vis_args = malloc(strlen(k->ki_args) * 4 + 1)) == NULL)
105                 errx(1, "malloc failed");
106         strvis(vis_args, k->ki_args, VIS_TAB | VIS_NL | VIS_NOSLASH);
107
108         if (STAILQ_NEXT(ve, next_ve) != NULL && strlen(vis_args) > ARGUMENTS_WIDTH)
109                 vis_args[ARGUMENTS_WIDTH] = '\0';
110
111         return (vis_args);
112 }
113
114 char *
115 command(KINFO *k, VARENT *ve)
116 {
117         char *vis_args, *vis_env, *str;
118
119         if (cflag) {
120                 /* If it is the last field, then don't pad */
121                 if (STAILQ_NEXT(ve, next_ve) == NULL) {
122                         asprintf(&str, "%s%s%s%s%s",
123                             k->ki_d.prefix ? k->ki_d.prefix : "",
124                             k->ki_p->ki_comm,
125                             (showthreads && k->ki_p->ki_numthreads > 1) ? "/" : "",
126                             (showthreads && k->ki_p->ki_numthreads > 1) ? k->ki_p->ki_tdname : "",
127                             (showthreads && k->ki_p->ki_numthreads > 1) ? k->ki_p->ki_moretdname : "");
128                 } else
129                         str = strdup(k->ki_p->ki_comm);
130
131                 return (str);
132         }
133         if ((vis_args = malloc(strlen(k->ki_args) * 4 + 1)) == NULL)
134                 errx(1, "malloc failed");
135         strvis(vis_args, k->ki_args, VIS_TAB | VIS_NL | VIS_NOSLASH);
136
137         if (STAILQ_NEXT(ve, next_ve) == NULL) {
138                 /* last field */
139
140                 if (k->ki_env) {
141                         if ((vis_env = malloc(strlen(k->ki_env) * 4 + 1))
142                             == NULL)
143                                 errx(1, "malloc failed");
144                         strvis(vis_env, k->ki_env,
145                             VIS_TAB | VIS_NL | VIS_NOSLASH);
146                 } else
147                         vis_env = NULL;
148
149                 asprintf(&str, "%s%s%s%s",
150                     k->ki_d.prefix ? k->ki_d.prefix : "",
151                     vis_env ? vis_env : "",
152                     vis_env ? " " : "",
153                     vis_args);
154
155                 if (vis_env != NULL)
156                         free(vis_env);
157                 free(vis_args);
158         } else {
159                 /* ki_d.prefix & ki_env aren't shown for interim fields */
160                 str = vis_args;
161
162                 if (strlen(str) > COMMAND_WIDTH)
163                         str[COMMAND_WIDTH] = '\0';
164         }
165
166         return (str);
167 }
168
169 char *
170 ucomm(KINFO *k, VARENT *ve)
171 {
172         char *str;
173
174         if (STAILQ_NEXT(ve, next_ve) == NULL) { /* last field, don't pad */
175                 asprintf(&str, "%s%s%s%s%s",
176                     k->ki_d.prefix ? k->ki_d.prefix : "",
177                     k->ki_p->ki_comm,
178                     (showthreads && k->ki_p->ki_numthreads > 1) ? "/" : "",
179                     (showthreads && k->ki_p->ki_numthreads > 1) ? k->ki_p->ki_tdname : "",
180                     (showthreads && k->ki_p->ki_numthreads > 1) ? k->ki_p->ki_moretdname : "");
181         } else {
182                 if (showthreads && k->ki_p->ki_numthreads > 1)
183                         asprintf(&str, "%s/%s%s", k->ki_p->ki_comm,
184                             k->ki_p->ki_tdname, k->ki_p->ki_moretdname);
185                 else
186                         str = strdup(k->ki_p->ki_comm);
187         }
188         return (str);
189 }
190
191 char *
192 tdnam(KINFO *k, VARENT *ve __unused)
193 {
194         char *str;
195
196         if (showthreads && k->ki_p->ki_numthreads > 1)
197                 asprintf(&str, "%s%s", k->ki_p->ki_tdname,
198                     k->ki_p->ki_moretdname);
199         else
200                 str = strdup("      ");
201
202         return (str);
203 }
204
205 char *
206 logname(KINFO *k, VARENT *ve __unused)
207 {
208
209         if (*k->ki_p->ki_login == '\0')
210                 return (NULL);
211         return (strdup(k->ki_p->ki_login));
212 }
213
214 char *
215 state(KINFO *k, VARENT *ve __unused)
216 {
217         int flag, tdflags;
218         char *cp, *buf;
219
220         buf = malloc(16);
221         if (buf == NULL)
222                 errx(1, "malloc failed");
223
224         flag = k->ki_p->ki_flag;
225         tdflags = k->ki_p->ki_tdflags;  /* XXXKSE */
226         cp = buf;
227
228         switch (k->ki_p->ki_stat) {
229
230         case SSTOP:
231                 *cp = 'T';
232                 break;
233
234         case SSLEEP:
235                 if (tdflags & TDF_SINTR)        /* interruptable (long) */
236                         *cp = k->ki_p->ki_slptime >= MAXSLP ? 'I' : 'S';
237                 else
238                         *cp = 'D';
239                 break;
240
241         case SRUN:
242         case SIDL:
243                 *cp = 'R';
244                 break;
245
246         case SWAIT:
247                 *cp = 'W';
248                 break;
249
250         case SLOCK:
251                 *cp = 'L';
252                 break;
253
254         case SZOMB:
255                 *cp = 'Z';
256                 break;
257
258         default:
259                 *cp = '?';
260         }
261         cp++;
262         if (!(flag & P_INMEM))
263                 *cp++ = 'W';
264         if (k->ki_p->ki_nice < NZERO)
265                 *cp++ = '<';
266         else if (k->ki_p->ki_nice > NZERO)
267                 *cp++ = 'N';
268         if (flag & P_TRACED)
269                 *cp++ = 'X';
270         if (flag & P_WEXIT && k->ki_p->ki_stat != SZOMB)
271                 *cp++ = 'E';
272         if (flag & P_PPWAIT)
273                 *cp++ = 'V';
274         if ((flag & P_SYSTEM) || k->ki_p->ki_lock > 0)
275                 *cp++ = 'L';
276         if (k->ki_p->ki_kiflag & KI_SLEADER)
277                 *cp++ = 's';
278         if ((flag & P_CONTROLT) && k->ki_p->ki_pgid == k->ki_p->ki_tpgid)
279                 *cp++ = '+';
280         if (flag & P_JAILED)
281                 *cp++ = 'J';
282         *cp = '\0';
283         return (buf);
284 }
285
286 #define scalepri(x)     ((x) - PZERO)
287
288 char *
289 pri(KINFO *k, VARENT *ve __unused)
290 {
291         char *str;
292
293         asprintf(&str, "%d", scalepri(k->ki_p->ki_pri.pri_level));
294         return (str);
295 }
296
297 char *
298 upr(KINFO *k, VARENT *ve __unused)
299 {
300         char *str;
301
302         asprintf(&str, "%d", scalepri(k->ki_p->ki_pri.pri_user));
303         return (str);
304 }
305 #undef scalepri
306
307 char *
308 uname(KINFO *k, VARENT *ve __unused)
309 {
310
311         return (strdup(user_from_uid(k->ki_p->ki_uid, 0)));
312 }
313
314 char *
315 egroupname(KINFO *k, VARENT *ve __unused)
316 {
317
318         return (strdup(group_from_gid(k->ki_p->ki_groups[0], 0)));
319 }
320
321 char *
322 rgroupname(KINFO *k, VARENT *ve __unused)
323 {
324
325         return (strdup(group_from_gid(k->ki_p->ki_rgid, 0)));
326 }
327
328 char *
329 runame(KINFO *k, VARENT *ve __unused)
330 {
331
332         return (strdup(user_from_uid(k->ki_p->ki_ruid, 0)));
333 }
334
335 char *
336 tdev(KINFO *k, VARENT *ve __unused)
337 {
338         dev_t dev;
339         char *str;
340
341         dev = k->ki_p->ki_tdev;
342         if (dev == NODEV)
343                 str = strdup("-");
344         else
345                 asprintf(&str, "%#jx", (uintmax_t)dev);
346
347         return (str);
348 }
349
350 char *
351 tname(KINFO *k, VARENT *ve __unused)
352 {
353         dev_t dev;
354         char *ttname, *str;
355
356         dev = k->ki_p->ki_tdev;
357         if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
358                 str = strdup("- ");
359         else {
360                 if (strncmp(ttname, "tty", 3) == 0 ||
361                     strncmp(ttname, "cua", 3) == 0)
362                         ttname += 3;
363                 if (strncmp(ttname, "pts/", 4) == 0)
364                         ttname += 4;
365                 asprintf(&str, "%s%c", ttname,
366                     k->ki_p->ki_kiflag & KI_CTTY ? ' ' : '-');
367         }
368
369         return (str);
370 }
371
372 char *
373 longtname(KINFO *k, VARENT *ve __unused)
374 {
375         dev_t dev;
376         const char *ttname;
377
378         dev = k->ki_p->ki_tdev;
379         if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
380                 ttname = "-";
381
382         return (strdup(ttname));
383 }
384
385 char *
386 started(KINFO *k, VARENT *ve __unused)
387 {
388         time_t then;
389         struct tm *tp;
390         static int use_ampm = -1;
391         size_t buflen = 100;
392         char *buf;
393
394         if (!k->ki_valid)
395                 return (NULL);
396
397         buf = malloc(buflen);
398         if (buf == NULL)
399                 errx(1, "malloc failed");
400
401         if (use_ampm < 0)
402                 use_ampm = (*nl_langinfo(T_FMT_AMPM) != '\0');
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,
407                     use_ampm ? "%l:%M%p" : "%k:%M  ", tp);
408         } else if (now - k->ki_p->ki_start.tv_sec < 7 * 86400) {
409                 (void)strftime(buf, buflen,
410                     use_ampm ? "%a%I%p" : "%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                 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                 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                 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 }