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