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