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 * 4. 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 30 #ifndef lint 31 static const char copyright[] = 32 "@(#) Copyright (c) 1993\n\ 33 The Regents of the University of California. All rights reserved.\n"; 34 #endif /* not lint */ 35 36 #ifndef lint 37 #if 0 38 static char sccsid[] = "@(#)from: sysctl.c 8.1 (Berkeley) 6/6/93"; 39 #endif 40 static const char rcsid[] = 41 "$FreeBSD$"; 42 #endif /* not lint */ 43 44 #include <sys/param.h> 45 #include <sys/time.h> 46 #include <sys/resource.h> 47 #include <sys/stat.h> 48 #include <sys/sysctl.h> 49 #include <sys/vmmeter.h> 50 51 #if defined(__amd64__) || defined(__i386__) 52 #include <machine/pc/bios.h> 53 #endif 54 55 #include <ctype.h> 56 #include <err.h> 57 #include <errno.h> 58 #include <inttypes.h> 59 #include <locale.h> 60 #include <stdio.h> 61 #include <stdlib.h> 62 #include <string.h> 63 #include <sysexits.h> 64 #include <unistd.h> 65 66 static const char *conffile; 67 68 static int aflag, bflag, dflag, eflag, hflag, iflag; 69 static int Nflag, nflag, oflag, qflag, Tflag, Wflag, xflag; 70 71 static int oidfmt(int *, int, char *, u_int *); 72 static int parsefile(const char *); 73 static int parse(const char *, int); 74 static int show_var(int *, int); 75 static int sysctl_all(int *oid, int len); 76 static int name2oid(char *, int *); 77 78 static int set_IK(const char *, int *); 79 80 static void 81 usage(void) 82 { 83 84 (void)fprintf(stderr, "%s\n%s\n", 85 "usage: sysctl [-bdehiNnoqTWx] [-f filename] name[=value] ...", 86 " sysctl [-bdehNnoqTWx] -a"); 87 exit(1); 88 } 89 90 int 91 main(int argc, char **argv) 92 { 93 int ch; 94 int warncount = 0; 95 96 setlocale(LC_NUMERIC, ""); 97 setbuf(stdout,0); 98 setbuf(stderr,0); 99 100 while ((ch = getopt(argc, argv, "Aabdef:hiNnoqTwWxX")) != -1) { 101 switch (ch) { 102 case 'A': 103 /* compatibility */ 104 aflag = oflag = 1; 105 break; 106 case 'a': 107 aflag = 1; 108 break; 109 case 'b': 110 bflag = 1; 111 break; 112 case 'd': 113 dflag = 1; 114 break; 115 case 'e': 116 eflag = 1; 117 break; 118 case 'f': 119 conffile = optarg; 120 break; 121 case 'h': 122 hflag = 1; 123 break; 124 case 'i': 125 iflag = 1; 126 break; 127 case 'N': 128 Nflag = 1; 129 break; 130 case 'n': 131 nflag = 1; 132 break; 133 case 'o': 134 oflag = 1; 135 break; 136 case 'q': 137 qflag = 1; 138 break; 139 case 'T': 140 Tflag = 1; 141 break; 142 case 'w': 143 /* compatibility */ 144 /* ignored */ 145 break; 146 case 'W': 147 Wflag = 1; 148 break; 149 case 'X': 150 /* compatibility */ 151 aflag = xflag = 1; 152 break; 153 case 'x': 154 xflag = 1; 155 break; 156 default: 157 usage(); 158 } 159 } 160 argc -= optind; 161 argv += optind; 162 163 if (Nflag && nflag) 164 usage(); 165 if (aflag && argc == 0) 166 exit(sysctl_all(0, 0)); 167 if (argc == 0 && conffile == NULL) 168 usage(); 169 170 warncount = 0; 171 if (conffile != NULL) 172 warncount += parsefile(conffile); 173 174 while (argc-- > 0) 175 warncount += parse(*argv++, 0); 176 177 return (warncount); 178 } 179 180 /* 181 * Parse a name into a MIB entry. 182 * Lookup and print out the MIB entry if it exists. 183 * Set a new value if requested. 184 */ 185 static int 186 parse(const char *string, int lineno) 187 { 188 int len, i, j; 189 void *newval = 0; 190 int intval; 191 unsigned int uintval; 192 long longval; 193 unsigned long ulongval; 194 size_t newsize = 0; 195 int64_t i64val; 196 uint64_t u64val; 197 int mib[CTL_MAXNAME]; 198 char *cp, *bufp, buf[BUFSIZ], *endptr, fmt[BUFSIZ], line[BUFSIZ]; 199 u_int kind; 200 201 if (lineno) 202 snprintf(line, sizeof(line), " at line %d", lineno); 203 else 204 line[0] = '\0'; 205 206 cp = buf; 207 if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ) { 208 warnx("oid too long: '%s'%s", string, line); 209 return (1); 210 } 211 bufp = strsep(&cp, "=:"); 212 if (cp != NULL) { 213 /* Tflag just lists tunables, do not allow assignment */ 214 if (Tflag || Wflag) { 215 warnx("Can't set variables when using -T or -W"); 216 usage(); 217 } 218 while (isspace(*cp)) 219 cp++; 220 /* Strip a pair of " or ' if any. */ 221 switch (*cp) { 222 case '\"': 223 case '\'': 224 if (cp[strlen(cp) - 1] == *cp) 225 cp[strlen(cp) - 1] = '\0'; 226 cp++; 227 } 228 newval = cp; 229 newsize = strlen(cp); 230 } 231 len = name2oid(bufp, mib); 232 233 if (len < 0) { 234 if (iflag) 235 return (0); 236 if (qflag) 237 return (1); 238 else { 239 warn("unknown oid '%s'%s", bufp, line); 240 return (1); 241 } 242 } 243 244 if (oidfmt(mib, len, fmt, &kind)) { 245 warn("couldn't find format of oid '%s'%s", bufp, line); 246 if (iflag) 247 return (1); 248 else 249 exit(1); 250 } 251 252 if (newval == NULL || dflag) { 253 if ((kind & CTLTYPE) == CTLTYPE_NODE) { 254 if (dflag) { 255 i = show_var(mib, len); 256 if (!i && !bflag) 257 putchar('\n'); 258 } 259 sysctl_all(mib, len); 260 } else { 261 i = show_var(mib, len); 262 if (!i && !bflag) 263 putchar('\n'); 264 } 265 } else { 266 if ((kind & CTLTYPE) == CTLTYPE_NODE) { 267 warnx("oid '%s' isn't a leaf node%s", bufp, line); 268 return (1); 269 } 270 271 if (!(kind & CTLFLAG_WR)) { 272 if (kind & CTLFLAG_TUN) { 273 warnx("oid '%s' is a read only tunable%s", bufp, line); 274 warnx("Tunable values are set in /boot/loader.conf"); 275 } else 276 warnx("oid '%s' is read only%s", bufp, line); 277 return (1); 278 } 279 280 if ((kind & CTLTYPE) == CTLTYPE_INT || 281 (kind & CTLTYPE) == CTLTYPE_UINT || 282 (kind & CTLTYPE) == CTLTYPE_LONG || 283 (kind & CTLTYPE) == CTLTYPE_ULONG || 284 (kind & CTLTYPE) == CTLTYPE_S64 || 285 (kind & CTLTYPE) == CTLTYPE_U64) { 286 if (strlen(newval) == 0) { 287 warnx("empty numeric value"); 288 return (1); 289 } 290 } 291 292 switch (kind & CTLTYPE) { 293 case CTLTYPE_INT: 294 if (strcmp(fmt, "IK") == 0) { 295 if (!set_IK(newval, &intval)) { 296 warnx("invalid value '%s'%s", 297 (char *)newval, line); 298 return (1); 299 } 300 } else { 301 intval = (int)strtol(newval, &endptr, 302 0); 303 if (endptr == newval || *endptr != '\0') { 304 warnx("invalid integer '%s'%s", 305 (char *)newval, line); 306 return (1); 307 } 308 } 309 newval = &intval; 310 newsize = sizeof(intval); 311 break; 312 case CTLTYPE_UINT: 313 uintval = (int) strtoul(newval, &endptr, 0); 314 if (endptr == newval || *endptr != '\0') { 315 warnx("invalid unsigned integer '%s'%s", 316 (char *)newval, line); 317 return (1); 318 } 319 newval = &uintval; 320 newsize = sizeof(uintval); 321 break; 322 case CTLTYPE_LONG: 323 longval = strtol(newval, &endptr, 0); 324 if (endptr == newval || *endptr != '\0') { 325 warnx("invalid long integer '%s'%s", 326 (char *)newval, line); 327 return (1); 328 } 329 newval = &longval; 330 newsize = sizeof(longval); 331 break; 332 case CTLTYPE_ULONG: 333 ulongval = strtoul(newval, &endptr, 0); 334 if (endptr == newval || *endptr != '\0') { 335 warnx("invalid unsigned long integer" 336 " '%s'%s", (char *)newval, line); 337 return (1); 338 } 339 newval = &ulongval; 340 newsize = sizeof(ulongval); 341 break; 342 case CTLTYPE_STRING: 343 break; 344 case CTLTYPE_S64: 345 i64val = strtoimax(newval, &endptr, 0); 346 if (endptr == newval || *endptr != '\0') { 347 warnx("invalid int64_t '%s'%s", 348 (char *)newval, line); 349 return (1); 350 } 351 newval = &i64val; 352 newsize = sizeof(i64val); 353 break; 354 case CTLTYPE_U64: 355 u64val = strtoumax(newval, &endptr, 0); 356 if (endptr == newval || *endptr != '\0') { 357 warnx("invalid uint64_t '%s'%s", 358 (char *)newval, line); 359 return (1); 360 } 361 newval = &u64val; 362 newsize = sizeof(u64val); 363 break; 364 case CTLTYPE_OPAQUE: 365 /* FALLTHROUGH */ 366 default: 367 warnx("oid '%s' is type %d," 368 " cannot set that%s", bufp, 369 kind & CTLTYPE, line); 370 return (1); 371 } 372 373 i = show_var(mib, len); 374 if (sysctl(mib, len, 0, 0, newval, newsize) == -1) { 375 if (!i && !bflag) 376 putchar('\n'); 377 switch (errno) { 378 case EOPNOTSUPP: 379 warnx("%s: value is not available%s", 380 string, line); 381 return (1); 382 case ENOTDIR: 383 warnx("%s: specification is incomplete%s", 384 string, line); 385 return (1); 386 case ENOMEM: 387 warnx("%s: type is unknown to this program%s", 388 string, line); 389 return (1); 390 default: 391 warn("%s%s", string, line); 392 return (1); 393 } 394 } 395 if (!bflag) 396 printf(" -> "); 397 i = nflag; 398 nflag = 1; 399 j = show_var(mib, len); 400 if (!j && !bflag) 401 putchar('\n'); 402 nflag = i; 403 } 404 405 return (0); 406 } 407 408 static int 409 parsefile(const char *filename) 410 { 411 FILE *file; 412 char line[BUFSIZ], *p, *pq, *pdq; 413 int warncount = 0, lineno = 0; 414 415 file = fopen(filename, "r"); 416 if (file == NULL) 417 err(EX_NOINPUT, "%s", filename); 418 while (fgets(line, sizeof(line), file) != NULL) { 419 lineno++; 420 p = line; 421 pq = strchr(line, '\''); 422 pdq = strchr(line, '\"'); 423 /* Replace the first # with \0. */ 424 while((p = strchr(p, '#')) != NULL) { 425 if (pq != NULL && p > pq) { 426 if ((p = strchr(pq+1, '\'')) != NULL) 427 *(++p) = '\0'; 428 break; 429 } else if (pdq != NULL && p > pdq) { 430 if ((p = strchr(pdq+1, '\"')) != NULL) 431 *(++p) = '\0'; 432 break; 433 } else if (p == line || *(p-1) != '\\') { 434 *p = '\0'; 435 break; 436 } 437 p++; 438 } 439 /* Trim spaces */ 440 p = line + strlen(line) - 1; 441 while (p >= line && isspace((int)*p)) { 442 *p = '\0'; 443 p--; 444 } 445 p = line; 446 while (isspace((int)*p)) 447 p++; 448 if (*p == '\0') 449 continue; 450 else 451 warncount += parse(p, lineno); 452 } 453 fclose(file); 454 455 return (warncount); 456 } 457 458 /* These functions will dump out various interesting structures. */ 459 460 static int 461 S_clockinfo(size_t l2, void *p) 462 { 463 struct clockinfo *ci = (struct clockinfo*)p; 464 465 if (l2 != sizeof(*ci)) { 466 warnx("S_clockinfo %zu != %zu", l2, sizeof(*ci)); 467 return (1); 468 } 469 printf(hflag ? "{ hz = %'d, tick = %'d, profhz = %'d, stathz = %'d }" : 470 "{ hz = %d, tick = %d, profhz = %d, stathz = %d }", 471 ci->hz, ci->tick, ci->profhz, ci->stathz); 472 return (0); 473 } 474 475 static int 476 S_loadavg(size_t l2, void *p) 477 { 478 struct loadavg *tv = (struct loadavg*)p; 479 480 if (l2 != sizeof(*tv)) { 481 warnx("S_loadavg %zu != %zu", l2, sizeof(*tv)); 482 return (1); 483 } 484 printf(hflag ? "{ %'.2f %'.2f %'.2f }" : "{ %.2f %.2f %.2f }", 485 (double)tv->ldavg[0]/(double)tv->fscale, 486 (double)tv->ldavg[1]/(double)tv->fscale, 487 (double)tv->ldavg[2]/(double)tv->fscale); 488 return (0); 489 } 490 491 static int 492 S_timeval(size_t l2, void *p) 493 { 494 struct timeval *tv = (struct timeval*)p; 495 time_t tv_sec; 496 char *p1, *p2; 497 498 if (l2 != sizeof(*tv)) { 499 warnx("S_timeval %zu != %zu", l2, sizeof(*tv)); 500 return (1); 501 } 502 printf(hflag ? "{ sec = %'jd, usec = %'ld } " : 503 "{ sec = %jd, usec = %ld } ", 504 (intmax_t)tv->tv_sec, tv->tv_usec); 505 tv_sec = tv->tv_sec; 506 p1 = strdup(ctime(&tv_sec)); 507 for (p2=p1; *p2 ; p2++) 508 if (*p2 == '\n') 509 *p2 = '\0'; 510 fputs(p1, stdout); 511 free(p1); 512 return (0); 513 } 514 515 static int 516 S_vmtotal(size_t l2, void *p) 517 { 518 struct vmtotal *v = (struct vmtotal *)p; 519 int pageKilo = getpagesize() / 1024; 520 521 if (l2 != sizeof(*v)) { 522 warnx("S_vmtotal %zu != %zu", l2, sizeof(*v)); 523 return (1); 524 } 525 526 printf( 527 "\nSystem wide totals computed every five seconds:" 528 " (values in kilobytes)\n"); 529 printf("===============================================\n"); 530 printf( 531 "Processes:\t\t(RUNQ: %hd Disk Wait: %hd Page Wait: " 532 "%hd Sleep: %hd)\n", 533 v->t_rq, v->t_dw, v->t_pw, v->t_sl); 534 printf( 535 "Virtual Memory:\t\t(Total: %dK Active: %dK)\n", 536 v->t_vm * pageKilo, v->t_avm * pageKilo); 537 printf("Real Memory:\t\t(Total: %dK Active: %dK)\n", 538 v->t_rm * pageKilo, v->t_arm * pageKilo); 539 printf("Shared Virtual Memory:\t(Total: %dK Active: %dK)\n", 540 v->t_vmshr * pageKilo, v->t_avmshr * pageKilo); 541 printf("Shared Real Memory:\t(Total: %dK Active: %dK)\n", 542 v->t_rmshr * pageKilo, v->t_armshr * pageKilo); 543 printf("Free Memory:\t%dK", v->t_free * pageKilo); 544 545 return (0); 546 } 547 548 #if defined(__amd64__) || defined(__i386__) 549 static int 550 S_bios_smap_xattr(size_t l2, void *p) 551 { 552 struct bios_smap_xattr *smap, *end; 553 554 if (l2 % sizeof(*smap) != 0) { 555 warnx("S_bios_smap_xattr %zu is not a multiple of %zu", l2, 556 sizeof(*smap)); 557 return (1); 558 } 559 560 end = (struct bios_smap_xattr *)((char *)p + l2); 561 for (smap = p; smap < end; smap++) 562 printf("\nSMAP type=%02x, xattr=%02x, base=%016jx, len=%016jx", 563 smap->type, smap->xattr, (uintmax_t)smap->base, 564 (uintmax_t)smap->length); 565 return (0); 566 } 567 #endif 568 569 static int 570 set_IK(const char *str, int *val) 571 { 572 float temp; 573 int len, kelv; 574 const char *p; 575 char *endptr; 576 577 if ((len = strlen(str)) == 0) 578 return (0); 579 p = &str[len - 1]; 580 if (*p == 'C' || *p == 'F') { 581 temp = strtof(str, &endptr); 582 if (endptr == str || endptr != p) 583 return (0); 584 if (*p == 'F') 585 temp = (temp - 32) * 5 / 9; 586 kelv = temp * 10 + 2732; 587 } else { 588 kelv = (int)strtol(str, &endptr, 10); 589 if (endptr == str || *endptr != '\0') 590 return (0); 591 } 592 *val = kelv; 593 return (1); 594 } 595 596 /* 597 * These functions uses a presently undocumented interface to the kernel 598 * to walk the tree and get the type so it can print the value. 599 * This interface is under work and consideration, and should probably 600 * be killed with a big axe by the first person who can find the time. 601 * (be aware though, that the proper interface isn't as obvious as it 602 * may seem, there are various conflicting requirements. 603 */ 604 605 static int 606 name2oid(char *name, int *oidp) 607 { 608 int oid[2]; 609 int i; 610 size_t j; 611 612 oid[0] = 0; 613 oid[1] = 3; 614 615 j = CTL_MAXNAME * sizeof(int); 616 i = sysctl(oid, 2, oidp, &j, name, strlen(name)); 617 if (i < 0) 618 return (i); 619 j /= sizeof(int); 620 return (j); 621 } 622 623 static int 624 oidfmt(int *oid, int len, char *fmt, u_int *kind) 625 { 626 int qoid[CTL_MAXNAME+2]; 627 u_char buf[BUFSIZ]; 628 int i; 629 size_t j; 630 631 qoid[0] = 0; 632 qoid[1] = 4; 633 memcpy(qoid + 2, oid, len * sizeof(int)); 634 635 j = sizeof(buf); 636 i = sysctl(qoid, len + 2, buf, &j, 0, 0); 637 if (i) 638 err(1, "sysctl fmt %d %zu %d", i, j, errno); 639 640 if (kind) 641 *kind = *(u_int *)buf; 642 643 if (fmt) 644 strcpy(fmt, (char *)(buf + sizeof(u_int))); 645 return (0); 646 } 647 648 static int ctl_sign[CTLTYPE+1] = { 649 [CTLTYPE_INT] = 1, 650 [CTLTYPE_LONG] = 1, 651 [CTLTYPE_S64] = 1, 652 }; 653 654 static int ctl_size[CTLTYPE+1] = { 655 [CTLTYPE_INT] = sizeof(int), 656 [CTLTYPE_UINT] = sizeof(u_int), 657 [CTLTYPE_LONG] = sizeof(long), 658 [CTLTYPE_ULONG] = sizeof(u_long), 659 [CTLTYPE_S64] = sizeof(int64_t), 660 [CTLTYPE_U64] = sizeof(int64_t), 661 }; 662 663 /* 664 * This formats and outputs the value of one variable 665 * 666 * Returns zero if anything was actually output. 667 * Returns one if didn't know what to do with this. 668 * Return minus one if we had errors. 669 */ 670 static int 671 show_var(int *oid, int nlen) 672 { 673 u_char buf[BUFSIZ], *val, *oval, *p; 674 char name[BUFSIZ], fmt[BUFSIZ]; 675 const char *sep, *sep1; 676 int qoid[CTL_MAXNAME+2]; 677 uintmax_t umv; 678 intmax_t mv; 679 int i, hexlen, sign, ctltype; 680 size_t intlen; 681 size_t j, len; 682 u_int kind; 683 int (*func)(size_t, void *); 684 685 /* Silence GCC. */ 686 umv = mv = intlen = 0; 687 688 bzero(buf, BUFSIZ); 689 bzero(fmt, BUFSIZ); 690 bzero(name, BUFSIZ); 691 qoid[0] = 0; 692 memcpy(qoid + 2, oid, nlen * sizeof(int)); 693 694 qoid[1] = 1; 695 j = sizeof(name); 696 i = sysctl(qoid, nlen + 2, name, &j, 0, 0); 697 if (i || !j) 698 err(1, "sysctl name %d %zu %d", i, j, errno); 699 700 oidfmt(oid, nlen, fmt, &kind); 701 /* if Wflag then only list sysctls that are writeable and not stats. */ 702 if (Wflag && ((kind & CTLFLAG_WR) == 0 || (kind & CTLFLAG_STATS) != 0)) 703 return 1; 704 705 /* if Tflag then only list sysctls that are tuneables. */ 706 if (Tflag && (kind & CTLFLAG_TUN) == 0) 707 return 1; 708 709 if (Nflag) { 710 printf("%s", name); 711 return (0); 712 } 713 714 if (eflag) 715 sep = "="; 716 else 717 sep = ": "; 718 719 if (dflag) { /* just print description */ 720 qoid[1] = 5; 721 j = sizeof(buf); 722 i = sysctl(qoid, nlen + 2, buf, &j, 0, 0); 723 if (!nflag) 724 printf("%s%s", name, sep); 725 printf("%s", buf); 726 return (0); 727 } 728 /* find an estimate of how much we need for this var */ 729 j = 0; 730 i = sysctl(oid, nlen, 0, &j, 0, 0); 731 j += j; /* we want to be sure :-) */ 732 733 val = oval = malloc(j + 1); 734 if (val == NULL) { 735 warnx("malloc failed"); 736 return (1); 737 } 738 ctltype = (kind & CTLTYPE); 739 len = j; 740 i = sysctl(oid, nlen, val, &len, 0, 0); 741 if (i != 0 || (len == 0 && ctltype != CTLTYPE_STRING)) { 742 free(oval); 743 return (1); 744 } 745 746 if (bflag) { 747 fwrite(val, 1, len, stdout); 748 free(oval); 749 return (0); 750 } 751 val[len] = '\0'; 752 p = val; 753 sign = ctl_sign[ctltype]; 754 intlen = ctl_size[ctltype]; 755 756 switch (ctltype) { 757 case CTLTYPE_STRING: 758 if (!nflag) 759 printf("%s%s", name, sep); 760 printf("%.*s", (int)len, p); 761 free(oval); 762 return (0); 763 764 case CTLTYPE_INT: 765 case CTLTYPE_UINT: 766 case CTLTYPE_LONG: 767 case CTLTYPE_ULONG: 768 case CTLTYPE_S64: 769 case CTLTYPE_U64: 770 if (!nflag) 771 printf("%s%s", name, sep); 772 hexlen = 2 + (intlen * CHAR_BIT + 3) / 4; 773 sep1 = ""; 774 while (len >= intlen) { 775 switch (kind & CTLTYPE) { 776 case CTLTYPE_INT: 777 case CTLTYPE_UINT: 778 umv = *(u_int *)p; 779 mv = *(int *)p; 780 break; 781 case CTLTYPE_LONG: 782 case CTLTYPE_ULONG: 783 umv = *(u_long *)p; 784 mv = *(long *)p; 785 break; 786 case CTLTYPE_S64: 787 case CTLTYPE_U64: 788 umv = *(uint64_t *)p; 789 mv = *(int64_t *)p; 790 break; 791 } 792 fputs(sep1, stdout); 793 if (xflag) 794 printf("%#0*jx", hexlen, umv); 795 else if (!sign) 796 printf(hflag ? "%'ju" : "%ju", umv); 797 else if (fmt[1] == 'K') { 798 if (mv < 0) 799 printf("%jd", mv); 800 else 801 printf("%.1fC", (mv - 2732.0) / 10); 802 } else 803 printf(hflag ? "%'jd" : "%jd", mv); 804 sep1 = " "; 805 len -= intlen; 806 p += intlen; 807 } 808 free(oval); 809 return (0); 810 811 case CTLTYPE_OPAQUE: 812 i = 0; 813 if (strcmp(fmt, "S,clockinfo") == 0) 814 func = S_clockinfo; 815 else if (strcmp(fmt, "S,timeval") == 0) 816 func = S_timeval; 817 else if (strcmp(fmt, "S,loadavg") == 0) 818 func = S_loadavg; 819 else if (strcmp(fmt, "S,vmtotal") == 0) 820 func = S_vmtotal; 821 #if defined(__amd64__) || defined(__i386__) 822 else if (strcmp(fmt, "S,bios_smap_xattr") == 0) 823 func = S_bios_smap_xattr; 824 #endif 825 else 826 func = NULL; 827 if (func) { 828 if (!nflag) 829 printf("%s%s", name, sep); 830 i = (*func)(len, p); 831 free(oval); 832 return (i); 833 } 834 /* FALLTHROUGH */ 835 default: 836 if (!oflag && !xflag) { 837 free(oval); 838 return (1); 839 } 840 if (!nflag) 841 printf("%s%s", name, sep); 842 printf("Format:%s Length:%zu Dump:0x", fmt, len); 843 while (len-- && (xflag || p < val + 16)) 844 printf("%02x", *p++); 845 if (!xflag && len > 16) 846 printf("..."); 847 free(oval); 848 return (0); 849 } 850 free(oval); 851 return (1); 852 } 853 854 static int 855 sysctl_all(int *oid, int len) 856 { 857 int name1[22], name2[22]; 858 int i, j; 859 size_t l1, l2; 860 861 name1[0] = 0; 862 name1[1] = 2; 863 l1 = 2; 864 if (len) { 865 memcpy(name1+2, oid, len * sizeof(int)); 866 l1 += len; 867 } else { 868 name1[2] = 1; 869 l1++; 870 } 871 for (;;) { 872 l2 = sizeof(name2); 873 j = sysctl(name1, l1, name2, &l2, 0, 0); 874 if (j < 0) { 875 if (errno == ENOENT) 876 return (0); 877 else 878 err(1, "sysctl(getnext) %d %zu", j, l2); 879 } 880 881 l2 /= sizeof(int); 882 883 if (len < 0 || l2 < (unsigned int)len) 884 return (0); 885 886 for (i = 0; i < len; i++) 887 if (name2[i] != oid[i]) 888 return (0); 889 890 i = show_var(name2, l2); 891 if (!i && !bflag) 892 putchar('\n'); 893 894 memcpy(name1+2, name2, l2 * sizeof(int)); 895 l1 = 2 + l2; 896 } 897 } 898