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