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