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