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