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 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 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 * 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 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 * 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 * 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 * 693 maxrss(KINFO *k __unused, VARENT *ve __unused) 694 { 695 696 /* XXX not yet */ 697 return (NULL); 698 } 699 700 char * 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 * 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 * 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 * 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 * 811 emulname(KINFO *k, VARENT *ve __unused) 812 { 813 814 return (strdup(k->ki_p->ki_emul)); 815 } 816 817 char * 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 * 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 * 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