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