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