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