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