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