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 #include <sys/param.h>
33 #include <sys/time.h>
34 #include <sys/resource.h>
35 #include <sys/proc.h>
36 #include <sys/stat.h>
37
38 #include <sys/mac.h>
39 #include <sys/user.h>
40 #include <sys/sysctl.h>
41 #include <sys/vmmeter.h>
42
43 #include <err.h>
44 #include <grp.h>
45 #include <jail.h>
46 #include <langinfo.h>
47 #include <locale.h>
48 #include <math.h>
49 #include <nlist.h>
50 #include <pwd.h>
51 #include <stddef.h>
52 #include <stdint.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <unistd.h>
57 #include <vis.h>
58 #include <libxo/xo.h>
59
60 #include "ps.h"
61
62 #define COMMAND_WIDTH 16
63 #define ARGUMENTS_WIDTH 16
64
65 #define ps_pgtok(a) (((a) * getpagesize()) / 1024)
66
67 void
printheader(void)68 printheader(void)
69 {
70 VAR *v;
71 struct varent *vent;
72
73 STAILQ_FOREACH(vent, &varlist, next_ve)
74 if (*vent->header != '\0')
75 break;
76 if (!vent)
77 return;
78
79 STAILQ_FOREACH(vent, &varlist, next_ve) {
80 v = vent->var;
81 if (v->flag & LJUST) {
82 if (STAILQ_NEXT(vent, next_ve) == NULL) /* last one */
83 xo_emit("{T:/%hs}", vent->header);
84 else
85 xo_emit("{T:/%-*hs}", v->width, vent->header);
86 } else
87 xo_emit("{T:/%*hs}", v->width, vent->header);
88 if (STAILQ_NEXT(vent, next_ve) != NULL)
89 xo_emit("{P: }");
90 }
91 xo_emit("\n");
92 }
93
94 char *
arguments(KINFO * k,VARENT * ve)95 arguments(KINFO *k, VARENT *ve)
96 {
97 char *vis_args;
98
99 if ((vis_args = malloc(strlen(k->ki_args) * 4 + 1)) == NULL)
100 xo_errx(1, "malloc failed");
101 strvis(vis_args, k->ki_args, VIS_TAB | VIS_NL | VIS_NOSLASH);
102
103 if (STAILQ_NEXT(ve, next_ve) != NULL && strlen(vis_args) > ARGUMENTS_WIDTH)
104 vis_args[ARGUMENTS_WIDTH] = '\0';
105
106 return (vis_args);
107 }
108
109 char *
command(KINFO * k,VARENT * ve)110 command(KINFO *k, VARENT *ve)
111 {
112 char *vis_args, *vis_env, *str;
113
114 if (cflag) {
115 /* If it is the last field, then don't pad */
116 if (STAILQ_NEXT(ve, next_ve) == NULL) {
117 asprintf(&str, "%s%s%s%s%s",
118 k->ki_d.prefix ? k->ki_d.prefix : "",
119 k->ki_p->ki_comm,
120 (showthreads && k->ki_p->ki_numthreads > 1) ? "/" : "",
121 (showthreads && k->ki_p->ki_numthreads > 1) ? k->ki_p->ki_tdname : "",
122 (showthreads && k->ki_p->ki_numthreads > 1) ? k->ki_p->ki_moretdname : "");
123 } else
124 str = strdup(k->ki_p->ki_comm);
125
126 return (str);
127 }
128 if ((vis_args = malloc(strlen(k->ki_args) * 4 + 1)) == NULL)
129 xo_errx(1, "malloc failed");
130 strvis(vis_args, k->ki_args, VIS_TAB | VIS_NL | VIS_NOSLASH);
131
132 if (STAILQ_NEXT(ve, next_ve) == NULL) {
133 /* last field */
134
135 if (k->ki_env) {
136 if ((vis_env = malloc(strlen(k->ki_env) * 4 + 1))
137 == NULL)
138 xo_errx(1, "malloc failed");
139 strvis(vis_env, k->ki_env,
140 VIS_TAB | VIS_NL | VIS_NOSLASH);
141 } else
142 vis_env = NULL;
143
144 asprintf(&str, "%s%s%s%s",
145 k->ki_d.prefix ? k->ki_d.prefix : "",
146 vis_env ? vis_env : "",
147 vis_env ? " " : "",
148 vis_args);
149
150 if (vis_env != NULL)
151 free(vis_env);
152 free(vis_args);
153 } else {
154 /* ki_d.prefix & ki_env aren't shown for interim fields */
155 str = vis_args;
156
157 if (strlen(str) > COMMAND_WIDTH)
158 str[COMMAND_WIDTH] = '\0';
159 }
160
161 return (str);
162 }
163
164 char *
ucomm(KINFO * k,VARENT * ve)165 ucomm(KINFO *k, VARENT *ve)
166 {
167 char *str;
168
169 if (STAILQ_NEXT(ve, next_ve) == NULL) { /* last field, don't pad */
170 asprintf(&str, "%s%s%s%s%s",
171 k->ki_d.prefix ? k->ki_d.prefix : "",
172 k->ki_p->ki_comm,
173 (showthreads && k->ki_p->ki_numthreads > 1) ? "/" : "",
174 (showthreads && k->ki_p->ki_numthreads > 1) ? k->ki_p->ki_tdname : "",
175 (showthreads && k->ki_p->ki_numthreads > 1) ? k->ki_p->ki_moretdname : "");
176 } else {
177 if (showthreads && k->ki_p->ki_numthreads > 1)
178 asprintf(&str, "%s/%s%s", k->ki_p->ki_comm,
179 k->ki_p->ki_tdname, k->ki_p->ki_moretdname);
180 else
181 str = strdup(k->ki_p->ki_comm);
182 }
183 return (str);
184 }
185
186 char *
tdnam(KINFO * k,VARENT * ve __unused)187 tdnam(KINFO *k, VARENT *ve __unused)
188 {
189 char *str;
190
191 if (showthreads && k->ki_p->ki_numthreads > 1)
192 asprintf(&str, "%s%s", k->ki_p->ki_tdname,
193 k->ki_p->ki_moretdname);
194 else
195 str = strdup(" ");
196
197 return (str);
198 }
199
200 char *
logname(KINFO * k,VARENT * ve __unused)201 logname(KINFO *k, VARENT *ve __unused)
202 {
203
204 if (*k->ki_p->ki_login == '\0')
205 return (NULL);
206 return (strdup(k->ki_p->ki_login));
207 }
208
209 char *
state(KINFO * k,VARENT * ve __unused)210 state(KINFO *k, VARENT *ve __unused)
211 {
212 long flag, tdflags;
213 char *cp, *buf;
214
215 buf = malloc(16);
216 if (buf == NULL)
217 xo_errx(1, "malloc failed");
218
219 flag = k->ki_p->ki_flag;
220 tdflags = k->ki_p->ki_tdflags; /* XXXKSE */
221 cp = buf;
222
223 switch (k->ki_p->ki_stat) {
224
225 case SSTOP:
226 *cp = 'T';
227 break;
228
229 case SSLEEP:
230 if (tdflags & TDF_SINTR) /* interruptible (long) */
231 *cp = k->ki_p->ki_slptime >= MAXSLP ? 'I' : 'S';
232 else
233 *cp = 'D';
234 break;
235
236 case SRUN:
237 case SIDL:
238 *cp = 'R';
239 break;
240
241 case SWAIT:
242 *cp = 'W';
243 break;
244
245 case SLOCK:
246 *cp = 'L';
247 break;
248
249 case SZOMB:
250 *cp = 'Z';
251 break;
252
253 default:
254 *cp = '?';
255 }
256 cp++;
257 if (!(flag & P_INMEM))
258 *cp++ = 'W';
259 if (k->ki_p->ki_nice < NZERO || k->ki_p->ki_pri.pri_class == PRI_REALTIME)
260 *cp++ = '<';
261 else if (k->ki_p->ki_nice > NZERO || k->ki_p->ki_pri.pri_class == PRI_IDLE)
262 *cp++ = 'N';
263 if (flag & P_TRACED)
264 *cp++ = 'X';
265 if (flag & P_WEXIT && k->ki_p->ki_stat != SZOMB)
266 *cp++ = 'E';
267 if (flag & P_PPWAIT)
268 *cp++ = 'V';
269 if ((flag & P_SYSTEM) || k->ki_p->ki_lock > 0)
270 *cp++ = 'L';
271 if ((k->ki_p->ki_cr_flags & CRED_FLAG_CAPMODE) != 0)
272 *cp++ = 'C';
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 *
username(KINFO * k,VARENT * ve __unused)305 username(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 *
cpunum(KINFO * k,VARENT * ve __unused)545 cpunum(KINFO *k, VARENT *ve __unused)
546 {
547 char *cpu;
548
549 if (k->ki_p->ki_stat == SRUN && k->ki_p->ki_oncpu != NOCPU) {
550 asprintf(&cpu, "%d", k->ki_p->ki_oncpu);
551 } else {
552 asprintf(&cpu, "%d", k->ki_p->ki_lastcpu);
553 }
554 return (cpu);
555 }
556
557 char *
systime(KINFO * k,VARENT * ve)558 systime(KINFO *k, VARENT *ve)
559 {
560 long secs, psecs;
561
562 secs = k->ki_p->ki_rusage.ru_stime.tv_sec;
563 psecs = k->ki_p->ki_rusage.ru_stime.tv_usec;
564 if (sumrusage) {
565 secs += k->ki_p->ki_childstime.tv_sec;
566 psecs += k->ki_p->ki_childstime.tv_usec;
567 }
568 return (printtime(k, ve, secs, psecs));
569 }
570
571 char *
usertime(KINFO * k,VARENT * ve)572 usertime(KINFO *k, VARENT *ve)
573 {
574 long secs, psecs;
575
576 secs = k->ki_p->ki_rusage.ru_utime.tv_sec;
577 psecs = k->ki_p->ki_rusage.ru_utime.tv_usec;
578 if (sumrusage) {
579 secs += k->ki_p->ki_childutime.tv_sec;
580 psecs += k->ki_p->ki_childutime.tv_usec;
581 }
582 return (printtime(k, ve, secs, psecs));
583 }
584
585 char *
elapsed(KINFO * k,VARENT * ve __unused)586 elapsed(KINFO *k, VARENT *ve __unused)
587 {
588 time_t val;
589 int days, hours, mins, secs;
590 char *str;
591
592 if (!k->ki_valid)
593 return (NULL);
594 val = now - k->ki_p->ki_start.tv_sec;
595 days = val / (24 * 60 * 60);
596 val %= 24 * 60 * 60;
597 hours = val / (60 * 60);
598 val %= 60 * 60;
599 mins = val / 60;
600 secs = val % 60;
601 if (days != 0)
602 asprintf(&str, "%3d-%02d:%02d:%02d", days, hours, mins, secs);
603 else if (hours != 0)
604 asprintf(&str, "%02d:%02d:%02d", hours, mins, secs);
605 else
606 asprintf(&str, "%02d:%02d", mins, secs);
607
608 return (str);
609 }
610
611 char *
elapseds(KINFO * k,VARENT * ve __unused)612 elapseds(KINFO *k, VARENT *ve __unused)
613 {
614 time_t val;
615 char *str;
616
617 if (!k->ki_valid)
618 return (NULL);
619 val = now - k->ki_p->ki_start.tv_sec;
620 asprintf(&str, "%jd", (intmax_t)val);
621 return (str);
622 }
623
624 double
getpcpu(const KINFO * k)625 getpcpu(const KINFO *k)
626 {
627 static int failure;
628
629 if (!nlistread)
630 failure = donlist();
631 if (failure)
632 return (0.0);
633
634 #define fxtofl(fixpt) ((double)(fixpt) / fscale)
635
636 /* XXX - I don't like this */
637 if (k->ki_p->ki_swtime == 0 || (k->ki_p->ki_flag & P_INMEM) == 0)
638 return (0.0);
639 if (rawcpu)
640 return (100.0 * fxtofl(k->ki_p->ki_pctcpu));
641 return (100.0 * fxtofl(k->ki_p->ki_pctcpu) /
642 (1.0 - exp(k->ki_p->ki_swtime * log(fxtofl(ccpu)))));
643 }
644
645 char *
pcpu(KINFO * k,VARENT * ve __unused)646 pcpu(KINFO *k, VARENT *ve __unused)
647 {
648 char *str;
649
650 asprintf(&str, "%.1f", getpcpu(k));
651 return (str);
652 }
653
654 static double
getpmem(KINFO * k)655 getpmem(KINFO *k)
656 {
657 static int failure;
658 double fracmem;
659
660 if (!nlistread)
661 failure = donlist();
662 if (failure)
663 return (0.0);
664
665 if ((k->ki_p->ki_flag & P_INMEM) == 0)
666 return (0.0);
667 /* XXX want pmap ptpages, segtab, etc. (per architecture) */
668 /* XXX don't have info about shared */
669 fracmem = ((double)k->ki_p->ki_rssize) / mempages;
670 return (100.0 * fracmem);
671 }
672
673 char *
pmem(KINFO * k,VARENT * ve __unused)674 pmem(KINFO *k, VARENT *ve __unused)
675 {
676 char *str;
677
678 asprintf(&str, "%.1f", getpmem(k));
679 return (str);
680 }
681
682 char *
pagein(KINFO * k,VARENT * ve __unused)683 pagein(KINFO *k, VARENT *ve __unused)
684 {
685 char *str;
686
687 asprintf(&str, "%ld", k->ki_valid ? k->ki_p->ki_rusage.ru_majflt : 0);
688 return (str);
689 }
690
691 /* ARGSUSED */
692 char *
maxrss(KINFO * k __unused,VARENT * ve __unused)693 maxrss(KINFO *k __unused, VARENT *ve __unused)
694 {
695
696 /* XXX not yet */
697 return (NULL);
698 }
699
700 char *
priorityr(KINFO * k,VARENT * ve __unused)701 priorityr(KINFO *k, VARENT *ve __unused)
702 {
703 struct priority *lpri;
704 char *str;
705 unsigned class, level;
706
707 lpri = &k->ki_p->ki_pri;
708 class = lpri->pri_class;
709 level = lpri->pri_level;
710 switch (class) {
711 case RTP_PRIO_REALTIME:
712 /* alias for PRI_REALTIME */
713 asprintf(&str, "real:%u", level - PRI_MIN_REALTIME);
714 break;
715 case RTP_PRIO_NORMAL:
716 /* alias for PRI_TIMESHARE */
717 if (level >= PRI_MIN_TIMESHARE)
718 asprintf(&str, "normal:%u", level - PRI_MIN_TIMESHARE);
719 else
720 asprintf(&str, "kernel:%u", level - PRI_MIN_KERN);
721 break;
722 case RTP_PRIO_IDLE:
723 /* alias for PRI_IDLE */
724 asprintf(&str, "idle:%u", level - PRI_MIN_IDLE);
725 break;
726 case RTP_PRIO_ITHD:
727 /* alias for PRI_ITHD */
728 asprintf(&str, "intr:%u", level - PRI_MIN_ITHD);
729 break;
730 default:
731 asprintf(&str, "%u:%u", class, level);
732 break;
733 }
734 return (str);
735 }
736
737 /*
738 * Generic output routines. Print fields from various prototype
739 * structures.
740 */
741 static char *
printval(void * bp,VAR * v)742 printval(void *bp, VAR *v)
743 {
744 static char ofmt[32] = "%";
745 const char *fcp;
746 char *cp, *str;
747
748 cp = ofmt + 1;
749 fcp = v->fmt;
750 while ((*cp++ = *fcp++));
751
752 #define CHKINF127(n) (((n) > 127) && (v->flag & INF127) ? 127 : (n))
753
754 switch (v->type) {
755 case CHAR:
756 (void)asprintf(&str, ofmt, *(char *)bp);
757 break;
758 case UCHAR:
759 (void)asprintf(&str, ofmt, *(u_char *)bp);
760 break;
761 case SHORT:
762 (void)asprintf(&str, ofmt, *(short *)bp);
763 break;
764 case USHORT:
765 (void)asprintf(&str, ofmt, *(u_short *)bp);
766 break;
767 case INT:
768 (void)asprintf(&str, ofmt, *(int *)bp);
769 break;
770 case UINT:
771 (void)asprintf(&str, ofmt, CHKINF127(*(u_int *)bp));
772 break;
773 case LONG:
774 (void)asprintf(&str, ofmt, *(long *)bp);
775 break;
776 case ULONG:
777 (void)asprintf(&str, ofmt, *(u_long *)bp);
778 break;
779 case KPTR:
780 (void)asprintf(&str, ofmt, *(u_long *)bp);
781 break;
782 case PGTOK:
783 (void)asprintf(&str, ofmt, ps_pgtok(*(u_long *)bp));
784 break;
785 }
786
787 return (str);
788 }
789
790 char *
kvar(KINFO * k,VARENT * ve)791 kvar(KINFO *k, VARENT *ve)
792 {
793 VAR *v;
794
795 v = ve->var;
796 return (printval((char *)((char *)k->ki_p + v->off), v));
797 }
798
799 char *
rvar(KINFO * k,VARENT * ve)800 rvar(KINFO *k, VARENT *ve)
801 {
802 VAR *v;
803
804 v = ve->var;
805 if (!k->ki_valid)
806 return (NULL);
807 return (printval((char *)((char *)(&k->ki_p->ki_rusage) + v->off), v));
808 }
809
810 char *
emulname(KINFO * k,VARENT * ve __unused)811 emulname(KINFO *k, VARENT *ve __unused)
812 {
813
814 return (strdup(k->ki_p->ki_emul));
815 }
816
817 char *
label(KINFO * k,VARENT * ve __unused)818 label(KINFO *k, VARENT *ve __unused)
819 {
820 char *string;
821 mac_t proclabel;
822 int error;
823
824 string = NULL;
825 if (mac_prepare_process_label(&proclabel) == -1) {
826 xo_warn("mac_prepare_process_label");
827 goto out;
828 }
829 error = mac_get_pid(k->ki_p->ki_pid, proclabel);
830 if (error == 0) {
831 if (mac_to_text(proclabel, &string) == -1)
832 string = NULL;
833 }
834 mac_free(proclabel);
835 out:
836 return (string);
837 }
838
839 char *
loginclass(KINFO * k,VARENT * ve __unused)840 loginclass(KINFO *k, VARENT *ve __unused)
841 {
842
843 /*
844 * Don't display login class for system processes;
845 * login classes are used for resource limits,
846 * and limits don't apply to system processes.
847 */
848 if (k->ki_p->ki_flag & P_SYSTEM) {
849 return (strdup("-"));
850 }
851 return (strdup(k->ki_p->ki_loginclass));
852 }
853
854 char *
jailname(KINFO * k,VARENT * ve __unused)855 jailname(KINFO *k, VARENT *ve __unused)
856 {
857 char *name;
858
859 if (k->ki_p->ki_jid == 0)
860 return (strdup("-"));
861 name = jail_getname(k->ki_p->ki_jid);
862 if (name == NULL)
863 return (strdup("-"));
864 return (name);
865 }
866