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