1 /* 2 * Copyright (c) 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Copyright (C) 2017 THL A29 Limited, a Tencent company. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 4. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * Derived from FreeBSD's sbin/sysctl/sysctl.c. 33 */ 34 35 #ifndef lint 36 static const char copyright[] = 37 "@(#) Copyright (c) 1993\n\ 38 The Regents of the University of California. All rights reserved.\n"; 39 #endif /* not lint */ 40 41 #ifndef lint 42 #if 0 43 static char sccsid[] = "@(#)from: sysctl.c 8.1 (Berkeley) 6/6/93"; 44 #endif 45 static const char rcsid[] = 46 "$FreeBSD$"; 47 #endif /* not lint */ 48 49 #ifndef FSTACK 50 #include <sys/param.h> 51 #include <sys/time.h> 52 #include <sys/resource.h> 53 #include <sys/stat.h> 54 #include <sys/sysctl.h> 55 #include <sys/vmmeter.h> 56 57 #ifdef __amd64__ 58 #include <sys/efi.h> 59 #include <machine/metadata.h> 60 #endif 61 62 #if defined(__amd64__) || defined(__i386__) 63 #include <machine/pc/bios.h> 64 #endif 65 66 #endif 67 68 #include <assert.h> 69 #include <ctype.h> 70 #include <err.h> 71 #include <errno.h> 72 #include <inttypes.h> 73 #include <locale.h> 74 #include <stdio.h> 75 #include <stdlib.h> 76 #include <string.h> 77 #include <sysexits.h> 78 #include <unistd.h> 79 80 #ifdef FSTACK 81 #include <time.h> 82 #include <limits.h> 83 84 #include "sys/sysctl.h" 85 #include "ff_ipc.h" 86 87 struct clockinfo { 88 int hz; /* clock frequency */ 89 int tick; /* micro-seconds per hz tick */ 90 int spare; 91 int stathz; /* statistics clock frequency */ 92 int profhz; /* profiling clock frequency */ 93 }; 94 95 struct loadavg { 96 __uint32_t ldavg[3]; 97 long fscale; 98 }; 99 100 /* Structure extended to include extended attribute field in ACPI 3.0. */ 101 struct bios_smap_xattr { 102 u_int64_t base; 103 u_int64_t length; 104 u_int32_t type; 105 u_int32_t xattr; 106 } __packed; 107 108 /* systemwide totals computed every five seconds */ 109 struct vmtotal { 110 int16_t t_rq; /* length of the run queue */ 111 int16_t t_dw; /* jobs in ``disk wait'' (neg priority) */ 112 int16_t t_pw; /* jobs in page wait */ 113 int16_t t_sl; /* jobs sleeping in core */ 114 int16_t t_sw; /* swapped out runnable/short block jobs */ 115 int32_t t_vm; /* total virtual memory */ 116 int32_t t_avm; /* active virtual memory */ 117 int32_t t_rm; /* total real memory in use */ 118 int32_t t_arm; /* active real memory */ 119 int32_t t_vmshr; /* shared virtual memory */ 120 int32_t t_avmshr; /* active shared virtual memory */ 121 int32_t t_rmshr; /* shared real memory */ 122 int32_t t_armshr; /* active shared real memory */ 123 int32_t t_free; /* free memory pages */ 124 }; 125 126 struct efi_md { 127 uint32_t md_type; 128 #define EFI_MD_TYPE_NULL 0 129 #define EFI_MD_TYPE_CODE 1 /* Loader text. */ 130 #define EFI_MD_TYPE_DATA 2 /* Loader data. */ 131 #define EFI_MD_TYPE_BS_CODE 3 /* Boot services text. */ 132 #define EFI_MD_TYPE_BS_DATA 4 /* Boot services data. */ 133 #define EFI_MD_TYPE_RT_CODE 5 /* Runtime services text. */ 134 #define EFI_MD_TYPE_RT_DATA 6 /* Runtime services data. */ 135 #define EFI_MD_TYPE_FREE 7 /* Unused/free memory. */ 136 #define EFI_MD_TYPE_BAD 8 /* Bad memory */ 137 #define EFI_MD_TYPE_RECLAIM 9 /* ACPI reclaimable memory. */ 138 #define EFI_MD_TYPE_FIRMWARE 10 /* ACPI NV memory */ 139 #define EFI_MD_TYPE_IOMEM 11 /* Memory-mapped I/O. */ 140 #define EFI_MD_TYPE_IOPORT 12 /* I/O port space. */ 141 #define EFI_MD_TYPE_PALCODE 13 /* PAL */ 142 uint32_t __pad; 143 uint64_t md_phys; 144 void *md_virt; 145 uint64_t md_pages; 146 uint64_t md_attr; 147 #define EFI_MD_ATTR_UC 0x0000000000000001UL 148 #define EFI_MD_ATTR_WC 0x0000000000000002UL 149 #define EFI_MD_ATTR_WT 0x0000000000000004UL 150 #define EFI_MD_ATTR_WB 0x0000000000000008UL 151 #define EFI_MD_ATTR_UCE 0x0000000000000010UL 152 #define EFI_MD_ATTR_WP 0x0000000000001000UL 153 #define EFI_MD_ATTR_RP 0x0000000000002000UL 154 #define EFI_MD_ATTR_XP 0x0000000000004000UL 155 #define EFI_MD_ATTR_RT 0x8000000000000000UL 156 }; 157 158 struct efi_map_header { 159 uint64_t memory_size; 160 uint64_t descriptor_size; 161 uint32_t descriptor_version; 162 }; 163 164 #endif 165 166 static const char *conffile; 167 168 static int aflag, bflag, Bflag, dflag, eflag, hflag, iflag; 169 static int Nflag, nflag, oflag, qflag, tflag, Tflag, Wflag, xflag; 170 171 static int oidfmt(int *, int, char *, u_int *); 172 static int parsefile(const char *); 173 static int parse(const char *, int); 174 static int show_var(int *, int); 175 static int sysctl_all(int *oid, int len); 176 static int name2oid(const char *, int *); 177 178 static int strIKtoi(const char *, char **, const char *); 179 180 static int ctl_sign[CTLTYPE+1] = { 181 [CTLTYPE_INT] = 1, 182 [CTLTYPE_LONG] = 1, 183 [CTLTYPE_S8] = 1, 184 [CTLTYPE_S16] = 1, 185 [CTLTYPE_S32] = 1, 186 [CTLTYPE_S64] = 1, 187 }; 188 189 static int ctl_size[CTLTYPE+1] = { 190 [CTLTYPE_INT] = sizeof(int), 191 [CTLTYPE_UINT] = sizeof(u_int), 192 [CTLTYPE_LONG] = sizeof(long), 193 [CTLTYPE_ULONG] = sizeof(u_long), 194 [CTLTYPE_S8] = sizeof(int8_t), 195 [CTLTYPE_S16] = sizeof(int16_t), 196 [CTLTYPE_S32] = sizeof(int32_t), 197 [CTLTYPE_S64] = sizeof(int64_t), 198 [CTLTYPE_U8] = sizeof(uint8_t), 199 [CTLTYPE_U16] = sizeof(uint16_t), 200 [CTLTYPE_U32] = sizeof(uint32_t), 201 [CTLTYPE_U64] = sizeof(uint64_t), 202 }; 203 204 static const char *ctl_typename[CTLTYPE+1] = { 205 [CTLTYPE_INT] = "integer", 206 [CTLTYPE_UINT] = "unsigned integer", 207 [CTLTYPE_LONG] = "long integer", 208 [CTLTYPE_ULONG] = "unsigned long", 209 [CTLTYPE_U8] = "uint8_t", 210 [CTLTYPE_U16] = "uint16_t", 211 [CTLTYPE_U32] = "uint16_t", 212 [CTLTYPE_U64] = "uint64_t", 213 [CTLTYPE_S8] = "int8_t", 214 [CTLTYPE_S16] = "int16_t", 215 [CTLTYPE_S32] = "int32_t", 216 [CTLTYPE_S64] = "int64_t", 217 [CTLTYPE_NODE] = "node", 218 [CTLTYPE_STRING] = "string", 219 [CTLTYPE_OPAQUE] = "opaque", 220 }; 221 222 static void 223 usage(void) 224 { 225 226 #ifndef FSTACK 227 (void)fprintf(stderr, "%s\n%s\n", 228 "usage: sysctl [-bdehiNnoqTtWx] [ -B <bufsize> ] [-f filename] name[=value] ...", 229 " sysctl [-bdehNnoqTtWx] [ -B <bufsize> ] -a"); 230 #else 231 (void)fprintf(stderr, "%s\n%s\n", 232 "usage: sysctl -p <f-stack proc_id> [-bdehiNnoqTtWx] [ -B <bufsize> ] [-f filename] name[=value] ...", 233 " sysctl -p <f-stack proc_id> [-bdehNnoqTtWx] [ -B <bufsize> ] -a"); 234 #endif 235 exit(1); 236 } 237 238 int 239 main(int argc, char **argv) 240 { 241 int ch; 242 int warncount = 0; 243 244 setlocale(LC_NUMERIC, ""); 245 setbuf(stdout,0); 246 setbuf(stderr,0); 247 248 #ifndef FSTACK 249 while ((ch = getopt(argc, argv, "AabB:def:hiNnoqtTwWxX")) != -1) { 250 #else 251 while ((ch = getopt(argc, argv, "AabB:def:hiNnoqtTwWxXp:")) != -1) { 252 #endif 253 switch (ch) { 254 case 'A': 255 /* compatibility */ 256 aflag = oflag = 1; 257 break; 258 case 'a': 259 aflag = 1; 260 break; 261 case 'b': 262 bflag = 1; 263 break; 264 case 'B': 265 Bflag = strtol(optarg, NULL, 0); 266 break; 267 case 'd': 268 dflag = 1; 269 break; 270 case 'e': 271 eflag = 1; 272 break; 273 case 'f': 274 conffile = optarg; 275 break; 276 case 'h': 277 hflag = 1; 278 break; 279 case 'i': 280 iflag = 1; 281 break; 282 case 'N': 283 Nflag = 1; 284 break; 285 case 'n': 286 nflag = 1; 287 break; 288 case 'o': 289 oflag = 1; 290 break; 291 case 'q': 292 qflag = 1; 293 break; 294 case 't': 295 tflag = 1; 296 break; 297 case 'T': 298 Tflag = 1; 299 break; 300 case 'w': 301 /* compatibility */ 302 /* ignored */ 303 break; 304 case 'W': 305 Wflag = 1; 306 break; 307 case 'X': 308 /* compatibility */ 309 aflag = xflag = 1; 310 break; 311 case 'x': 312 xflag = 1; 313 break; 314 #ifdef FSTACK 315 case 'p': 316 ff_set_proc_id(atoi(optarg)); 317 break; 318 #endif 319 default: 320 usage(); 321 } 322 } 323 argc -= optind; 324 argv += optind; 325 326 if (Nflag && nflag) 327 usage(); 328 if (aflag && argc == 0) 329 exit(sysctl_all(0, 0)); 330 if (argc == 0 && conffile == NULL) 331 usage(); 332 333 warncount = 0; 334 if (conffile != NULL) 335 warncount += parsefile(conffile); 336 337 while (argc-- > 0) 338 warncount += parse(*argv++, 0); 339 340 return (warncount); 341 } 342 343 /* 344 * Parse a name into a MIB entry. 345 * Lookup and print out the MIB entry if it exists. 346 * Set a new value if requested. 347 */ 348 static int 349 parse(const char *string, int lineno) 350 { 351 int len, i, j; 352 const void *newval; 353 const char *newvalstr = NULL; 354 int8_t i8val; 355 uint8_t u8val; 356 int16_t i16val; 357 uint16_t u16val; 358 int32_t i32val; 359 uint32_t u32val; 360 int intval; 361 unsigned int uintval; 362 long longval; 363 unsigned long ulongval; 364 size_t newsize = Bflag; 365 int64_t i64val; 366 uint64_t u64val; 367 int mib[CTL_MAXNAME]; 368 char *cp, *bufp, buf[BUFSIZ], *endptr = NULL, fmt[BUFSIZ], line[BUFSIZ]; 369 u_int kind; 370 371 if (lineno) 372 snprintf(line, sizeof(line), " at line %d", lineno); 373 else 374 line[0] = '\0'; 375 376 cp = buf; 377 if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ) { 378 warnx("oid too long: '%s'%s", string, line); 379 return (1); 380 } 381 bufp = strsep(&cp, "=:"); 382 if (cp != NULL) { 383 /* Tflag just lists tunables, do not allow assignment */ 384 if (Tflag || Wflag) { 385 warnx("Can't set variables when using -T or -W"); 386 usage(); 387 } 388 while (isspace(*cp)) 389 cp++; 390 /* Strip a pair of " or ' if any. */ 391 switch (*cp) { 392 case '\"': 393 case '\'': 394 if (cp[strlen(cp) - 1] == *cp) 395 cp[strlen(cp) - 1] = '\0'; 396 cp++; 397 } 398 newvalstr = cp; 399 newsize = strlen(cp); 400 } 401 /* Trim spaces */ 402 cp = bufp + strlen(bufp) - 1; 403 while (cp >= bufp && isspace((int)*cp)) { 404 *cp = '\0'; 405 cp--; 406 } 407 len = name2oid(bufp, mib); 408 409 if (len < 0) { 410 if (iflag) 411 return (0); 412 if (qflag) 413 return (1); 414 else { 415 if (errno == ENOENT) { 416 warnx("unknown oid '%s'%s", bufp, line); 417 } else { 418 warn("unknown oid '%s'%s", bufp, line); 419 } 420 return (1); 421 } 422 } 423 424 if (oidfmt(mib, len, fmt, &kind)) { 425 warn("couldn't find format of oid '%s'%s", bufp, line); 426 if (iflag) 427 return (1); 428 else 429 exit(1); 430 } 431 432 if (newvalstr == NULL || dflag) { 433 if ((kind & CTLTYPE) == CTLTYPE_NODE) { 434 if (dflag) { 435 i = show_var(mib, len); 436 if (!i && !bflag) 437 putchar('\n'); 438 } 439 sysctl_all(mib, len); 440 } else { 441 i = show_var(mib, len); 442 if (!i && !bflag) 443 putchar('\n'); 444 } 445 } else { 446 if ((kind & CTLTYPE) == CTLTYPE_NODE) { 447 warnx("oid '%s' isn't a leaf node%s", bufp, line); 448 return (1); 449 } 450 451 if (!(kind & CTLFLAG_WR)) { 452 if (kind & CTLFLAG_TUN) { 453 warnx("oid '%s' is a read only tunable%s", bufp, line); 454 warnx("Tunable values are set in /boot/loader.conf"); 455 } else 456 warnx("oid '%s' is read only%s", bufp, line); 457 return (1); 458 } 459 460 switch (kind & CTLTYPE) { 461 case CTLTYPE_INT: 462 case CTLTYPE_UINT: 463 case CTLTYPE_LONG: 464 case CTLTYPE_ULONG: 465 case CTLTYPE_S8: 466 case CTLTYPE_S16: 467 case CTLTYPE_S32: 468 case CTLTYPE_S64: 469 case CTLTYPE_U8: 470 case CTLTYPE_U16: 471 case CTLTYPE_U32: 472 case CTLTYPE_U64: 473 if (strlen(newvalstr) == 0) { 474 warnx("empty numeric value"); 475 return (1); 476 } 477 /* FALLTHROUGH */ 478 case CTLTYPE_STRING: 479 break; 480 default: 481 warnx("oid '%s' is type %d," 482 " cannot set that%s", bufp, 483 kind & CTLTYPE, line); 484 return (1); 485 } 486 487 errno = 0; 488 489 switch (kind & CTLTYPE) { 490 case CTLTYPE_INT: 491 if (strncmp(fmt, "IK", 2) == 0) 492 intval = strIKtoi(newvalstr, &endptr, fmt); 493 else 494 intval = (int)strtol(newvalstr, &endptr, 495 0); 496 newval = &intval; 497 newsize = sizeof(intval); 498 break; 499 case CTLTYPE_UINT: 500 uintval = (int) strtoul(newvalstr, &endptr, 0); 501 newval = &uintval; 502 newsize = sizeof(uintval); 503 break; 504 case CTLTYPE_LONG: 505 longval = strtol(newvalstr, &endptr, 0); 506 newval = &longval; 507 newsize = sizeof(longval); 508 break; 509 case CTLTYPE_ULONG: 510 ulongval = strtoul(newvalstr, &endptr, 0); 511 newval = &ulongval; 512 newsize = sizeof(ulongval); 513 break; 514 case CTLTYPE_STRING: 515 newval = newvalstr; 516 break; 517 case CTLTYPE_S8: 518 i8val = (int8_t)strtol(newvalstr, &endptr, 0); 519 newval = &i8val; 520 newsize = sizeof(i8val); 521 break; 522 case CTLTYPE_S16: 523 i16val = (int16_t)strtol(newvalstr, &endptr, 524 0); 525 newval = &i16val; 526 newsize = sizeof(i16val); 527 break; 528 case CTLTYPE_S32: 529 i32val = (int32_t)strtol(newvalstr, &endptr, 530 0); 531 newval = &i32val; 532 newsize = sizeof(i32val); 533 break; 534 case CTLTYPE_S64: 535 i64val = strtoimax(newvalstr, &endptr, 0); 536 newval = &i64val; 537 newsize = sizeof(i64val); 538 break; 539 case CTLTYPE_U8: 540 u8val = (uint8_t)strtoul(newvalstr, &endptr, 0); 541 newval = &u8val; 542 newsize = sizeof(u8val); 543 break; 544 case CTLTYPE_U16: 545 u16val = (uint16_t)strtoul(newvalstr, &endptr, 546 0); 547 newval = &u16val; 548 newsize = sizeof(u16val); 549 break; 550 case CTLTYPE_U32: 551 u32val = (uint32_t)strtoul(newvalstr, &endptr, 552 0); 553 newval = &u32val; 554 newsize = sizeof(u32val); 555 break; 556 case CTLTYPE_U64: 557 u64val = strtoumax(newvalstr, &endptr, 0); 558 newval = &u64val; 559 newsize = sizeof(u64val); 560 break; 561 default: 562 /* NOTREACHED */ 563 abort(); 564 } 565 566 if (errno != 0 || endptr == newvalstr || 567 (endptr != NULL && *endptr != '\0')) { 568 warnx("invalid %s '%s'%s", ctl_typename[kind & CTLTYPE], 569 newvalstr, line); 570 return (1); 571 } 572 573 i = show_var(mib, len); 574 if (sysctl(mib, len, 0, 0, newval, newsize) == -1) { 575 if (!i && !bflag) 576 putchar('\n'); 577 switch (errno) { 578 case EOPNOTSUPP: 579 warnx("%s: value is not available%s", 580 string, line); 581 return (1); 582 case ENOTDIR: 583 warnx("%s: specification is incomplete%s", 584 string, line); 585 return (1); 586 case ENOMEM: 587 warnx("%s: type is unknown to this program%s", 588 string, line); 589 return (1); 590 default: 591 warn("%s%s", string, line); 592 return (1); 593 } 594 } 595 if (!bflag) 596 printf(" -> "); 597 i = nflag; 598 nflag = 1; 599 j = show_var(mib, len); 600 if (!j && !bflag) 601 putchar('\n'); 602 nflag = i; 603 } 604 605 return (0); 606 } 607 608 static int 609 parsefile(const char *filename) 610 { 611 FILE *file; 612 char line[BUFSIZ], *p, *pq, *pdq; 613 int warncount = 0, lineno = 0; 614 615 file = fopen(filename, "r"); 616 if (file == NULL) 617 err(EX_NOINPUT, "%s", filename); 618 while (fgets(line, sizeof(line), file) != NULL) { 619 lineno++; 620 p = line; 621 pq = strchr(line, '\''); 622 pdq = strchr(line, '\"'); 623 /* Replace the first # with \0. */ 624 while((p = strchr(p, '#')) != NULL) { 625 if (pq != NULL && p > pq) { 626 if ((p = strchr(pq+1, '\'')) != NULL) 627 *(++p) = '\0'; 628 break; 629 } else if (pdq != NULL && p > pdq) { 630 if ((p = strchr(pdq+1, '\"')) != NULL) 631 *(++p) = '\0'; 632 break; 633 } else if (p == line || *(p-1) != '\\') { 634 *p = '\0'; 635 break; 636 } 637 p++; 638 } 639 /* Trim spaces */ 640 p = line + strlen(line) - 1; 641 while (p >= line && isspace((int)*p)) { 642 *p = '\0'; 643 p--; 644 } 645 p = line; 646 while (isspace((int)*p)) 647 p++; 648 if (*p == '\0') 649 continue; 650 else 651 warncount += parse(p, lineno); 652 } 653 fclose(file); 654 655 return (warncount); 656 } 657 658 /* These functions will dump out various interesting structures. */ 659 660 static int 661 S_clockinfo(size_t l2, void *p) 662 { 663 struct clockinfo *ci = (struct clockinfo*)p; 664 665 if (l2 != sizeof(*ci)) { 666 warnx("S_clockinfo %zu != %zu", l2, sizeof(*ci)); 667 return (1); 668 } 669 printf(hflag ? "{ hz = %'d, tick = %'d, profhz = %'d, stathz = %'d }" : 670 "{ hz = %d, tick = %d, profhz = %d, stathz = %d }", 671 ci->hz, ci->tick, ci->profhz, ci->stathz); 672 return (0); 673 } 674 675 static int 676 S_loadavg(size_t l2, void *p) 677 { 678 struct loadavg *tv = (struct loadavg*)p; 679 680 if (l2 != sizeof(*tv)) { 681 warnx("S_loadavg %zu != %zu", l2, sizeof(*tv)); 682 return (1); 683 } 684 printf(hflag ? "{ %'.2f %'.2f %'.2f }" : "{ %.2f %.2f %.2f }", 685 (double)tv->ldavg[0]/(double)tv->fscale, 686 (double)tv->ldavg[1]/(double)tv->fscale, 687 (double)tv->ldavg[2]/(double)tv->fscale); 688 return (0); 689 } 690 691 static int 692 S_timeval(size_t l2, void *p) 693 { 694 struct timeval *tv = (struct timeval*)p; 695 time_t tv_sec; 696 char *p1, *p2; 697 698 if (l2 != sizeof(*tv)) { 699 warnx("S_timeval %zu != %zu", l2, sizeof(*tv)); 700 return (1); 701 } 702 printf(hflag ? "{ sec = %'jd, usec = %'ld } " : 703 "{ sec = %jd, usec = %ld } ", 704 (intmax_t)tv->tv_sec, tv->tv_usec); 705 tv_sec = tv->tv_sec; 706 p1 = strdup(ctime(&tv_sec)); 707 for (p2=p1; *p2 ; p2++) 708 if (*p2 == '\n') 709 *p2 = '\0'; 710 fputs(p1, stdout); 711 free(p1); 712 return (0); 713 } 714 715 static int 716 S_vmtotal(size_t l2, void *p) 717 { 718 struct vmtotal *v = (struct vmtotal *)p; 719 int pageKilo = getpagesize() / 1024; 720 721 if (l2 != sizeof(*v)) { 722 warnx("S_vmtotal %zu != %zu", l2, sizeof(*v)); 723 return (1); 724 } 725 726 printf( 727 "\nSystem wide totals computed every five seconds:" 728 " (values in kilobytes)\n"); 729 printf("===============================================\n"); 730 printf( 731 "Processes:\t\t(RUNQ: %hd Disk Wait: %hd Page Wait: " 732 "%hd Sleep: %hd)\n", 733 v->t_rq, v->t_dw, v->t_pw, v->t_sl); 734 printf( 735 "Virtual Memory:\t\t(Total: %jdK Active: %jdK)\n", 736 (intmax_t)v->t_vm * pageKilo, (intmax_t)v->t_avm * pageKilo); 737 printf("Real Memory:\t\t(Total: %jdK Active: %jdK)\n", 738 (intmax_t)v->t_rm * pageKilo, (intmax_t)v->t_arm * pageKilo); 739 printf("Shared Virtual Memory:\t(Total: %jdK Active: %jdK)\n", 740 (intmax_t)v->t_vmshr * pageKilo, (intmax_t)v->t_avmshr * pageKilo); 741 printf("Shared Real Memory:\t(Total: %jdK Active: %jdK)\n", 742 (intmax_t)v->t_rmshr * pageKilo, (intmax_t)v->t_armshr * pageKilo); 743 printf("Free Memory:\t%jdK", (intmax_t)v->t_free * pageKilo); 744 745 return (0); 746 } 747 748 #ifdef __amd64__ 749 #define efi_next_descriptor(ptr, size) \ 750 ((struct efi_md *)(((uint8_t *) ptr) + size)) 751 752 static int 753 S_efi_map(size_t l2, void *p) 754 { 755 struct efi_map_header *efihdr; 756 struct efi_md *map; 757 const char *type; 758 size_t efisz; 759 int ndesc, i; 760 761 static const char *types[] = { 762 "Reserved", 763 "LoaderCode", 764 "LoaderData", 765 "BootServicesCode", 766 "BootServicesData", 767 "RuntimeServicesCode", 768 "RuntimeServicesData", 769 "ConventionalMemory", 770 "UnusableMemory", 771 "ACPIReclaimMemory", 772 "ACPIMemoryNVS", 773 "MemoryMappedIO", 774 "MemoryMappedIOPortSpace", 775 "PalCode" 776 }; 777 778 /* 779 * Memory map data provided by UEFI via the GetMemoryMap 780 * Boot Services API. 781 */ 782 if (l2 < sizeof(*efihdr)) { 783 warnx("S_efi_map length less than header"); 784 return (1); 785 } 786 efihdr = p; 787 efisz = (sizeof(struct efi_map_header) + 0xf) & ~0xf; 788 map = (struct efi_md *)((uint8_t *)efihdr + efisz); 789 790 if (efihdr->descriptor_size == 0) 791 return (0); 792 if (l2 != efisz + efihdr->memory_size) { 793 warnx("S_efi_map length mismatch %zu vs %zu", l2, efisz + 794 efihdr->memory_size); 795 return (1); 796 } 797 ndesc = efihdr->memory_size / efihdr->descriptor_size; 798 799 printf("\n%23s %12s %12s %8s %4s", 800 "Type", "Physical", "Virtual", "#Pages", "Attr"); 801 802 for (i = 0; i < ndesc; i++, 803 map = efi_next_descriptor(map, efihdr->descriptor_size)) { 804 if (map->md_type <= EFI_MD_TYPE_PALCODE) 805 type = types[map->md_type]; 806 else 807 type = "<INVALID>"; 808 printf("\n%23s %012lx %12p %08lx ", type, map->md_phys, 809 map->md_virt, map->md_pages); 810 if (map->md_attr & EFI_MD_ATTR_UC) 811 printf("UC "); 812 if (map->md_attr & EFI_MD_ATTR_WC) 813 printf("WC "); 814 if (map->md_attr & EFI_MD_ATTR_WT) 815 printf("WT "); 816 if (map->md_attr & EFI_MD_ATTR_WB) 817 printf("WB "); 818 if (map->md_attr & EFI_MD_ATTR_UCE) 819 printf("UCE "); 820 if (map->md_attr & EFI_MD_ATTR_WP) 821 printf("WP "); 822 if (map->md_attr & EFI_MD_ATTR_RP) 823 printf("RP "); 824 if (map->md_attr & EFI_MD_ATTR_XP) 825 printf("XP "); 826 if (map->md_attr & EFI_MD_ATTR_RT) 827 printf("RUNTIME"); 828 } 829 return (0); 830 } 831 #endif 832 833 #if defined(__amd64__) || defined(__i386__) 834 static int 835 S_bios_smap_xattr(size_t l2, void *p) 836 { 837 struct bios_smap_xattr *smap, *end; 838 839 if (l2 % sizeof(*smap) != 0) { 840 warnx("S_bios_smap_xattr %zu is not a multiple of %zu", l2, 841 sizeof(*smap)); 842 return (1); 843 } 844 845 end = (struct bios_smap_xattr *)((char *)p + l2); 846 for (smap = p; smap < end; smap++) 847 printf("\nSMAP type=%02x, xattr=%02x, base=%016jx, len=%016jx", 848 smap->type, smap->xattr, (uintmax_t)smap->base, 849 (uintmax_t)smap->length); 850 return (0); 851 } 852 #endif 853 854 static int 855 strIKtoi(const char *str, char **endptrp, const char *fmt) 856 { 857 int kelv; 858 float temp; 859 size_t len; 860 const char *p; 861 int prec, i; 862 863 assert(errno == 0); 864 865 len = strlen(str); 866 /* caller already checked this */ 867 assert(len > 0); 868 869 /* 870 * A format of "IK" is in deciKelvin. A format of "IK3" is in 871 * milliKelvin. The single digit following IK is log10 of the 872 * multiplying factor to convert Kelvin into the untis of this sysctl, 873 * or the dividing factor to convert the sysctl value to Kelvin. Numbers 874 * larger than 6 will run into precision issues with 32-bit integers. 875 * Characters that aren't ASCII digits after the 'K' are ignored. No 876 * localization is present because this is an interface from the kernel 877 * to this program (eg not an end-user interface), so isdigit() isn't 878 * used here. 879 */ 880 if (fmt[2] != '\0' && fmt[2] >= '0' && fmt[2] <= '9') 881 prec = fmt[2] - '0'; 882 else 883 prec = 1; 884 p = &str[len - 1]; 885 if (*p == 'C' || *p == 'F' || *p == 'K') { 886 temp = strtof(str, endptrp); 887 if (*endptrp != str && *endptrp == p && errno == 0) { 888 if (*p == 'F') 889 temp = (temp - 32) * 5 / 9; 890 *endptrp = NULL; 891 if (*p != 'K') 892 temp += 273.15; 893 for (i = 0; i < prec; i++) 894 temp *= 10.0; 895 return ((int)(temp + 0.5)); 896 } 897 } else { 898 /* No unit specified -> treat it as a raw number */ 899 kelv = (int)strtol(str, endptrp, 10); 900 if (*endptrp != str && *endptrp == p && errno == 0) { 901 *endptrp = NULL; 902 return (kelv); 903 } 904 } 905 906 errno = ERANGE; 907 return (0); 908 } 909 910 /* 911 * These functions uses a presently undocumented interface to the kernel 912 * to walk the tree and get the type so it can print the value. 913 * This interface is under work and consideration, and should probably 914 * be killed with a big axe by the first person who can find the time. 915 * (be aware though, that the proper interface isn't as obvious as it 916 * may seem, there are various conflicting requirements. 917 */ 918 919 static int 920 name2oid(const char *name, int *oidp) 921 { 922 int oid[2]; 923 int i; 924 size_t j; 925 926 oid[0] = 0; 927 oid[1] = 3; 928 929 j = CTL_MAXNAME * sizeof(int); 930 i = sysctl(oid, 2, oidp, &j, name, strlen(name)); 931 if (i < 0) 932 return (i); 933 j /= sizeof(int); 934 return (j); 935 } 936 937 static int 938 oidfmt(int *oid, int len, char *fmt, u_int *kind) 939 { 940 int qoid[CTL_MAXNAME+2]; 941 u_char buf[BUFSIZ]; 942 int i; 943 size_t j; 944 945 qoid[0] = 0; 946 qoid[1] = 4; 947 memcpy(qoid + 2, oid, len * sizeof(int)); 948 949 j = sizeof(buf); 950 i = sysctl(qoid, len + 2, buf, &j, 0, 0); 951 if (i) 952 err(1, "sysctl fmt %d %zu %d", i, j, errno); 953 954 if (kind) 955 *kind = *(u_int *)buf; 956 957 if (fmt) 958 strcpy(fmt, (char *)(buf + sizeof(u_int))); 959 return (0); 960 } 961 962 /* 963 * This formats and outputs the value of one variable 964 * 965 * Returns zero if anything was actually output. 966 * Returns one if didn't know what to do with this. 967 * Return minus one if we had errors. 968 */ 969 static int 970 show_var(int *oid, int nlen) 971 { 972 u_char buf[BUFSIZ], *val, *oval, *p; 973 char name[BUFSIZ], fmt[BUFSIZ]; 974 const char *sep, *sep1, *prntype; 975 int qoid[CTL_MAXNAME+2]; 976 uintmax_t umv; 977 intmax_t mv; 978 int i, hexlen, sign, ctltype; 979 size_t intlen; 980 size_t j, len; 981 u_int kind; 982 float base; 983 int (*func)(size_t, void *); 984 int prec; 985 986 /* Silence GCC. */ 987 umv = mv = intlen = 0; 988 989 bzero(buf, BUFSIZ); 990 bzero(fmt, BUFSIZ); 991 bzero(name, BUFSIZ); 992 qoid[0] = 0; 993 memcpy(qoid + 2, oid, nlen * sizeof(int)); 994 995 qoid[1] = 1; 996 j = sizeof(name); 997 i = sysctl(qoid, nlen + 2, name, &j, 0, 0); 998 if (i || !j) 999 err(1, "sysctl name %d %zu %d", i, j, errno); 1000 1001 oidfmt(oid, nlen, fmt, &kind); 1002 /* if Wflag then only list sysctls that are writeable and not stats. */ 1003 if (Wflag && ((kind & CTLFLAG_WR) == 0 || (kind & CTLFLAG_STATS) != 0)) 1004 return 1; 1005 1006 /* if Tflag then only list sysctls that are tuneables. */ 1007 if (Tflag && (kind & CTLFLAG_TUN) == 0) 1008 return 1; 1009 1010 if (Nflag) { 1011 printf("%s", name); 1012 return (0); 1013 } 1014 1015 if (eflag) 1016 sep = "="; 1017 else 1018 sep = ": "; 1019 1020 ctltype = (kind & CTLTYPE); 1021 if (tflag || dflag) { 1022 if (!nflag) 1023 printf("%s%s", name, sep); 1024 if (ctl_typename[ctltype] != NULL) 1025 prntype = ctl_typename[ctltype]; 1026 else 1027 prntype = "unknown"; 1028 if (tflag && dflag) 1029 printf("%s%s", prntype, sep); 1030 else if (tflag) { 1031 printf("%s", prntype); 1032 return (0); 1033 } 1034 qoid[1] = 5; 1035 j = sizeof(buf); 1036 i = sysctl(qoid, nlen + 2, buf, &j, 0, 0); 1037 printf("%s", buf); 1038 return (0); 1039 } 1040 /* find an estimate of how much we need for this var */ 1041 if (Bflag) 1042 j = Bflag; 1043 else { 1044 j = 0; 1045 i = sysctl(oid, nlen, 0, &j, 0, 0); 1046 j += j; /* we want to be sure :-) */ 1047 } 1048 1049 val = oval = malloc(j + 1); 1050 if (val == NULL) { 1051 warnx("malloc failed"); 1052 return (1); 1053 } 1054 len = j; 1055 i = sysctl(oid, nlen, val, &len, 0, 0); 1056 if (i != 0 || (len == 0 && ctltype != CTLTYPE_STRING)) { 1057 free(oval); 1058 return (1); 1059 } 1060 1061 if (bflag) { 1062 fwrite(val, 1, len, stdout); 1063 free(oval); 1064 return (0); 1065 } 1066 val[len] = '\0'; 1067 p = val; 1068 sign = ctl_sign[ctltype]; 1069 intlen = ctl_size[ctltype]; 1070 1071 switch (ctltype) { 1072 case CTLTYPE_STRING: 1073 if (!nflag) 1074 printf("%s%s", name, sep); 1075 printf("%.*s", (int)len, p); 1076 free(oval); 1077 return (0); 1078 1079 case CTLTYPE_INT: 1080 case CTLTYPE_UINT: 1081 case CTLTYPE_LONG: 1082 case CTLTYPE_ULONG: 1083 case CTLTYPE_S8: 1084 case CTLTYPE_S16: 1085 case CTLTYPE_S32: 1086 case CTLTYPE_S64: 1087 case CTLTYPE_U8: 1088 case CTLTYPE_U16: 1089 case CTLTYPE_U32: 1090 case CTLTYPE_U64: 1091 if (!nflag) 1092 printf("%s%s", name, sep); 1093 hexlen = 2 + (intlen * CHAR_BIT + 3) / 4; 1094 sep1 = ""; 1095 while (len >= intlen) { 1096 switch (kind & CTLTYPE) { 1097 case CTLTYPE_INT: 1098 case CTLTYPE_UINT: 1099 umv = *(u_int *)p; 1100 mv = *(int *)p; 1101 break; 1102 case CTLTYPE_LONG: 1103 case CTLTYPE_ULONG: 1104 umv = *(u_long *)p; 1105 mv = *(long *)p; 1106 break; 1107 case CTLTYPE_S8: 1108 case CTLTYPE_U8: 1109 umv = *(uint8_t *)p; 1110 mv = *(int8_t *)p; 1111 break; 1112 case CTLTYPE_S16: 1113 case CTLTYPE_U16: 1114 umv = *(uint16_t *)p; 1115 mv = *(int16_t *)p; 1116 break; 1117 case CTLTYPE_S32: 1118 case CTLTYPE_U32: 1119 umv = *(uint32_t *)p; 1120 mv = *(int32_t *)p; 1121 break; 1122 case CTLTYPE_S64: 1123 case CTLTYPE_U64: 1124 umv = *(uint64_t *)p; 1125 mv = *(int64_t *)p; 1126 break; 1127 } 1128 fputs(sep1, stdout); 1129 if (xflag) 1130 printf("%#0*jx", hexlen, umv); 1131 else if (!sign) 1132 printf(hflag ? "%'ju" : "%ju", umv); 1133 else if (fmt[1] == 'K') { 1134 if (mv < 0) 1135 printf("%jd", mv); 1136 else { 1137 /* 1138 * See strIKtoi for details on fmt. 1139 */ 1140 prec = 1; 1141 if (fmt[2] != '\0') 1142 prec = fmt[2] - '0'; 1143 base = 1.0; 1144 for (int i = 0; i < prec; i++) 1145 base *= 10.0; 1146 printf("%.*fC", prec, 1147 (float)mv / base - 273.15); 1148 } 1149 } else 1150 printf(hflag ? "%'jd" : "%jd", mv); 1151 sep1 = " "; 1152 len -= intlen; 1153 p += intlen; 1154 } 1155 free(oval); 1156 return (0); 1157 1158 case CTLTYPE_OPAQUE: 1159 i = 0; 1160 if (strcmp(fmt, "S,clockinfo") == 0) 1161 func = S_clockinfo; 1162 else if (strcmp(fmt, "S,timeval") == 0) 1163 func = S_timeval; 1164 else if (strcmp(fmt, "S,loadavg") == 0) 1165 func = S_loadavg; 1166 else if (strcmp(fmt, "S,vmtotal") == 0) 1167 func = S_vmtotal; 1168 #ifdef __amd64__ 1169 else if (strcmp(fmt, "S,efi_map_header") == 0) 1170 func = S_efi_map; 1171 #endif 1172 #if defined(__amd64__) || defined(__i386__) 1173 else if (strcmp(fmt, "S,bios_smap_xattr") == 0) 1174 func = S_bios_smap_xattr; 1175 #endif 1176 else 1177 func = NULL; 1178 if (func) { 1179 if (!nflag) 1180 printf("%s%s", name, sep); 1181 i = (*func)(len, p); 1182 free(oval); 1183 return (i); 1184 } 1185 /* FALLTHROUGH */ 1186 default: 1187 if (!oflag && !xflag) { 1188 free(oval); 1189 return (1); 1190 } 1191 if (!nflag) 1192 printf("%s%s", name, sep); 1193 printf("Format:%s Length:%zu Dump:0x", fmt, len); 1194 while (len-- && (xflag || p < val + 16)) 1195 printf("%02x", *p++); 1196 if (!xflag && len > 16) 1197 printf("..."); 1198 free(oval); 1199 return (0); 1200 } 1201 free(oval); 1202 return (1); 1203 } 1204 1205 static int 1206 sysctl_all(int *oid, int len) 1207 { 1208 int name1[22], name2[22]; 1209 int i, j; 1210 size_t l1, l2; 1211 1212 name1[0] = 0; 1213 name1[1] = 2; 1214 l1 = 2; 1215 if (len) { 1216 memcpy(name1+2, oid, len * sizeof(int)); 1217 l1 += len; 1218 } else { 1219 name1[2] = 1; 1220 l1++; 1221 } 1222 for (;;) { 1223 l2 = sizeof(name2); 1224 j = sysctl(name1, l1, name2, &l2, 0, 0); 1225 if (j < 0) { 1226 if (errno == ENOENT) 1227 return (0); 1228 else 1229 err(1, "sysctl(getnext) %d %zu", j, l2); 1230 } 1231 1232 l2 /= sizeof(int); 1233 1234 if (len < 0 || l2 < (unsigned int)len) 1235 return (0); 1236 1237 for (i = 0; i < len; i++) 1238 if (name2[i] != oid[i]) 1239 return (0); 1240 1241 i = show_var(name2, l2); 1242 if (!i && !bflag) 1243 putchar('\n'); 1244 1245 memcpy(name1+2, name2, l2 * sizeof(int)); 1246 l1 = 2 + l2; 1247 } 1248 } 1249