11553Srgrimes/* 21553Srgrimes * Copyright (c) 1993 31553Srgrimes * The Regents of the University of California. All rights reserved. 41553Srgrimes * 51553Srgrimes * Redistribution and use in source and binary forms, with or without 61553Srgrimes * modification, are permitted provided that the following conditions 71553Srgrimes * are met: 81553Srgrimes * 1. Redistributions of source code must retain the above copyright 91553Srgrimes * notice, this list of conditions and the following disclaimer. 101553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111553Srgrimes * notice, this list of conditions and the following disclaimer in the 121553Srgrimes * documentation and/or other materials provided with the distribution. 131553Srgrimes * 4. Neither the name of the University nor the names of its contributors 141553Srgrimes * may be used to endorse or promote products derived from this software 151553Srgrimes * without specific prior written permission. 161553Srgrimes * 171553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201553Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271553Srgrimes * SUCH DAMAGE. 281553Srgrimes */ 291553Srgrimes 301553Srgrimes#ifndef lint 3130602Scharnierstatic const char copyright[] = 321553Srgrimes"@(#) Copyright (c) 1993\n\ 331553Srgrimes The Regents of the University of California. All rights reserved.\n"; 341553Srgrimes#endif /* not lint */ 351553Srgrimes 361553Srgrimes#ifndef lint 3730602Scharnier#if 0 3830602Scharnierstatic char sccsid[] = "@(#)from: sysctl.c 8.1 (Berkeley) 6/6/93"; 3930602Scharnier#endif 406284Swollmanstatic const char rcsid[] = 4150476Speter "$FreeBSD: releng/10.3/sbin/sysctl/sysctl.c 289292 2015-10-14 06:31:49Z bapt $"; 421553Srgrimes#endif /* not lint */ 431553Srgrimes 4491217Sbde#include <sys/param.h> 4591217Sbde#include <sys/time.h> 4691217Sbde#include <sys/resource.h> 471553Srgrimes#include <sys/stat.h> 481553Srgrimes#include <sys/sysctl.h> 49109097Sdillon#include <sys/vmmeter.h> 501553Srgrimes 51272913Sjhb#ifdef __amd64__ 52272913Sjhb#include <sys/efi.h> 53272913Sjhb#include <machine/metadata.h> 54272913Sjhb#endif 55272913Sjhb 56272913Sjhb#if defined(__amd64__) || defined(__i386__) 57272913Sjhb#include <machine/pc/bios.h> 58272913Sjhb#endif 59272913Sjhb 6030602Scharnier#include <ctype.h> 6130602Scharnier#include <err.h> 621553Srgrimes#include <errno.h> 63170287Sdwmalone#include <inttypes.h> 64122233Sdes#include <locale.h> 651553Srgrimes#include <stdio.h> 661553Srgrimes#include <stdlib.h> 671553Srgrimes#include <string.h> 68244198Sdelphij#include <sysexits.h> 6930602Scharnier#include <unistd.h> 701553Srgrimes 71244198Sdelphijstatic const char *conffile; 72244198Sdelphij 73203310Sgavinstatic int aflag, bflag, dflag, eflag, hflag, iflag; 74244198Sdelphijstatic int Nflag, nflag, oflag, qflag, Tflag, Wflag, xflag; 751553Srgrimes 7612946Sphkstatic int oidfmt(int *, int, char *, u_int *); 77244198Sdelphijstatic int parsefile(const char *); 78244198Sdelphijstatic int parse(const char *, int); 7912946Sphkstatic int show_var(int *, int); 80170512Sdwmalonestatic int sysctl_all(int *oid, int len); 81275485Sdelphijstatic int name2oid(const char *, int *); 821553Srgrimes 83198340Sedstatic int set_IK(const char *, int *); 8488696Sphk 8512946Sphkstatic void 8612946Sphkusage(void) 8712946Sphk{ 881553Srgrimes 8977330Sdes (void)fprintf(stderr, "%s\n%s\n", 90244198Sdelphij "usage: sysctl [-bdehiNnoqTWx] [-f filename] name[=value] ...", 91244106Salfred " sysctl [-bdehNnoqTWx] -a"); 9212946Sphk exit(1); 9312946Sphk} 941553Srgrimes 951553Srgrimesint 9612946Sphkmain(int argc, char **argv) 971553Srgrimes{ 9812946Sphk int ch; 99244198Sdelphij int warncount = 0; 100122233Sdes 101122233Sdes setlocale(LC_NUMERIC, ""); 10212946Sphk setbuf(stdout,0); 10312946Sphk setbuf(stderr,0); 1041553Srgrimes 105244198Sdelphij while ((ch = getopt(argc, argv, "Aabdef:hiNnoqTwWxX")) != -1) { 1061553Srgrimes switch (ch) { 10771034Sdes case 'A': 10877330Sdes /* compatibility */ 10977330Sdes aflag = oflag = 1; 11071034Sdes break; 11171034Sdes case 'a': 11271034Sdes aflag = 1; 11371034Sdes break; 11471034Sdes case 'b': 11571034Sdes bflag = 1; 11671034Sdes break; 11788006Sluigi case 'd': 11888006Sluigi dflag = 1; 11988006Sluigi break; 12085747Stobez case 'e': 12185747Stobez eflag = 1; 12285747Stobez break; 123244198Sdelphij case 'f': 124244198Sdelphij conffile = optarg; 125244198Sdelphij break; 126122233Sdes case 'h': 127122233Sdes hflag = 1; 128122233Sdes break; 129203310Sgavin case 'i': 130203310Sgavin iflag = 1; 131203310Sgavin break; 13271034Sdes case 'N': 13371034Sdes Nflag = 1; 13471034Sdes break; 13571034Sdes case 'n': 13671034Sdes nflag = 1; 13771034Sdes break; 13877330Sdes case 'o': 13977330Sdes oflag = 1; 14077330Sdes break; 141150167Srwatson case 'q': 142150167Srwatson qflag = 1; 143150167Srwatson break; 144244106Salfred case 'T': 145244106Salfred Tflag = 1; 146244106Salfred break; 14771034Sdes case 'w': 14877330Sdes /* compatibility */ 14977330Sdes /* ignored */ 15071034Sdes break; 151244106Salfred case 'W': 152244106Salfred Wflag = 1; 153244106Salfred break; 15471034Sdes case 'X': 15577330Sdes /* compatibility */ 15677330Sdes aflag = xflag = 1; 15771034Sdes break; 15877330Sdes case 'x': 15977330Sdes xflag = 1; 16077330Sdes break; 16171034Sdes default: 16271034Sdes usage(); 1631553Srgrimes } 1641553Srgrimes } 1651553Srgrimes argc -= optind; 1661553Srgrimes argv += optind; 1671553Srgrimes 16877330Sdes if (Nflag && nflag) 16942456Sdes usage(); 17077330Sdes if (aflag && argc == 0) 17177330Sdes exit(sysctl_all(0, 0)); 172244198Sdelphij if (argc == 0 && conffile == NULL) 1731553Srgrimes usage(); 174179965Smtm 175179965Smtm warncount = 0; 176244198Sdelphij if (conffile != NULL) 177244198Sdelphij warncount += parsefile(conffile); 178244198Sdelphij 1791553Srgrimes while (argc-- > 0) 180244198Sdelphij warncount += parse(*argv++, 0); 181244198Sdelphij 182244198Sdelphij return (warncount); 1831553Srgrimes} 1841553Srgrimes 1851553Srgrimes/* 1861553Srgrimes * Parse a name into a MIB entry. 1871553Srgrimes * Lookup and print out the MIB entry if it exists. 1881553Srgrimes * Set a new value if requested. 1891553Srgrimes */ 190244198Sdelphijstatic int 191244198Sdelphijparse(const char *string, int lineno) 1921553Srgrimes{ 19312946Sphk int len, i, j; 1941553Srgrimes void *newval = 0; 19578434Spirzyk int intval; 19678434Spirzyk unsigned int uintval; 19778434Spirzyk long longval; 19878434Spirzyk unsigned long ulongval; 19978434Spirzyk size_t newsize = 0; 200217616Smdf int64_t i64val; 201217616Smdf uint64_t u64val; 2021553Srgrimes int mib[CTL_MAXNAME]; 203244198Sdelphij char *cp, *bufp, buf[BUFSIZ], *endptr, fmt[BUFSIZ], line[BUFSIZ]; 20412946Sphk u_int kind; 2051553Srgrimes 206244198Sdelphij if (lineno) 207244198Sdelphij snprintf(line, sizeof(line), " at line %d", lineno); 208244198Sdelphij else 209244198Sdelphij line[0] = '\0'; 210244198Sdelphij 211244104Sdelphij cp = buf; 212244198Sdelphij if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ) { 213260193Strasz warnx("oid too long: '%s'%s", string, line); 214244198Sdelphij return (1); 215244198Sdelphij } 216244198Sdelphij bufp = strsep(&cp, "=:"); 217244104Sdelphij if (cp != NULL) { 218244106Salfred /* Tflag just lists tunables, do not allow assignment */ 219244106Salfred if (Tflag || Wflag) { 220244106Salfred warnx("Can't set variables when using -T or -W"); 221244106Salfred usage(); 222244106Salfred } 2231553Srgrimes while (isspace(*cp)) 2241553Srgrimes cp++; 225244198Sdelphij /* Strip a pair of " or ' if any. */ 226244198Sdelphij switch (*cp) { 227244198Sdelphij case '\"': 228244198Sdelphij case '\'': 229244198Sdelphij if (cp[strlen(cp) - 1] == *cp) 230244198Sdelphij cp[strlen(cp) - 1] = '\0'; 231244198Sdelphij cp++; 232244198Sdelphij } 2331553Srgrimes newval = cp; 2341553Srgrimes newsize = strlen(cp); 2351553Srgrimes } 236289291Sbapt /* Trim spaces */ 237289291Sbapt cp = bufp + strlen(bufp) - 1; 238289291Sbapt while (cp >= bufp && isspace((int)*cp)) { 239289291Sbapt *cp = '\0'; 240289291Sbapt cp--; 241289291Sbapt } 24212946Sphk len = name2oid(bufp, mib); 2431553Srgrimes 244150167Srwatson if (len < 0) { 245203310Sgavin if (iflag) 246244198Sdelphij return (0); 247150167Srwatson if (qflag) 248244198Sdelphij return (1); 249244198Sdelphij else { 250289292Sbapt if (errno == ENOENT) { 251289292Sbapt warnx("unknown oid '%s'%s", bufp, line); 252289292Sbapt } else { 253289292Sbapt warn("unknown oid '%s'%s", bufp, line); 254289292Sbapt } 255244198Sdelphij return (1); 256244198Sdelphij } 257244198Sdelphij } 258244198Sdelphij 259244198Sdelphij if (oidfmt(mib, len, fmt, &kind)) { 260244198Sdelphij warn("couldn't find format of oid '%s'%s", bufp, line); 261244198Sdelphij if (iflag) 262244198Sdelphij return (1); 263244198Sdelphij else 264150167Srwatson exit(1); 265150167Srwatson } 2661553Srgrimes 267228181Sjhb if (newval == NULL || dflag) { 26812946Sphk if ((kind & CTLTYPE) == CTLTYPE_NODE) { 269144998Smdodd if (dflag) { 270144998Smdodd i = show_var(mib, len); 271144998Smdodd if (!i && !bflag) 272144998Smdodd putchar('\n'); 273144998Smdodd } 27412946Sphk sysctl_all(mib, len); 27512946Sphk } else { 27612946Sphk i = show_var(mib, len); 27712946Sphk if (!i && !bflag) 27812946Sphk putchar('\n'); 2791553Srgrimes } 28012946Sphk } else { 281244198Sdelphij if ((kind & CTLTYPE) == CTLTYPE_NODE) { 282260193Strasz warnx("oid '%s' isn't a leaf node%s", bufp, line); 283244198Sdelphij return (1); 284244198Sdelphij } 2851553Srgrimes 286121849Ssilby if (!(kind & CTLFLAG_WR)) { 287121306Ssilby if (kind & CTLFLAG_TUN) { 288245361Sdelphij warnx("oid '%s' is a read only tunable%s", bufp, line); 289244198Sdelphij warnx("Tunable values are set in /boot/loader.conf"); 290244198Sdelphij } else 291244198Sdelphij warnx("oid '%s' is read only%s", bufp, line); 292244198Sdelphij return (1); 293121306Ssilby } 294116383Srwatson 295116383Srwatson if ((kind & CTLTYPE) == CTLTYPE_INT || 296116383Srwatson (kind & CTLTYPE) == CTLTYPE_UINT || 297116383Srwatson (kind & CTLTYPE) == CTLTYPE_LONG || 298126472Sdd (kind & CTLTYPE) == CTLTYPE_ULONG || 299217616Smdf (kind & CTLTYPE) == CTLTYPE_S64 || 300217616Smdf (kind & CTLTYPE) == CTLTYPE_U64) { 301244198Sdelphij if (strlen(newval) == 0) { 302244198Sdelphij warnx("empty numeric value"); 303244198Sdelphij return (1); 304244198Sdelphij } 305116383Srwatson } 306122234Sdes 30712946Sphk switch (kind & CTLTYPE) { 30812946Sphk case CTLTYPE_INT: 309161951Sume if (strcmp(fmt, "IK") == 0) { 310244198Sdelphij if (!set_IK(newval, &intval)) { 311244198Sdelphij warnx("invalid value '%s'%s", 312244198Sdelphij (char *)newval, line); 313244198Sdelphij return (1); 314244198Sdelphij } 315161951Sume } else { 316161951Sume intval = (int)strtol(newval, &endptr, 317161951Sume 0); 318244198Sdelphij if (endptr == newval || *endptr != '\0') { 319244198Sdelphij warnx("invalid integer '%s'%s", 320244198Sdelphij (char *)newval, line); 321244198Sdelphij return (1); 322244198Sdelphij } 323161951Sume } 32412946Sphk newval = &intval; 32577928Sdd newsize = sizeof(intval); 3261553Srgrimes break; 32778434Spirzyk case CTLTYPE_UINT: 328116383Srwatson uintval = (int) strtoul(newval, &endptr, 0); 329244198Sdelphij if (endptr == newval || *endptr != '\0') { 330244198Sdelphij warnx("invalid unsigned integer '%s'%s", 331244198Sdelphij (char *)newval, line); 332244198Sdelphij return (1); 333244198Sdelphij } 33478434Spirzyk newval = &uintval; 335170512Sdwmalone newsize = sizeof(uintval); 33612946Sphk break; 33778434Spirzyk case CTLTYPE_LONG: 338116383Srwatson longval = strtol(newval, &endptr, 0); 339244198Sdelphij if (endptr == newval || *endptr != '\0') { 340244198Sdelphij warnx("invalid long integer '%s'%s", 341244198Sdelphij (char *)newval, line); 342244198Sdelphij return (1); 343244198Sdelphij } 34478434Spirzyk newval = &longval; 345170512Sdwmalone newsize = sizeof(longval); 34678434Spirzyk break; 34778434Spirzyk case CTLTYPE_ULONG: 348116383Srwatson ulongval = strtoul(newval, &endptr, 0); 349244198Sdelphij if (endptr == newval || *endptr != '\0') { 350244198Sdelphij warnx("invalid unsigned long integer" 351244198Sdelphij " '%s'%s", (char *)newval, line); 352244198Sdelphij return (1); 353244198Sdelphij } 35478434Spirzyk newval = &ulongval; 355170512Sdwmalone newsize = sizeof(ulongval); 35678434Spirzyk break; 35712946Sphk case CTLTYPE_STRING: 35812946Sphk break; 359217616Smdf case CTLTYPE_S64: 360217616Smdf i64val = strtoimax(newval, &endptr, 0); 361244198Sdelphij if (endptr == newval || *endptr != '\0') { 362244198Sdelphij warnx("invalid int64_t '%s'%s", 363244198Sdelphij (char *)newval, line); 364244198Sdelphij return (1); 365244198Sdelphij } 366217616Smdf newval = &i64val; 367217616Smdf newsize = sizeof(i64val); 36812946Sphk break; 369217616Smdf case CTLTYPE_U64: 370217616Smdf u64val = strtoumax(newval, &endptr, 0); 371244198Sdelphij if (endptr == newval || *endptr != '\0') { 372244198Sdelphij warnx("invalid uint64_t '%s'%s", 373244198Sdelphij (char *)newval, line); 374244198Sdelphij return (1); 375244198Sdelphij } 376217616Smdf newval = &u64val; 377217616Smdf newsize = sizeof(u64val); 378217616Smdf break; 37988696Sphk case CTLTYPE_OPAQUE: 38088696Sphk /* FALLTHROUGH */ 38112946Sphk default: 382244198Sdelphij warnx("oid '%s' is type %d," 383244198Sdelphij " cannot set that%s", bufp, 384244198Sdelphij kind & CTLTYPE, line); 385244198Sdelphij return (1); 3861553Srgrimes } 3871553Srgrimes 38812946Sphk i = show_var(mib, len); 38912946Sphk if (sysctl(mib, len, 0, 0, newval, newsize) == -1) { 39012946Sphk if (!i && !bflag) 39112946Sphk putchar('\n'); 39212946Sphk switch (errno) { 39312946Sphk case EOPNOTSUPP: 394244198Sdelphij warnx("%s: value is not available%s", 395244198Sdelphij string, line); 396244198Sdelphij return (1); 39712946Sphk case ENOTDIR: 398244198Sdelphij warnx("%s: specification is incomplete%s", 399244198Sdelphij string, line); 400244198Sdelphij return (1); 40112946Sphk case ENOMEM: 402244198Sdelphij warnx("%s: type is unknown to this program%s", 403244198Sdelphij string, line); 404244198Sdelphij return (1); 40512946Sphk default: 406244198Sdelphij warn("%s%s", string, line); 407244198Sdelphij return (1); 40812946Sphk } 40912946Sphk } 41012946Sphk if (!bflag) 41112946Sphk printf(" -> "); 41212946Sphk i = nflag; 41312946Sphk nflag = 1; 41412946Sphk j = show_var(mib, len); 41512946Sphk if (!j && !bflag) 41612946Sphk putchar('\n'); 41712946Sphk nflag = i; 41812946Sphk } 419244198Sdelphij 420244198Sdelphij return (0); 42112946Sphk} 4221553Srgrimes 423244198Sdelphijstatic int 424244198Sdelphijparsefile(const char *filename) 425244198Sdelphij{ 426244198Sdelphij FILE *file; 427244198Sdelphij char line[BUFSIZ], *p, *pq, *pdq; 428244198Sdelphij int warncount = 0, lineno = 0; 429244198Sdelphij 430244198Sdelphij file = fopen(filename, "r"); 431244198Sdelphij if (file == NULL) 432244198Sdelphij err(EX_NOINPUT, "%s", filename); 433244198Sdelphij while (fgets(line, sizeof(line), file) != NULL) { 434244198Sdelphij lineno++; 435244198Sdelphij p = line; 436244198Sdelphij pq = strchr(line, '\''); 437244198Sdelphij pdq = strchr(line, '\"'); 438244198Sdelphij /* Replace the first # with \0. */ 439244198Sdelphij while((p = strchr(p, '#')) != NULL) { 440244198Sdelphij if (pq != NULL && p > pq) { 441244198Sdelphij if ((p = strchr(pq+1, '\'')) != NULL) 442244198Sdelphij *(++p) = '\0'; 443244198Sdelphij break; 444244198Sdelphij } else if (pdq != NULL && p > pdq) { 445244198Sdelphij if ((p = strchr(pdq+1, '\"')) != NULL) 446244198Sdelphij *(++p) = '\0'; 447244198Sdelphij break; 448244198Sdelphij } else if (p == line || *(p-1) != '\\') { 449244198Sdelphij *p = '\0'; 450244198Sdelphij break; 451244198Sdelphij } 452244198Sdelphij p++; 453244198Sdelphij } 454244198Sdelphij /* Trim spaces */ 455244198Sdelphij p = line + strlen(line) - 1; 456244198Sdelphij while (p >= line && isspace((int)*p)) { 457244198Sdelphij *p = '\0'; 458244198Sdelphij p--; 459244198Sdelphij } 460244198Sdelphij p = line; 461244198Sdelphij while (isspace((int)*p)) 462244198Sdelphij p++; 463244198Sdelphij if (*p == '\0') 464244198Sdelphij continue; 465244198Sdelphij else 466244198Sdelphij warncount += parse(p, lineno); 467244198Sdelphij } 468244198Sdelphij fclose(file); 469244198Sdelphij 470244198Sdelphij return (warncount); 471244198Sdelphij} 472244198Sdelphij 47312946Sphk/* These functions will dump out various interesting structures. */ 4741553Srgrimes 47512946Sphkstatic int 476272913SjhbS_clockinfo(size_t l2, void *p) 47712946Sphk{ 47812946Sphk struct clockinfo *ci = (struct clockinfo*)p; 479170512Sdwmalone 48097232Salfred if (l2 != sizeof(*ci)) { 481272913Sjhb warnx("S_clockinfo %zu != %zu", l2, sizeof(*ci)); 482170558Sbde return (1); 48397232Salfred } 484122233Sdes printf(hflag ? "{ hz = %'d, tick = %'d, profhz = %'d, stathz = %'d }" : 485122233Sdes "{ hz = %d, tick = %d, profhz = %d, stathz = %d }", 48694752Sphk ci->hz, ci->tick, ci->profhz, ci->stathz); 48712946Sphk return (0); 48812946Sphk} 4891553Srgrimes 49012946Sphkstatic int 491272913SjhbS_loadavg(size_t l2, void *p) 49212946Sphk{ 49312946Sphk struct loadavg *tv = (struct loadavg*)p; 4948857Srgrimes 49597232Salfred if (l2 != sizeof(*tv)) { 496272913Sjhb warnx("S_loadavg %zu != %zu", l2, sizeof(*tv)); 497170558Sbde return (1); 49897232Salfred } 499122233Sdes printf(hflag ? "{ %'.2f %'.2f %'.2f }" : "{ %.2f %.2f %.2f }", 50012946Sphk (double)tv->ldavg[0]/(double)tv->fscale, 50112946Sphk (double)tv->ldavg[1]/(double)tv->fscale, 50212946Sphk (double)tv->ldavg[2]/(double)tv->fscale); 50312946Sphk return (0); 50412946Sphk} 5051553Srgrimes 50612946Sphkstatic int 507272913SjhbS_timeval(size_t l2, void *p) 50812946Sphk{ 50912946Sphk struct timeval *tv = (struct timeval*)p; 51037266Sbde time_t tv_sec; 51112946Sphk char *p1, *p2; 5121553Srgrimes 51397232Salfred if (l2 != sizeof(*tv)) { 514272913Sjhb warnx("S_timeval %zu != %zu", l2, sizeof(*tv)); 515170558Sbde return (1); 51697232Salfred } 517194684Sjhay printf(hflag ? "{ sec = %'jd, usec = %'ld } " : 518194684Sjhay "{ sec = %jd, usec = %ld } ", 519194684Sjhay (intmax_t)tv->tv_sec, tv->tv_usec); 52037266Sbde tv_sec = tv->tv_sec; 52137266Sbde p1 = strdup(ctime(&tv_sec)); 52212946Sphk for (p2=p1; *p2 ; p2++) 52312946Sphk if (*p2 == '\n') 52412946Sphk *p2 = '\0'; 52512946Sphk fputs(p1, stdout); 526205118Sbrucec free(p1); 52712946Sphk return (0); 52812946Sphk} 5291553Srgrimes 53012946Sphkstatic int 531272913SjhbS_vmtotal(size_t l2, void *p) 532109097Sdillon{ 533109097Sdillon struct vmtotal *v = (struct vmtotal *)p; 534109113Sdillon int pageKilo = getpagesize() / 1024; 535109097Sdillon 536109097Sdillon if (l2 != sizeof(*v)) { 537272913Sjhb warnx("S_vmtotal %zu != %zu", l2, sizeof(*v)); 538170558Sbde return (1); 539109097Sdillon } 540109097Sdillon 541109113Sdillon printf( 542109113Sdillon "\nSystem wide totals computed every five seconds:" 543109113Sdillon " (values in kilobytes)\n"); 544109097Sdillon printf("===============================================\n"); 545109113Sdillon printf( 546164718Sru "Processes:\t\t(RUNQ: %hd Disk Wait: %hd Page Wait: " 547164718Sru "%hd Sleep: %hd)\n", 548109113Sdillon v->t_rq, v->t_dw, v->t_pw, v->t_sl); 549109113Sdillon printf( 550212726Szec "Virtual Memory:\t\t(Total: %dK Active: %dK)\n", 551164718Sru v->t_vm * pageKilo, v->t_avm * pageKilo); 552212726Szec printf("Real Memory:\t\t(Total: %dK Active: %dK)\n", 553164718Sru v->t_rm * pageKilo, v->t_arm * pageKilo); 554164718Sru printf("Shared Virtual Memory:\t(Total: %dK Active: %dK)\n", 555164718Sru v->t_vmshr * pageKilo, v->t_avmshr * pageKilo); 556164718Sru printf("Shared Real Memory:\t(Total: %dK Active: %dK)\n", 557164718Sru v->t_rmshr * pageKilo, v->t_armshr * pageKilo); 558272913Sjhb printf("Free Memory:\t%dK", v->t_free * pageKilo); 559122234Sdes 560109097Sdillon return (0); 561109097Sdillon} 562109097Sdillon 563272913Sjhb#ifdef __amd64__ 564272913Sjhb#define efi_next_descriptor(ptr, size) \ 565272913Sjhb ((struct efi_md *)(((uint8_t *) ptr) + size)) 566272913Sjhb 567109097Sdillonstatic int 568272913SjhbS_efi_map(size_t l2, void *p) 569272913Sjhb{ 570272913Sjhb struct efi_map_header *efihdr; 571272913Sjhb struct efi_md *map; 572272913Sjhb const char *type; 573272913Sjhb size_t efisz; 574272913Sjhb int ndesc, i; 575272913Sjhb 576272913Sjhb static const char *types[] = { 577272913Sjhb "Reserved", 578272913Sjhb "LoaderCode", 579272913Sjhb "LoaderData", 580272913Sjhb "BootServicesCode", 581272913Sjhb "BootServicesData", 582272913Sjhb "RuntimeServicesCode", 583272913Sjhb "RuntimeServicesData", 584272913Sjhb "ConventionalMemory", 585272913Sjhb "UnusableMemory", 586272913Sjhb "ACPIReclaimMemory", 587272913Sjhb "ACPIMemoryNVS", 588272913Sjhb "MemoryMappedIO", 589272913Sjhb "MemoryMappedIOPortSpace", 590272913Sjhb "PalCode" 591272913Sjhb }; 592272913Sjhb 593272913Sjhb /* 594272913Sjhb * Memory map data provided by UEFI via the GetMemoryMap 595272913Sjhb * Boot Services API. 596272913Sjhb */ 597272913Sjhb if (l2 < sizeof(*efihdr)) { 598272913Sjhb warnx("S_efi_map length less than header"); 599272913Sjhb return (1); 600272913Sjhb } 601272913Sjhb efihdr = p; 602272913Sjhb efisz = (sizeof(struct efi_map_header) + 0xf) & ~0xf; 603272913Sjhb map = (struct efi_md *)((uint8_t *)efihdr + efisz); 604272913Sjhb 605272913Sjhb if (efihdr->descriptor_size == 0) 606272913Sjhb return (0); 607272913Sjhb if (l2 != efisz + efihdr->memory_size) { 608272913Sjhb warnx("S_efi_map length mismatch %zu vs %zu", l2, efisz + 609272913Sjhb efihdr->memory_size); 610272913Sjhb return (1); 611272913Sjhb } 612272913Sjhb ndesc = efihdr->memory_size / efihdr->descriptor_size; 613272913Sjhb 614272913Sjhb printf("\n%23s %12s %12s %8s %4s", 615272913Sjhb "Type", "Physical", "Virtual", "#Pages", "Attr"); 616272913Sjhb 617272913Sjhb for (i = 0; i < ndesc; i++, 618272913Sjhb map = efi_next_descriptor(map, efihdr->descriptor_size)) { 619272913Sjhb if (map->md_type <= EFI_MD_TYPE_PALCODE) 620272913Sjhb type = types[map->md_type]; 621272913Sjhb else 622272913Sjhb type = "<INVALID>"; 623272913Sjhb printf("\n%23s %012lx %12p %08lx ", type, map->md_phys, 624272913Sjhb map->md_virt, map->md_pages); 625272913Sjhb if (map->md_attr & EFI_MD_ATTR_UC) 626272913Sjhb printf("UC "); 627272913Sjhb if (map->md_attr & EFI_MD_ATTR_WC) 628272913Sjhb printf("WC "); 629272913Sjhb if (map->md_attr & EFI_MD_ATTR_WT) 630272913Sjhb printf("WT "); 631272913Sjhb if (map->md_attr & EFI_MD_ATTR_WB) 632272913Sjhb printf("WB "); 633272913Sjhb if (map->md_attr & EFI_MD_ATTR_UCE) 634272913Sjhb printf("UCE "); 635272913Sjhb if (map->md_attr & EFI_MD_ATTR_WP) 636272913Sjhb printf("WP "); 637272913Sjhb if (map->md_attr & EFI_MD_ATTR_RP) 638272913Sjhb printf("RP "); 639272913Sjhb if (map->md_attr & EFI_MD_ATTR_XP) 640272913Sjhb printf("XP "); 641272913Sjhb if (map->md_attr & EFI_MD_ATTR_RT) 642272913Sjhb printf("RUNTIME"); 643272913Sjhb } 644272913Sjhb return (0); 645272913Sjhb} 646272913Sjhb#endif 647272913Sjhb 648272913Sjhb#if defined(__amd64__) || defined(__i386__) 649272913Sjhbstatic int 650272913SjhbS_bios_smap_xattr(size_t l2, void *p) 651272913Sjhb{ 652272913Sjhb struct bios_smap_xattr *smap, *end; 653272913Sjhb 654272913Sjhb if (l2 % sizeof(*smap) != 0) { 655272913Sjhb warnx("S_bios_smap_xattr %zu is not a multiple of %zu", l2, 656272913Sjhb sizeof(*smap)); 657272913Sjhb return (1); 658272913Sjhb } 659272913Sjhb 660272913Sjhb end = (struct bios_smap_xattr *)((char *)p + l2); 661272913Sjhb for (smap = p; smap < end; smap++) 662272913Sjhb printf("\nSMAP type=%02x, xattr=%02x, base=%016jx, len=%016jx", 663272913Sjhb smap->type, smap->xattr, (uintmax_t)smap->base, 664272913Sjhb (uintmax_t)smap->length); 665272913Sjhb return (0); 666272913Sjhb} 667272913Sjhb#endif 668272913Sjhb 669272913Sjhbstatic int 670198340Sedset_IK(const char *str, int *val) 671161951Sume{ 672161951Sume float temp; 673161951Sume int len, kelv; 674198340Sed const char *p; 675198340Sed char *endptr; 676161951Sume 677161951Sume if ((len = strlen(str)) == 0) 678161951Sume return (0); 679161951Sume p = &str[len - 1]; 680161951Sume if (*p == 'C' || *p == 'F') { 681161951Sume temp = strtof(str, &endptr); 682198340Sed if (endptr == str || endptr != p) 683161951Sume return (0); 684161951Sume if (*p == 'F') 685161951Sume temp = (temp - 32) * 5 / 9; 686161951Sume kelv = temp * 10 + 2732; 687161951Sume } else { 688161951Sume kelv = (int)strtol(str, &endptr, 10); 689161951Sume if (endptr == str || *endptr != '\0') 690161951Sume return (0); 691161951Sume } 692161951Sume *val = kelv; 693161951Sume return (1); 694161951Sume} 695161951Sume 69612946Sphk/* 69712946Sphk * These functions uses a presently undocumented interface to the kernel 69812946Sphk * to walk the tree and get the type so it can print the value. 69912946Sphk * This interface is under work and consideration, and should probably 70012946Sphk * be killed with a big axe by the first person who can find the time. 70112946Sphk * (be aware though, that the proper interface isn't as obvious as it 70212946Sphk * may seem, there are various conflicting requirements. 70312946Sphk */ 7041553Srgrimes 70512946Sphkstatic int 706275485Sdelphijname2oid(const char *name, int *oidp) 70712946Sphk{ 70812946Sphk int oid[2]; 70938533Sdfr int i; 71038533Sdfr size_t j; 7111553Srgrimes 71212946Sphk oid[0] = 0; 71312946Sphk oid[1] = 3; 7141553Srgrimes 71577928Sdd j = CTL_MAXNAME * sizeof(int); 71612946Sphk i = sysctl(oid, 2, oidp, &j, name, strlen(name)); 717122234Sdes if (i < 0) 718170512Sdwmalone return (i); 71977928Sdd j /= sizeof(int); 72012946Sphk return (j); 7211553Srgrimes} 7221553Srgrimes 72312946Sphkstatic int 72412946Sphkoidfmt(int *oid, int len, char *fmt, u_int *kind) 72512946Sphk{ 72612946Sphk int qoid[CTL_MAXNAME+2]; 72712946Sphk u_char buf[BUFSIZ]; 72838533Sdfr int i; 72938533Sdfr size_t j; 7301553Srgrimes 73112946Sphk qoid[0] = 0; 73212946Sphk qoid[1] = 4; 73312946Sphk memcpy(qoid + 2, oid, len * sizeof(int)); 7341553Srgrimes 73577928Sdd j = sizeof(buf); 73612946Sphk i = sysctl(qoid, len + 2, buf, &j, 0, 0); 73712946Sphk if (i) 738203917Suqs err(1, "sysctl fmt %d %zu %d", i, j, errno); 7391553Srgrimes 74012946Sphk if (kind) 74112946Sphk *kind = *(u_int *)buf; 74212946Sphk 74312946Sphk if (fmt) 74412946Sphk strcpy(fmt, (char *)(buf + sizeof(u_int))); 745170512Sdwmalone return (0); 7461553Srgrimes} 7471553Srgrimes 748217616Smdfstatic int ctl_sign[CTLTYPE+1] = { 749217616Smdf [CTLTYPE_INT] = 1, 750217616Smdf [CTLTYPE_LONG] = 1, 751217616Smdf [CTLTYPE_S64] = 1, 752217616Smdf}; 753217616Smdf 754217616Smdfstatic int ctl_size[CTLTYPE+1] = { 755217616Smdf [CTLTYPE_INT] = sizeof(int), 756217616Smdf [CTLTYPE_UINT] = sizeof(u_int), 757217616Smdf [CTLTYPE_LONG] = sizeof(long), 758217616Smdf [CTLTYPE_ULONG] = sizeof(u_long), 759217616Smdf [CTLTYPE_S64] = sizeof(int64_t), 760217616Smdf [CTLTYPE_U64] = sizeof(int64_t), 761217616Smdf}; 762217616Smdf 7631553Srgrimes/* 76412946Sphk * This formats and outputs the value of one variable 76512946Sphk * 76612946Sphk * Returns zero if anything was actually output. 76712946Sphk * Returns one if didn't know what to do with this. 76812946Sphk * Return minus one if we had errors. 7691553Srgrimes */ 77012946Sphkstatic int 77112946Sphkshow_var(int *oid, int nlen) 7721553Srgrimes{ 773162073Sru u_char buf[BUFSIZ], *val, *oval, *p; 774244133Salfred char name[BUFSIZ], fmt[BUFSIZ]; 775170513Sdwmalone const char *sep, *sep1; 77612946Sphk int qoid[CTL_MAXNAME+2]; 777170512Sdwmalone uintmax_t umv; 778170512Sdwmalone intmax_t mv; 779217586Smdf int i, hexlen, sign, ctltype; 780170287Sdwmalone size_t intlen; 78138533Sdfr size_t j, len; 78212946Sphk u_int kind; 783272913Sjhb int (*func)(size_t, void *); 7841553Srgrimes 785203917Suqs /* Silence GCC. */ 786203917Suqs umv = mv = intlen = 0; 787203917Suqs 788144997Smdodd bzero(buf, BUFSIZ); 789244133Salfred bzero(fmt, BUFSIZ); 790144997Smdodd bzero(name, BUFSIZ); 79142456Sdes qoid[0] = 0; 79242456Sdes memcpy(qoid + 2, oid, nlen * sizeof(int)); 79342456Sdes 79442456Sdes qoid[1] = 1; 79577928Sdd j = sizeof(name); 79642456Sdes i = sysctl(qoid, nlen + 2, name, &j, 0, 0); 79742456Sdes if (i || !j) 798203917Suqs err(1, "sysctl name %d %zu %d", i, j, errno); 79942456Sdes 800244133Salfred oidfmt(oid, nlen, fmt, &kind); 801244133Salfred /* if Wflag then only list sysctls that are writeable and not stats. */ 802244133Salfred if (Wflag && ((kind & CTLFLAG_WR) == 0 || (kind & CTLFLAG_STATS) != 0)) 803244133Salfred return 1; 804244133Salfred 805244133Salfred /* if Tflag then only list sysctls that are tuneables. */ 806244133Salfred if (Tflag && (kind & CTLFLAG_TUN) == 0) 807244133Salfred return 1; 808244133Salfred 80971034Sdes if (Nflag) { 81071034Sdes printf("%s", name); 81171034Sdes return (0); 81271034Sdes } 81371034Sdes 81485747Stobez if (eflag) 81585747Stobez sep = "="; 81685747Stobez else 81785747Stobez sep = ": "; 81885747Stobez 81988006Sluigi if (dflag) { /* just print description */ 82088006Sluigi qoid[1] = 5; 82188006Sluigi j = sizeof(buf); 82288006Sluigi i = sysctl(qoid, nlen + 2, buf, &j, 0, 0); 82388006Sluigi if (!nflag) 82488006Sluigi printf("%s%s", name, sep); 82588006Sluigi printf("%s", buf); 82688006Sluigi return (0); 82788006Sluigi } 82812946Sphk /* find an estimate of how much we need for this var */ 82912946Sphk j = 0; 83012946Sphk i = sysctl(oid, nlen, 0, &j, 0, 0); 83112946Sphk j += j; /* we want to be sure :-) */ 83212946Sphk 833162073Sru val = oval = malloc(j + 1); 834162073Sru if (val == NULL) { 835162073Sru warnx("malloc failed"); 836170558Sbde return (1); 837162073Sru } 838268243Shselasky ctltype = (kind & CTLTYPE); 83912946Sphk len = j; 84012946Sphk i = sysctl(oid, nlen, val, &len, 0, 0); 841268243Shselasky if (i != 0 || (len == 0 && ctltype != CTLTYPE_STRING)) { 842162073Sru free(oval); 84312946Sphk return (1); 844162073Sru } 84512946Sphk 84612946Sphk if (bflag) { 84712946Sphk fwrite(val, 1, len, stdout); 848162073Sru free(oval); 84912946Sphk return (0); 8501553Srgrimes } 85196234Sache val[len] = '\0'; 85212946Sphk p = val; 853217616Smdf sign = ctl_sign[ctltype]; 854217616Smdf intlen = ctl_size[ctltype]; 855217616Smdf 856217586Smdf switch (ctltype) { 857217586Smdf case CTLTYPE_STRING: 85812946Sphk if (!nflag) 85985747Stobez printf("%s%s", name, sep); 860203917Suqs printf("%.*s", (int)len, p); 861162073Sru free(oval); 86212946Sphk return (0); 863122234Sdes 864217586Smdf case CTLTYPE_INT: 865217586Smdf case CTLTYPE_UINT: 866217586Smdf case CTLTYPE_LONG: 867217586Smdf case CTLTYPE_ULONG: 868217616Smdf case CTLTYPE_S64: 869217616Smdf case CTLTYPE_U64: 87012946Sphk if (!nflag) 87185747Stobez printf("%s%s", name, sep); 872170514Sdwmalone hexlen = 2 + (intlen * CHAR_BIT + 3) / 4; 873170513Sdwmalone sep1 = ""; 874170287Sdwmalone while (len >= intlen) { 875217586Smdf switch (kind & CTLTYPE) { 876217586Smdf case CTLTYPE_INT: 877217586Smdf case CTLTYPE_UINT: 878170514Sdwmalone umv = *(u_int *)p; 879170514Sdwmalone mv = *(int *)p; 880170287Sdwmalone break; 881217586Smdf case CTLTYPE_LONG: 882217586Smdf case CTLTYPE_ULONG: 883170514Sdwmalone umv = *(u_long *)p; 884170514Sdwmalone mv = *(long *)p; 885170287Sdwmalone break; 886217616Smdf case CTLTYPE_S64: 887217616Smdf case CTLTYPE_U64: 888217616Smdf umv = *(uint64_t *)p; 889217616Smdf mv = *(int64_t *)p; 890170287Sdwmalone break; 891170287Sdwmalone } 892170513Sdwmalone fputs(sep1, stdout); 893217586Smdf if (xflag) 894217586Smdf printf("%#0*jx", hexlen, umv); 895217586Smdf else if (!sign) 896170512Sdwmalone printf(hflag ? "%'ju" : "%ju", umv); 897170287Sdwmalone else if (fmt[1] == 'K') { 898170514Sdwmalone if (mv < 0) 899170512Sdwmalone printf("%jd", mv); 900134541Speter else 901170512Sdwmalone printf("%.1fC", (mv - 2732.0) / 10); 902134541Speter } else 903170513Sdwmalone printf(hflag ? "%'jd" : "%jd", mv); 904170513Sdwmalone sep1 = " "; 905170287Sdwmalone len -= intlen; 906170287Sdwmalone p += intlen; 90741019Sphk } 908162073Sru free(oval); 90912946Sphk return (0); 91012946Sphk 911217586Smdf case CTLTYPE_OPAQUE: 91212946Sphk i = 0; 91377332Sdes if (strcmp(fmt, "S,clockinfo") == 0) 91477332Sdes func = S_clockinfo; 91577332Sdes else if (strcmp(fmt, "S,timeval") == 0) 91677332Sdes func = S_timeval; 91777332Sdes else if (strcmp(fmt, "S,loadavg") == 0) 91877332Sdes func = S_loadavg; 919109097Sdillon else if (strcmp(fmt, "S,vmtotal") == 0) 920109097Sdillon func = S_vmtotal; 921272913Sjhb#ifdef __amd64__ 922272913Sjhb else if (strcmp(fmt, "S,efi_map_header") == 0) 923272913Sjhb func = S_efi_map; 924272913Sjhb#endif 925272913Sjhb#if defined(__amd64__) || defined(__i386__) 926272913Sjhb else if (strcmp(fmt, "S,bios_smap_xattr") == 0) 927272913Sjhb func = S_bios_smap_xattr; 928272913Sjhb#endif 92977332Sdes else 93077332Sdes func = NULL; 93112946Sphk if (func) { 93212946Sphk if (!nflag) 93385747Stobez printf("%s%s", name, sep); 934163275Sharti i = (*func)(len, p); 935162073Sru free(oval); 936163275Sharti return (i); 93712946Sphk } 938102411Scharnier /* FALLTHROUGH */ 93912946Sphk default: 940162073Sru if (!oflag && !xflag) { 941162073Sru free(oval); 94212946Sphk return (1); 943162073Sru } 94412946Sphk if (!nflag) 94585747Stobez printf("%s%s", name, sep); 946203917Suqs printf("Format:%s Length:%zu Dump:0x", fmt, len); 94777332Sdes while (len-- && (xflag || p < val + 16)) 94812946Sphk printf("%02x", *p++); 94977332Sdes if (!xflag && len > 16) 95012946Sphk printf("..."); 951162073Sru free(oval); 95212946Sphk return (0); 9531553Srgrimes } 954162073Sru free(oval); 95512946Sphk return (1); 9561553Srgrimes} 9571553Srgrimes 95812946Sphkstatic int 959170512Sdwmalonesysctl_all(int *oid, int len) 9601553Srgrimes{ 96112946Sphk int name1[22], name2[22]; 96238533Sdfr int i, j; 96338533Sdfr size_t l1, l2; 9641553Srgrimes 96512946Sphk name1[0] = 0; 96612946Sphk name1[1] = 2; 96712946Sphk l1 = 2; 96812946Sphk if (len) { 96977928Sdd memcpy(name1+2, oid, len * sizeof(int)); 97012946Sphk l1 += len; 97112946Sphk } else { 97212946Sphk name1[2] = 1; 97312946Sphk l1++; 97412946Sphk } 97577332Sdes for (;;) { 97677928Sdd l2 = sizeof(name2); 97712946Sphk j = sysctl(name1, l1, name2, &l2, 0, 0); 97848956Sbillf if (j < 0) { 97912946Sphk if (errno == ENOENT) 980170512Sdwmalone return (0); 98112946Sphk else 982203917Suqs err(1, "sysctl(getnext) %d %zu", j, l2); 98348956Sbillf } 98412946Sphk 98577928Sdd l2 /= sizeof(int); 98612946Sphk 987170513Sdwmalone if (len < 0 || l2 < (unsigned int)len) 988170512Sdwmalone return (0); 98912946Sphk 99012946Sphk for (i = 0; i < len; i++) 99112946Sphk if (name2[i] != oid[i]) 992170512Sdwmalone return (0); 99312946Sphk 99412946Sphk i = show_var(name2, l2); 99512946Sphk if (!i && !bflag) 99612946Sphk putchar('\n'); 99712946Sphk 99877928Sdd memcpy(name1+2, name2, l2 * sizeof(int)); 99912946Sphk l1 = 2 + l2; 100012946Sphk } 10011553Srgrimes} 1002