1 /* 2 * Copyright (c) 1993 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 #ifndef lint 31 static const char copyright[] = 32 "@(#) Copyright (c) 1993\n\ 33 The Regents of the University of California. All rights reserved.\n"; 34 #endif /* not lint */ 35 36 #ifndef lint 37 #if 0 38 static char sccsid[] = "@(#)from: sysctl.c 8.1 (Berkeley) 6/6/93"; 39 #endif 40 static const char rcsid[] = 41 "$FreeBSD$"; 42 #endif /* not lint */ 43 44 #include <sys/param.h> 45 #include <sys/time.h> 46 #include <sys/resource.h> 47 #include <sys/sensors.h> 48 #include <sys/stat.h> 49 #include <sys/sysctl.h> 50 #include <sys/vmmeter.h> 51 52 #include <ctype.h> 53 #include <err.h> 54 #include <errno.h> 55 #include <inttypes.h> 56 #include <locale.h> 57 #include <stdio.h> 58 #include <stdlib.h> 59 #include <string.h> 60 #include <unistd.h> 61 62 static int aflag, bflag, dflag, eflag, hflag, Nflag, nflag, oflag; 63 static int qflag, xflag; 64 65 static int oidfmt(int *, int, char *, u_int *); 66 static void parse(char *); 67 static int show_var(int *, int); 68 static int sysctl_all(int *oid, int len); 69 static int name2oid(char *, int *); 70 71 static void set_T_dev_t(char *, void **, size_t *); 72 static int set_IK(char *, int *); 73 74 static void 75 usage(void) 76 { 77 78 (void)fprintf(stderr, "%s\n%s\n", 79 "usage: sysctl [-bdehNnoqx] name[=value] ...", 80 " sysctl [-bdehNnoqx] -a"); 81 exit(1); 82 } 83 84 int 85 main(int argc, char **argv) 86 { 87 int ch; 88 89 setlocale(LC_NUMERIC, ""); 90 setbuf(stdout,0); 91 setbuf(stderr,0); 92 93 while ((ch = getopt(argc, argv, "AabdehNnoqwxX")) != -1) { 94 switch (ch) { 95 case 'A': 96 /* compatibility */ 97 aflag = oflag = 1; 98 break; 99 case 'a': 100 aflag = 1; 101 break; 102 case 'b': 103 bflag = 1; 104 break; 105 case 'd': 106 dflag = 1; 107 break; 108 case 'e': 109 eflag = 1; 110 break; 111 case 'h': 112 hflag = 1; 113 break; 114 case 'N': 115 Nflag = 1; 116 break; 117 case 'n': 118 nflag = 1; 119 break; 120 case 'o': 121 oflag = 1; 122 break; 123 case 'q': 124 qflag = 1; 125 break; 126 case 'w': 127 /* compatibility */ 128 /* ignored */ 129 break; 130 case 'X': 131 /* compatibility */ 132 aflag = xflag = 1; 133 break; 134 case 'x': 135 xflag = 1; 136 break; 137 default: 138 usage(); 139 } 140 } 141 argc -= optind; 142 argv += optind; 143 144 if (Nflag && nflag) 145 usage(); 146 if (aflag && argc == 0) 147 exit(sysctl_all(0, 0)); 148 if (argc == 0) 149 usage(); 150 while (argc-- > 0) 151 parse(*argv++); 152 exit(0); 153 } 154 155 /* 156 * Parse a name into a MIB entry. 157 * Lookup and print out the MIB entry if it exists. 158 * Set a new value if requested. 159 */ 160 static void 161 parse(char *string) 162 { 163 int len, i, j; 164 void *newval = 0; 165 int intval; 166 unsigned int uintval; 167 long longval; 168 unsigned long ulongval; 169 size_t newsize = 0; 170 quad_t quadval; 171 int mib[CTL_MAXNAME]; 172 char *cp, *bufp, buf[BUFSIZ], *endptr, fmt[BUFSIZ]; 173 u_int kind; 174 175 bufp = buf; 176 if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ) 177 errx(1, "oid too long: '%s'", string); 178 if ((cp = strchr(string, '=')) != NULL) { 179 *strchr(buf, '=') = '\0'; 180 *cp++ = '\0'; 181 while (isspace(*cp)) 182 cp++; 183 newval = cp; 184 newsize = strlen(cp); 185 } 186 len = name2oid(bufp, mib); 187 188 if (len < 0) { 189 if (qflag) 190 exit(1); 191 else 192 errx(1, "unknown oid '%s'", bufp); 193 } 194 195 if (oidfmt(mib, len, fmt, &kind)) 196 err(1, "couldn't find format of oid '%s'", bufp); 197 198 if (newval == NULL) { 199 if ((kind & CTLTYPE) == CTLTYPE_NODE) { 200 if (dflag) { 201 i = show_var(mib, len); 202 if (!i && !bflag) 203 putchar('\n'); 204 } 205 sysctl_all(mib, len); 206 } else { 207 i = show_var(mib, len); 208 if (!i && !bflag) 209 putchar('\n'); 210 } 211 } else { 212 if ((kind & CTLTYPE) == CTLTYPE_NODE) 213 errx(1, "oid '%s' isn't a leaf node", bufp); 214 215 if (!(kind & CTLFLAG_WR)) { 216 if (kind & CTLFLAG_TUN) { 217 warnx("oid '%s' is a read only tunable", bufp); 218 errx(1, "Tunable values are set in /boot/loader.conf"); 219 } else { 220 errx(1, "oid '%s' is read only", bufp); 221 } 222 } 223 224 if ((kind & CTLTYPE) == CTLTYPE_INT || 225 (kind & CTLTYPE) == CTLTYPE_UINT || 226 (kind & CTLTYPE) == CTLTYPE_LONG || 227 (kind & CTLTYPE) == CTLTYPE_ULONG || 228 (kind & CTLTYPE) == CTLTYPE_QUAD) { 229 if (strlen(newval) == 0) 230 errx(1, "empty numeric value"); 231 } 232 233 switch (kind & CTLTYPE) { 234 case CTLTYPE_INT: 235 if (strcmp(fmt, "IK") == 0) { 236 if (!set_IK(newval, &intval)) 237 errx(1, "invalid value '%s'", 238 (char *)newval); 239 } else { 240 intval = (int)strtol(newval, &endptr, 241 0); 242 if (endptr == newval || *endptr != '\0') 243 errx(1, "invalid integer '%s'", 244 (char *)newval); 245 } 246 newval = &intval; 247 newsize = sizeof(intval); 248 break; 249 case CTLTYPE_UINT: 250 uintval = (int) strtoul(newval, &endptr, 0); 251 if (endptr == newval || *endptr != '\0') 252 errx(1, "invalid unsigned integer '%s'", 253 (char *)newval); 254 newval = &uintval; 255 newsize = sizeof(uintval); 256 break; 257 case CTLTYPE_LONG: 258 longval = strtol(newval, &endptr, 0); 259 if (endptr == newval || *endptr != '\0') 260 errx(1, "invalid long integer '%s'", 261 (char *)newval); 262 newval = &longval; 263 newsize = sizeof(longval); 264 break; 265 case CTLTYPE_ULONG: 266 ulongval = strtoul(newval, &endptr, 0); 267 if (endptr == newval || *endptr != '\0') 268 errx(1, "invalid unsigned long integer" 269 " '%s'", (char *)newval); 270 newval = &ulongval; 271 newsize = sizeof(ulongval); 272 break; 273 case CTLTYPE_STRING: 274 break; 275 case CTLTYPE_QUAD: 276 sscanf(newval, "%qd", &quadval); 277 newval = &quadval; 278 newsize = sizeof(quadval); 279 break; 280 case CTLTYPE_OPAQUE: 281 if (strcmp(fmt, "T,dev_t") == 0) { 282 set_T_dev_t (newval, &newval, &newsize); 283 break; 284 } 285 /* FALLTHROUGH */ 286 default: 287 errx(1, "oid '%s' is type %d," 288 " cannot set that", bufp, 289 kind & CTLTYPE); 290 } 291 292 i = show_var(mib, len); 293 if (sysctl(mib, len, 0, 0, newval, newsize) == -1) { 294 if (!i && !bflag) 295 putchar('\n'); 296 switch (errno) { 297 case EOPNOTSUPP: 298 errx(1, "%s: value is not available", 299 string); 300 case ENOTDIR: 301 errx(1, "%s: specification is incomplete", 302 string); 303 case ENOMEM: 304 errx(1, "%s: type is unknown to this program", 305 string); 306 default: 307 warn("%s", string); 308 return; 309 } 310 } 311 if (!bflag) 312 printf(" -> "); 313 i = nflag; 314 nflag = 1; 315 j = show_var(mib, len); 316 if (!j && !bflag) 317 putchar('\n'); 318 nflag = i; 319 } 320 } 321 322 /* These functions will dump out various interesting structures. */ 323 324 static int 325 S_clockinfo(int l2, void *p) 326 { 327 struct clockinfo *ci = (struct clockinfo*)p; 328 329 if (l2 != sizeof(*ci)) { 330 warnx("S_clockinfo %d != %d", l2, sizeof(*ci)); 331 return (1); 332 } 333 printf(hflag ? "{ hz = %'d, tick = %'d, profhz = %'d, stathz = %'d }" : 334 "{ hz = %d, tick = %d, profhz = %d, stathz = %d }", 335 ci->hz, ci->tick, ci->profhz, ci->stathz); 336 return (0); 337 } 338 339 static int 340 S_loadavg(int l2, void *p) 341 { 342 struct loadavg *tv = (struct loadavg*)p; 343 344 if (l2 != sizeof(*tv)) { 345 warnx("S_loadavg %d != %d", l2, sizeof(*tv)); 346 return (1); 347 } 348 printf(hflag ? "{ %'.2f %'.2f %'.2f }" : "{ %.2f %.2f %.2f }", 349 (double)tv->ldavg[0]/(double)tv->fscale, 350 (double)tv->ldavg[1]/(double)tv->fscale, 351 (double)tv->ldavg[2]/(double)tv->fscale); 352 return (0); 353 } 354 355 static int 356 S_timeval(int l2, void *p) 357 { 358 struct timeval *tv = (struct timeval*)p; 359 time_t tv_sec; 360 char *p1, *p2; 361 362 if (l2 != sizeof(*tv)) { 363 warnx("S_timeval %d != %d", l2, sizeof(*tv)); 364 return (1); 365 } 366 printf(hflag ? "{ sec = %'ld, usec = %'ld } " : 367 "{ sec = %ld, usec = %ld } ", 368 tv->tv_sec, tv->tv_usec); 369 tv_sec = tv->tv_sec; 370 p1 = strdup(ctime(&tv_sec)); 371 for (p2=p1; *p2 ; p2++) 372 if (*p2 == '\n') 373 *p2 = '\0'; 374 fputs(p1, stdout); 375 return (0); 376 } 377 378 static int 379 S_vmtotal(int l2, void *p) 380 { 381 struct vmtotal *v = (struct vmtotal *)p; 382 int pageKilo = getpagesize() / 1024; 383 384 if (l2 != sizeof(*v)) { 385 warnx("S_vmtotal %d != %d", l2, sizeof(*v)); 386 return (1); 387 } 388 389 printf( 390 "\nSystem wide totals computed every five seconds:" 391 " (values in kilobytes)\n"); 392 printf("===============================================\n"); 393 printf( 394 "Processes:\t\t(RUNQ: %hd Disk Wait: %hd Page Wait: " 395 "%hd Sleep: %hd)\n", 396 v->t_rq, v->t_dw, v->t_pw, v->t_sl); 397 printf( 398 "Virtual Memory:\t\t(Total: %dK, Active %dK)\n", 399 v->t_vm * pageKilo, v->t_avm * pageKilo); 400 printf("Real Memory:\t\t(Total: %dK Active %dK)\n", 401 v->t_rm * pageKilo, v->t_arm * pageKilo); 402 printf("Shared Virtual Memory:\t(Total: %dK Active: %dK)\n", 403 v->t_vmshr * pageKilo, v->t_avmshr * pageKilo); 404 printf("Shared Real Memory:\t(Total: %dK Active: %dK)\n", 405 v->t_rmshr * pageKilo, v->t_armshr * pageKilo); 406 printf("Free Memory Pages:\t%dK\n", v->t_free * pageKilo); 407 408 return (0); 409 } 410 411 static int 412 S_sensor(int l2, void *p) 413 { 414 struct sensor *s = (struct sensor *)p; 415 416 if (l2 != sizeof(*s)) { 417 warnx("S_sensor %d != %d", l2, sizeof(*s)); 418 return (1); 419 } 420 421 if (s->flags & SENSOR_FINVALID) { 422 /* 423 * XXX: with this flag, the node should be entirely ignored, 424 * but as the magic-based sysctl(8) is not too flexible, we 425 * simply have to print out that the sensor is invalid. 426 */ 427 printf("invalid"); 428 return (0); 429 } 430 431 if (s->flags & SENSOR_FUNKNOWN) 432 printf("unknown"); 433 else { 434 switch (s->type) { 435 case SENSOR_TEMP: 436 printf("%.2f degC", 437 (s->value - 273150000) / 1000000.0); 438 break; 439 case SENSOR_FANRPM: 440 printf("%lld RPM", s->value); 441 break; 442 case SENSOR_VOLTS_DC: 443 printf("%.2f VDC", s->value / 1000000.0); 444 break; 445 case SENSOR_AMPS: 446 printf("%.2f A", s->value / 1000000.0); 447 break; 448 case SENSOR_WATTHOUR: 449 printf("%.2f Wh", s->value / 1000000.0); 450 break; 451 case SENSOR_AMPHOUR: 452 printf("%.2f Ah", s->value / 1000000.0); 453 break; 454 case SENSOR_INDICATOR: 455 printf("%s", s->value ? "On" : "Off"); 456 break; 457 case SENSOR_INTEGER: 458 printf("%lld", s->value); 459 break; 460 case SENSOR_PERCENT: 461 printf("%.2f%%", s->value / 1000.0); 462 break; 463 case SENSOR_LUX: 464 printf("%.2f lx", s->value / 1000000.0); 465 break; 466 case SENSOR_DRIVE: 467 { 468 const char *name; 469 470 switch (s->value) { 471 case SENSOR_DRIVE_EMPTY: 472 name = "empty"; 473 break; 474 case SENSOR_DRIVE_READY: 475 name = "ready"; 476 break; 477 case SENSOR_DRIVE_POWERUP: 478 name = "powering up"; 479 break; 480 case SENSOR_DRIVE_ONLINE: 481 name = "online"; 482 break; 483 case SENSOR_DRIVE_IDLE: 484 name = "idle"; 485 break; 486 case SENSOR_DRIVE_ACTIVE: 487 name = "active"; 488 break; 489 case SENSOR_DRIVE_REBUILD: 490 name = "rebuilding"; 491 break; 492 case SENSOR_DRIVE_POWERDOWN: 493 name = "powering down"; 494 break; 495 case SENSOR_DRIVE_FAIL: 496 name = "failed"; 497 break; 498 case SENSOR_DRIVE_PFAIL: 499 name = "degraded"; 500 break; 501 default: 502 name = "unknown"; 503 break; 504 } 505 printf(name); 506 break; 507 } 508 case SENSOR_TIMEDELTA: 509 printf("%.6f secs", s->value / 1000000000.0); 510 break; 511 default: 512 printf("unknown"); 513 } 514 } 515 516 if (s->desc[0] != '\0') 517 printf(" (%s)", s->desc); 518 519 switch (s->status) { 520 case SENSOR_S_UNSPEC: 521 break; 522 case SENSOR_S_OK: 523 printf(", OK"); 524 break; 525 case SENSOR_S_WARN: 526 printf(", WARNING"); 527 break; 528 case SENSOR_S_CRIT: 529 printf(", CRITICAL"); 530 break; 531 case SENSOR_S_UNKNOWN: 532 printf(", UNKNOWN"); 533 break; 534 } 535 536 if (s->tv.tv_sec) { 537 time_t t = s->tv.tv_sec; 538 char ct[26]; 539 540 ctime_r(&t, ct); 541 ct[19] = '\0'; 542 printf(", %s.%03ld", ct, s->tv.tv_usec / 1000); 543 } 544 545 return (0); 546 } 547 548 static int 549 T_dev_t(int l2, void *p) 550 { 551 dev_t *d = (dev_t *)p; 552 553 if (l2 != sizeof(*d)) { 554 warnx("T_dev_T %d != %d", l2, sizeof(*d)); 555 return (1); 556 } 557 if ((int)(*d) != -1) { 558 if (minor(*d) > 255 || minor(*d) < 0) 559 printf("{ major = %d, minor = 0x%x }", 560 major(*d), minor(*d)); 561 else 562 printf("{ major = %d, minor = %d }", 563 major(*d), minor(*d)); 564 } 565 return (0); 566 } 567 568 static void 569 set_T_dev_t(char *path, void **val, size_t *size) 570 { 571 static struct stat statb; 572 573 if (strcmp(path, "none") && strcmp(path, "off")) { 574 int rc = stat (path, &statb); 575 if (rc) { 576 err(1, "cannot stat %s", path); 577 } 578 579 if (!S_ISCHR(statb.st_mode)) { 580 errx(1, "must specify a device special file."); 581 } 582 } else { 583 statb.st_rdev = NODEV; 584 } 585 *val = (void *) &statb.st_rdev; 586 *size = sizeof(statb.st_rdev); 587 } 588 589 static int 590 set_IK(char *str, int *val) 591 { 592 float temp; 593 int len, kelv; 594 char *p, *endptr; 595 596 if ((len = strlen(str)) == 0) 597 return (0); 598 p = &str[len - 1]; 599 if (*p == 'C' || *p == 'F') { 600 *p = '\0'; 601 temp = strtof(str, &endptr); 602 if (endptr == str || *endptr != '\0') 603 return (0); 604 if (*p == 'F') 605 temp = (temp - 32) * 5 / 9; 606 kelv = temp * 10 + 2732; 607 } else { 608 kelv = (int)strtol(str, &endptr, 10); 609 if (endptr == str || *endptr != '\0') 610 return (0); 611 } 612 *val = kelv; 613 return (1); 614 } 615 616 /* 617 * These functions uses a presently undocumented interface to the kernel 618 * to walk the tree and get the type so it can print the value. 619 * This interface is under work and consideration, and should probably 620 * be killed with a big axe by the first person who can find the time. 621 * (be aware though, that the proper interface isn't as obvious as it 622 * may seem, there are various conflicting requirements. 623 */ 624 625 static int 626 name2oid(char *name, int *oidp) 627 { 628 int oid[2]; 629 int i; 630 size_t j; 631 632 oid[0] = 0; 633 oid[1] = 3; 634 635 j = CTL_MAXNAME * sizeof(int); 636 i = sysctl(oid, 2, oidp, &j, name, strlen(name)); 637 if (i < 0) 638 return (i); 639 j /= sizeof(int); 640 return (j); 641 } 642 643 static int 644 oidfmt(int *oid, int len, char *fmt, u_int *kind) 645 { 646 int qoid[CTL_MAXNAME+2]; 647 u_char buf[BUFSIZ]; 648 int i; 649 size_t j; 650 651 qoid[0] = 0; 652 qoid[1] = 4; 653 memcpy(qoid + 2, oid, len * sizeof(int)); 654 655 j = sizeof(buf); 656 i = sysctl(qoid, len + 2, buf, &j, 0, 0); 657 if (i) 658 err(1, "sysctl fmt %d %d %d", i, j, errno); 659 660 if (kind) 661 *kind = *(u_int *)buf; 662 663 if (fmt) 664 strcpy(fmt, (char *)(buf + sizeof(u_int))); 665 return (0); 666 } 667 668 /* 669 * This formats and outputs the value of one variable 670 * 671 * Returns zero if anything was actually output. 672 * Returns one if didn't know what to do with this. 673 * Return minus one if we had errors. 674 */ 675 676 static int 677 show_var(int *oid, int nlen) 678 { 679 u_char buf[BUFSIZ], *val, *oval, *p; 680 char name[BUFSIZ], *fmt; 681 const char *sep, *sep1; 682 int qoid[CTL_MAXNAME+2]; 683 uintmax_t umv; 684 intmax_t mv; 685 int i, hexlen; 686 size_t intlen; 687 size_t j, len; 688 u_int kind; 689 int (*func)(int, void *); 690 691 bzero(buf, BUFSIZ); 692 bzero(name, BUFSIZ); 693 qoid[0] = 0; 694 memcpy(qoid + 2, oid, nlen * sizeof(int)); 695 696 qoid[1] = 1; 697 j = sizeof(name); 698 i = sysctl(qoid, nlen + 2, name, &j, 0, 0); 699 if (i || !j) 700 err(1, "sysctl name %d %d %d", i, j, errno); 701 702 if (Nflag) { 703 printf("%s", name); 704 return (0); 705 } 706 707 if (eflag) 708 sep = "="; 709 else 710 sep = ": "; 711 712 if (dflag) { /* just print description */ 713 qoid[1] = 5; 714 j = sizeof(buf); 715 i = sysctl(qoid, nlen + 2, buf, &j, 0, 0); 716 if (!nflag) 717 printf("%s%s", name, sep); 718 printf("%s", buf); 719 return (0); 720 } 721 /* find an estimate of how much we need for this var */ 722 j = 0; 723 i = sysctl(oid, nlen, 0, &j, 0, 0); 724 j += j; /* we want to be sure :-) */ 725 726 val = oval = malloc(j + 1); 727 if (val == NULL) { 728 warnx("malloc failed"); 729 return (1); 730 } 731 len = j; 732 i = sysctl(oid, nlen, val, &len, 0, 0); 733 if (i || !len) { 734 free(oval); 735 return (1); 736 } 737 738 if (bflag) { 739 fwrite(val, 1, len, stdout); 740 free(oval); 741 return (0); 742 } 743 val[len] = '\0'; 744 fmt = buf; 745 oidfmt(oid, nlen, fmt, &kind); 746 p = val; 747 switch (*fmt) { 748 case 'A': 749 if (!nflag) 750 printf("%s%s", name, sep); 751 printf("%.*s", len, p); 752 free(oval); 753 return (0); 754 755 case 'I': 756 case 'L': 757 case 'Q': 758 if (!nflag) 759 printf("%s%s", name, sep); 760 switch (*fmt) { 761 case 'I': intlen = sizeof(int); break; 762 case 'L': intlen = sizeof(long); break; 763 case 'Q': intlen = sizeof(quad_t); break; 764 } 765 hexlen = 2 + (intlen * CHAR_BIT + 3) / 4; 766 sep1 = ""; 767 while (len >= intlen) { 768 switch (*fmt) { 769 case 'I': 770 umv = *(u_int *)p; 771 mv = *(int *)p; 772 break; 773 case 'L': 774 umv = *(u_long *)p; 775 mv = *(long *)p; 776 break; 777 case 'Q': 778 umv = *(u_quad_t *)p; 779 mv = *(quad_t *)p; 780 break; 781 } 782 fputs(sep1, stdout); 783 if (fmt[1] == 'U') 784 printf(hflag ? "%'ju" : "%ju", umv); 785 else if (fmt[1] == 'X') 786 printf("%#0*jx", hexlen, umv); 787 else if (fmt[1] == 'K') { 788 if (mv < 0) 789 printf("%jd", mv); 790 else 791 printf("%.1fC", (mv - 2732.0) / 10); 792 } else 793 printf(hflag ? "%'jd" : "%jd", mv); 794 sep1 = " "; 795 len -= intlen; 796 p += intlen; 797 } 798 free(oval); 799 return (0); 800 801 case 'P': 802 if (!nflag) 803 printf("%s%s", name, sep); 804 printf("%p", *(void **)p); 805 free(oval); 806 return (0); 807 808 case 'T': 809 case 'S': 810 i = 0; 811 if (strcmp(fmt, "S,clockinfo") == 0) 812 func = S_clockinfo; 813 else if (strcmp(fmt, "S,timeval") == 0) 814 func = S_timeval; 815 else if (strcmp(fmt, "S,loadavg") == 0) 816 func = S_loadavg; 817 else if (strcmp(fmt, "S,vmtotal") == 0) 818 func = S_vmtotal; 819 else if (strcmp(fmt, "S,sensor") == 0) 820 func = S_sensor; 821 else if (strcmp(fmt, "T,dev_t") == 0) 822 func = T_dev_t; 823 else 824 func = NULL; 825 if (func) { 826 if (!nflag) 827 printf("%s%s", name, sep); 828 i = (*func)(len, p); 829 free(oval); 830 return (i); 831 } 832 /* FALLTHROUGH */ 833 default: 834 if (!oflag && !xflag) { 835 free(oval); 836 return (1); 837 } 838 if (!nflag) 839 printf("%s%s", name, sep); 840 printf("Format:%s Length:%d Dump:0x", fmt, len); 841 while (len-- && (xflag || p < val + 16)) 842 printf("%02x", *p++); 843 if (!xflag && len > 16) 844 printf("..."); 845 free(oval); 846 return (0); 847 } 848 free(oval); 849 return (1); 850 } 851 852 static int 853 sysctl_all(int *oid, int len) 854 { 855 int name1[22], name2[22]; 856 int i, j; 857 size_t l1, l2; 858 859 name1[0] = 0; 860 name1[1] = 2; 861 l1 = 2; 862 if (len) { 863 memcpy(name1+2, oid, len * sizeof(int)); 864 l1 += len; 865 } else { 866 name1[2] = 1; 867 l1++; 868 } 869 for (;;) { 870 l2 = sizeof(name2); 871 j = sysctl(name1, l1, name2, &l2, 0, 0); 872 if (j < 0) { 873 if (errno == ENOENT) 874 return (0); 875 else 876 err(1, "sysctl(getnext) %d %d", j, l2); 877 } 878 879 l2 /= sizeof(int); 880 881 if (len < 0 || l2 < (unsigned int)len) 882 return (0); 883 884 for (i = 0; i < len; i++) 885 if (name2[i] != oid[i]) 886 return (0); 887 888 i = show_var(name2, l2); 889 if (!i && !bflag) 890 putchar('\n'); 891 892 memcpy(name1+2, name2, l2 * sizeof(int)); 893 l1 = 2 + l2; 894 } 895 } 896