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