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