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