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