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$"; 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 5130602Scharnier#include <ctype.h> 5230602Scharnier#include <err.h> 531553Srgrimes#include <errno.h> 54170287Sdwmalone#include <inttypes.h> 55122233Sdes#include <locale.h> 561553Srgrimes#include <stdio.h> 571553Srgrimes#include <stdlib.h> 581553Srgrimes#include <string.h> 5930602Scharnier#include <unistd.h> 601553Srgrimes 61203310Sgavinstatic int aflag, bflag, dflag, eflag, hflag, iflag; 62203310Sgavinstatic int Nflag, nflag, oflag, qflag, xflag, warncount; 631553Srgrimes 6412946Sphkstatic int oidfmt(int *, int, char *, u_int *); 65244669Sdelphijstatic void parse(const char *); 6612946Sphkstatic int show_var(int *, int); 67170512Sdwmalonestatic int sysctl_all(int *oid, int len); 6812946Sphkstatic int name2oid(char *, int *); 691553Srgrimes 70198340Sedstatic int set_IK(const char *, int *); 7188696Sphk 7212946Sphkstatic void 7312946Sphkusage(void) 7412946Sphk{ 751553Srgrimes 7677330Sdes (void)fprintf(stderr, "%s\n%s\n", 77203717Sgavin "usage: sysctl [-bdehiNnoqx] name[=value] ...", 78152995Sru " sysctl [-bdehNnoqx] -a"); 7912946Sphk exit(1); 8012946Sphk} 811553Srgrimes 821553Srgrimesint 8312946Sphkmain(int argc, char **argv) 841553Srgrimes{ 8512946Sphk int ch; 86122233Sdes 87122233Sdes setlocale(LC_NUMERIC, ""); 8812946Sphk setbuf(stdout,0); 8912946Sphk setbuf(stderr,0); 901553Srgrimes 91203310Sgavin while ((ch = getopt(argc, argv, "AabdehiNnoqwxX")) != -1) { 921553Srgrimes switch (ch) { 9371034Sdes case 'A': 9477330Sdes /* compatibility */ 9577330Sdes aflag = oflag = 1; 9671034Sdes break; 9771034Sdes case 'a': 9871034Sdes aflag = 1; 9971034Sdes break; 10071034Sdes case 'b': 10171034Sdes bflag = 1; 10271034Sdes break; 10388006Sluigi case 'd': 10488006Sluigi dflag = 1; 10588006Sluigi break; 10685747Stobez case 'e': 10785747Stobez eflag = 1; 10885747Stobez break; 109122233Sdes case 'h': 110122233Sdes hflag = 1; 111122233Sdes break; 112203310Sgavin case 'i': 113203310Sgavin iflag = 1; 114203310Sgavin break; 11571034Sdes case 'N': 11671034Sdes Nflag = 1; 11771034Sdes break; 11871034Sdes case 'n': 11971034Sdes nflag = 1; 12071034Sdes break; 12177330Sdes case 'o': 12277330Sdes oflag = 1; 12377330Sdes break; 124150167Srwatson case 'q': 125150167Srwatson qflag = 1; 126150167Srwatson break; 12771034Sdes case 'w': 12877330Sdes /* compatibility */ 12977330Sdes /* ignored */ 13071034Sdes break; 13171034Sdes case 'X': 13277330Sdes /* compatibility */ 13377330Sdes aflag = xflag = 1; 13471034Sdes break; 13577330Sdes case 'x': 13677330Sdes xflag = 1; 13777330Sdes break; 13871034Sdes default: 13971034Sdes usage(); 1401553Srgrimes } 1411553Srgrimes } 1421553Srgrimes argc -= optind; 1431553Srgrimes argv += optind; 1441553Srgrimes 14577330Sdes if (Nflag && nflag) 14642456Sdes usage(); 14777330Sdes if (aflag && argc == 0) 14877330Sdes exit(sysctl_all(0, 0)); 1491553Srgrimes if (argc == 0) 1501553Srgrimes usage(); 151179965Smtm 152179965Smtm warncount = 0; 1531553Srgrimes while (argc-- > 0) 15412946Sphk parse(*argv++); 155179965Smtm exit(warncount); 1561553Srgrimes} 1571553Srgrimes 1581553Srgrimes/* 1591553Srgrimes * Parse a name into a MIB entry. 1601553Srgrimes * Lookup and print out the MIB entry if it exists. 1611553Srgrimes * Set a new value if requested. 1621553Srgrimes */ 16312946Sphkstatic void 164244669Sdelphijparse(const char *string) 1651553Srgrimes{ 16612946Sphk int len, i, j; 1671553Srgrimes void *newval = 0; 16878434Spirzyk int intval; 16978434Spirzyk unsigned int uintval; 17078434Spirzyk long longval; 17178434Spirzyk unsigned long ulongval; 17278434Spirzyk size_t newsize = 0; 173217616Smdf int64_t i64val; 174217616Smdf uint64_t u64val; 1751553Srgrimes int mib[CTL_MAXNAME]; 176116383Srwatson char *cp, *bufp, buf[BUFSIZ], *endptr, fmt[BUFSIZ]; 17712946Sphk u_int kind; 1781553Srgrimes 179244669Sdelphij cp = buf; 180140818Sssouhlal if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ) 181140818Sssouhlal errx(1, "oid too long: '%s'", string); 182244669Sdelphij bufp = strsep(&cp, "="); 183244669Sdelphij if (cp != NULL) { 1841553Srgrimes while (isspace(*cp)) 1851553Srgrimes cp++; 1861553Srgrimes newval = cp; 1871553Srgrimes newsize = strlen(cp); 1881553Srgrimes } 18912946Sphk len = name2oid(bufp, mib); 1901553Srgrimes 191150167Srwatson if (len < 0) { 192203310Sgavin if (iflag) 193203310Sgavin return; 194150167Srwatson if (qflag) 195150167Srwatson exit(1); 196150167Srwatson else 197150167Srwatson errx(1, "unknown oid '%s'", bufp); 198150167Srwatson } 1991553Srgrimes 20088696Sphk if (oidfmt(mib, len, fmt, &kind)) 20130602Scharnier err(1, "couldn't find format of oid '%s'", bufp); 2021553Srgrimes 203229615Sjhb if (newval == NULL || dflag) { 20412946Sphk if ((kind & CTLTYPE) == CTLTYPE_NODE) { 205144998Smdodd if (dflag) { 206144998Smdodd i = show_var(mib, len); 207144998Smdodd if (!i && !bflag) 208144998Smdodd putchar('\n'); 209144998Smdodd } 21012946Sphk sysctl_all(mib, len); 21112946Sphk } else { 21212946Sphk i = show_var(mib, len); 21312946Sphk if (!i && !bflag) 21412946Sphk putchar('\n'); 2151553Srgrimes } 21612946Sphk } else { 21712946Sphk if ((kind & CTLTYPE) == CTLTYPE_NODE) 21812946Sphk errx(1, "oid '%s' isn't a leaf node", bufp); 2191553Srgrimes 220121849Ssilby if (!(kind & CTLFLAG_WR)) { 221121306Ssilby if (kind & CTLFLAG_TUN) { 222121849Ssilby warnx("oid '%s' is a read only tunable", bufp); 223121849Ssilby errx(1, "Tunable values are set in /boot/loader.conf"); 224121306Ssilby } else { 225121306Ssilby errx(1, "oid '%s' is read only", bufp); 226121849Ssilby } 227121306Ssilby } 228116383Srwatson 229116383Srwatson if ((kind & CTLTYPE) == CTLTYPE_INT || 230116383Srwatson (kind & CTLTYPE) == CTLTYPE_UINT || 231116383Srwatson (kind & CTLTYPE) == CTLTYPE_LONG || 232126472Sdd (kind & CTLTYPE) == CTLTYPE_ULONG || 233217616Smdf (kind & CTLTYPE) == CTLTYPE_S64 || 234217616Smdf (kind & CTLTYPE) == CTLTYPE_U64) { 235116383Srwatson if (strlen(newval) == 0) 236116383Srwatson errx(1, "empty numeric value"); 237116383Srwatson } 238122234Sdes 23912946Sphk switch (kind & CTLTYPE) { 24012946Sphk case CTLTYPE_INT: 241161951Sume if (strcmp(fmt, "IK") == 0) { 242170512Sdwmalone if (!set_IK(newval, &intval)) 243161951Sume errx(1, "invalid value '%s'", 244170513Sdwmalone (char *)newval); 245161951Sume } else { 246161951Sume intval = (int)strtol(newval, &endptr, 247161951Sume 0); 248161951Sume if (endptr == newval || *endptr != '\0') 249161951Sume errx(1, "invalid integer '%s'", 250170513Sdwmalone (char *)newval); 251161951Sume } 25212946Sphk newval = &intval; 25377928Sdd newsize = sizeof(intval); 2541553Srgrimes break; 25578434Spirzyk case CTLTYPE_UINT: 256116383Srwatson uintval = (int) strtoul(newval, &endptr, 0); 257116383Srwatson if (endptr == newval || *endptr != '\0') 258116383Srwatson errx(1, "invalid unsigned integer '%s'", 259170513Sdwmalone (char *)newval); 26078434Spirzyk newval = &uintval; 261170512Sdwmalone newsize = sizeof(uintval); 26212946Sphk break; 26378434Spirzyk case CTLTYPE_LONG: 264116383Srwatson longval = strtol(newval, &endptr, 0); 265116383Srwatson if (endptr == newval || *endptr != '\0') 266116383Srwatson errx(1, "invalid long integer '%s'", 267170513Sdwmalone (char *)newval); 26878434Spirzyk newval = &longval; 269170512Sdwmalone newsize = sizeof(longval); 27078434Spirzyk break; 27178434Spirzyk case CTLTYPE_ULONG: 272116383Srwatson ulongval = strtoul(newval, &endptr, 0); 273116383Srwatson if (endptr == newval || *endptr != '\0') 274116383Srwatson errx(1, "invalid unsigned long integer" 275170513Sdwmalone " '%s'", (char *)newval); 27678434Spirzyk newval = &ulongval; 277170512Sdwmalone newsize = sizeof(ulongval); 27878434Spirzyk break; 27912946Sphk case CTLTYPE_STRING: 28012946Sphk break; 281217616Smdf case CTLTYPE_S64: 282217616Smdf i64val = strtoimax(newval, &endptr, 0); 283203917Suqs if (endptr == newval || *endptr != '\0') 284217616Smdf errx(1, "invalid int64_t '%s'", 285217616Smdf (char *)newval); 286217616Smdf newval = &i64val; 287217616Smdf newsize = sizeof(i64val); 28812946Sphk break; 289217616Smdf case CTLTYPE_U64: 290217616Smdf u64val = strtoumax(newval, &endptr, 0); 291217616Smdf if (endptr == newval || *endptr != '\0') 292217616Smdf errx(1, "invalid uint64_t '%s'", 293217616Smdf (char *)newval); 294217616Smdf newval = &u64val; 295217616Smdf newsize = sizeof(u64val); 296217616Smdf break; 29788696Sphk case CTLTYPE_OPAQUE: 29888696Sphk /* FALLTHROUGH */ 29912946Sphk default: 30012946Sphk errx(1, "oid '%s' is type %d," 30131214Sjdp " cannot set that", bufp, 30231214Sjdp kind & CTLTYPE); 3031553Srgrimes } 3041553Srgrimes 30512946Sphk i = show_var(mib, len); 30612946Sphk if (sysctl(mib, len, 0, 0, newval, newsize) == -1) { 30712946Sphk if (!i && !bflag) 30812946Sphk putchar('\n'); 30912946Sphk switch (errno) { 31012946Sphk case EOPNOTSUPP: 311122234Sdes errx(1, "%s: value is not available", 31212946Sphk string); 31312946Sphk case ENOTDIR: 314122234Sdes errx(1, "%s: specification is incomplete", 31512946Sphk string); 31612946Sphk case ENOMEM: 317122234Sdes errx(1, "%s: type is unknown to this program", 31812946Sphk string); 31912946Sphk default: 32030602Scharnier warn("%s", string); 321179965Smtm warncount++; 32212946Sphk return; 32312946Sphk } 32412946Sphk } 32512946Sphk if (!bflag) 32612946Sphk printf(" -> "); 32712946Sphk i = nflag; 32812946Sphk nflag = 1; 32912946Sphk j = show_var(mib, len); 33012946Sphk if (!j && !bflag) 33112946Sphk putchar('\n'); 33212946Sphk nflag = i; 33312946Sphk } 33412946Sphk} 3351553Srgrimes 33612946Sphk/* These functions will dump out various interesting structures. */ 3371553Srgrimes 33812946Sphkstatic int 33912946SphkS_clockinfo(int l2, void *p) 34012946Sphk{ 34112946Sphk struct clockinfo *ci = (struct clockinfo*)p; 342170512Sdwmalone 34397232Salfred if (l2 != sizeof(*ci)) { 344203917Suqs warnx("S_clockinfo %d != %zu", l2, sizeof(*ci)); 345170558Sbde return (1); 34697232Salfred } 347122233Sdes printf(hflag ? "{ hz = %'d, tick = %'d, profhz = %'d, stathz = %'d }" : 348122233Sdes "{ hz = %d, tick = %d, profhz = %d, stathz = %d }", 34994752Sphk ci->hz, ci->tick, ci->profhz, ci->stathz); 35012946Sphk return (0); 35112946Sphk} 3521553Srgrimes 35312946Sphkstatic int 35412946SphkS_loadavg(int l2, void *p) 35512946Sphk{ 35612946Sphk struct loadavg *tv = (struct loadavg*)p; 3578857Srgrimes 35897232Salfred if (l2 != sizeof(*tv)) { 359203917Suqs warnx("S_loadavg %d != %zu", l2, sizeof(*tv)); 360170558Sbde return (1); 36197232Salfred } 362122233Sdes printf(hflag ? "{ %'.2f %'.2f %'.2f }" : "{ %.2f %.2f %.2f }", 36312946Sphk (double)tv->ldavg[0]/(double)tv->fscale, 36412946Sphk (double)tv->ldavg[1]/(double)tv->fscale, 36512946Sphk (double)tv->ldavg[2]/(double)tv->fscale); 36612946Sphk return (0); 36712946Sphk} 3681553Srgrimes 36912946Sphkstatic int 37012946SphkS_timeval(int l2, void *p) 37112946Sphk{ 37212946Sphk struct timeval *tv = (struct timeval*)p; 37337266Sbde time_t tv_sec; 37412946Sphk char *p1, *p2; 3751553Srgrimes 37697232Salfred if (l2 != sizeof(*tv)) { 377203917Suqs warnx("S_timeval %d != %zu", l2, sizeof(*tv)); 378170558Sbde return (1); 37997232Salfred } 380194684Sjhay printf(hflag ? "{ sec = %'jd, usec = %'ld } " : 381194684Sjhay "{ sec = %jd, usec = %ld } ", 382194684Sjhay (intmax_t)tv->tv_sec, tv->tv_usec); 38337266Sbde tv_sec = tv->tv_sec; 38437266Sbde p1 = strdup(ctime(&tv_sec)); 38512946Sphk for (p2=p1; *p2 ; p2++) 38612946Sphk if (*p2 == '\n') 38712946Sphk *p2 = '\0'; 38812946Sphk fputs(p1, stdout); 389205118Sbrucec free(p1); 39012946Sphk return (0); 39112946Sphk} 3921553Srgrimes 39312946Sphkstatic int 394109097SdillonS_vmtotal(int l2, void *p) 395109097Sdillon{ 396109097Sdillon struct vmtotal *v = (struct vmtotal *)p; 397109113Sdillon int pageKilo = getpagesize() / 1024; 398109097Sdillon 399109097Sdillon if (l2 != sizeof(*v)) { 400203917Suqs warnx("S_vmtotal %d != %zu", l2, sizeof(*v)); 401170558Sbde return (1); 402109097Sdillon } 403109097Sdillon 404109113Sdillon printf( 405109113Sdillon "\nSystem wide totals computed every five seconds:" 406109113Sdillon " (values in kilobytes)\n"); 407109097Sdillon printf("===============================================\n"); 408109113Sdillon printf( 409164718Sru "Processes:\t\t(RUNQ: %hd Disk Wait: %hd Page Wait: " 410164718Sru "%hd Sleep: %hd)\n", 411109113Sdillon v->t_rq, v->t_dw, v->t_pw, v->t_sl); 412109113Sdillon printf( 413212726Szec "Virtual Memory:\t\t(Total: %dK Active: %dK)\n", 414164718Sru v->t_vm * pageKilo, v->t_avm * pageKilo); 415212726Szec printf("Real Memory:\t\t(Total: %dK Active: %dK)\n", 416164718Sru v->t_rm * pageKilo, v->t_arm * pageKilo); 417164718Sru printf("Shared Virtual Memory:\t(Total: %dK Active: %dK)\n", 418164718Sru v->t_vmshr * pageKilo, v->t_avmshr * pageKilo); 419164718Sru printf("Shared Real Memory:\t(Total: %dK Active: %dK)\n", 420164718Sru v->t_rmshr * pageKilo, v->t_armshr * pageKilo); 421234260Seadler printf("Free Memory:\t%dK\n", v->t_free * pageKilo); 422122234Sdes 423109097Sdillon return (0); 424109097Sdillon} 425109097Sdillon 426109097Sdillonstatic int 427198340Sedset_IK(const char *str, int *val) 428161951Sume{ 429161951Sume float temp; 430161951Sume int len, kelv; 431198340Sed const char *p; 432198340Sed char *endptr; 433161951Sume 434161951Sume if ((len = strlen(str)) == 0) 435161951Sume return (0); 436161951Sume p = &str[len - 1]; 437161951Sume if (*p == 'C' || *p == 'F') { 438161951Sume temp = strtof(str, &endptr); 439198340Sed if (endptr == str || endptr != p) 440161951Sume return (0); 441161951Sume if (*p == 'F') 442161951Sume temp = (temp - 32) * 5 / 9; 443161951Sume kelv = temp * 10 + 2732; 444161951Sume } else { 445161951Sume kelv = (int)strtol(str, &endptr, 10); 446161951Sume if (endptr == str || *endptr != '\0') 447161951Sume return (0); 448161951Sume } 449161951Sume *val = kelv; 450161951Sume return (1); 451161951Sume} 452161951Sume 45312946Sphk/* 45412946Sphk * These functions uses a presently undocumented interface to the kernel 45512946Sphk * to walk the tree and get the type so it can print the value. 45612946Sphk * This interface is under work and consideration, and should probably 45712946Sphk * be killed with a big axe by the first person who can find the time. 45812946Sphk * (be aware though, that the proper interface isn't as obvious as it 45912946Sphk * may seem, there are various conflicting requirements. 46012946Sphk */ 4611553Srgrimes 46212946Sphkstatic int 46312946Sphkname2oid(char *name, int *oidp) 46412946Sphk{ 46512946Sphk int oid[2]; 46638533Sdfr int i; 46738533Sdfr size_t j; 4681553Srgrimes 46912946Sphk oid[0] = 0; 47012946Sphk oid[1] = 3; 4711553Srgrimes 47277928Sdd j = CTL_MAXNAME * sizeof(int); 47312946Sphk i = sysctl(oid, 2, oidp, &j, name, strlen(name)); 474122234Sdes if (i < 0) 475170512Sdwmalone return (i); 47677928Sdd j /= sizeof(int); 47712946Sphk return (j); 4781553Srgrimes} 4791553Srgrimes 48012946Sphkstatic int 48112946Sphkoidfmt(int *oid, int len, char *fmt, u_int *kind) 48212946Sphk{ 48312946Sphk int qoid[CTL_MAXNAME+2]; 48412946Sphk u_char buf[BUFSIZ]; 48538533Sdfr int i; 48638533Sdfr size_t j; 4871553Srgrimes 48812946Sphk qoid[0] = 0; 48912946Sphk qoid[1] = 4; 49012946Sphk memcpy(qoid + 2, oid, len * sizeof(int)); 4911553Srgrimes 49277928Sdd j = sizeof(buf); 49312946Sphk i = sysctl(qoid, len + 2, buf, &j, 0, 0); 49412946Sphk if (i) 495203917Suqs err(1, "sysctl fmt %d %zu %d", i, j, errno); 4961553Srgrimes 49712946Sphk if (kind) 49812946Sphk *kind = *(u_int *)buf; 49912946Sphk 50012946Sphk if (fmt) 50112946Sphk strcpy(fmt, (char *)(buf + sizeof(u_int))); 502170512Sdwmalone return (0); 5031553Srgrimes} 5041553Srgrimes 505217616Smdfstatic int ctl_sign[CTLTYPE+1] = { 506217616Smdf [CTLTYPE_INT] = 1, 507217616Smdf [CTLTYPE_LONG] = 1, 508217616Smdf [CTLTYPE_S64] = 1, 509217616Smdf}; 510217616Smdf 511217616Smdfstatic int ctl_size[CTLTYPE+1] = { 512217616Smdf [CTLTYPE_INT] = sizeof(int), 513217616Smdf [CTLTYPE_UINT] = sizeof(u_int), 514217616Smdf [CTLTYPE_LONG] = sizeof(long), 515217616Smdf [CTLTYPE_ULONG] = sizeof(u_long), 516217616Smdf [CTLTYPE_S64] = sizeof(int64_t), 517217616Smdf [CTLTYPE_U64] = sizeof(int64_t), 518217616Smdf}; 519217616Smdf 5201553Srgrimes/* 52112946Sphk * This formats and outputs the value of one variable 52212946Sphk * 52312946Sphk * Returns zero if anything was actually output. 52412946Sphk * Returns one if didn't know what to do with this. 52512946Sphk * Return minus one if we had errors. 5261553Srgrimes */ 52712946Sphkstatic int 52812946Sphkshow_var(int *oid, int nlen) 5291553Srgrimes{ 530162073Sru u_char buf[BUFSIZ], *val, *oval, *p; 531170513Sdwmalone char name[BUFSIZ], *fmt; 532170513Sdwmalone const char *sep, *sep1; 53312946Sphk int qoid[CTL_MAXNAME+2]; 534170512Sdwmalone uintmax_t umv; 535170512Sdwmalone intmax_t mv; 536217586Smdf int i, hexlen, sign, ctltype; 537170287Sdwmalone size_t intlen; 53838533Sdfr size_t j, len; 53912946Sphk u_int kind; 54077332Sdes int (*func)(int, void *); 5411553Srgrimes 542203917Suqs /* Silence GCC. */ 543203917Suqs umv = mv = intlen = 0; 544203917Suqs 545144997Smdodd bzero(buf, BUFSIZ); 546144997Smdodd bzero(name, BUFSIZ); 54742456Sdes qoid[0] = 0; 54842456Sdes memcpy(qoid + 2, oid, nlen * sizeof(int)); 54942456Sdes 55042456Sdes qoid[1] = 1; 55177928Sdd j = sizeof(name); 55242456Sdes i = sysctl(qoid, nlen + 2, name, &j, 0, 0); 55342456Sdes if (i || !j) 554203917Suqs err(1, "sysctl name %d %zu %d", i, j, errno); 55542456Sdes 55671034Sdes if (Nflag) { 55771034Sdes printf("%s", name); 55871034Sdes return (0); 55971034Sdes } 56071034Sdes 56185747Stobez if (eflag) 56285747Stobez sep = "="; 56385747Stobez else 56485747Stobez sep = ": "; 56585747Stobez 56688006Sluigi if (dflag) { /* just print description */ 56788006Sluigi qoid[1] = 5; 56888006Sluigi j = sizeof(buf); 56988006Sluigi i = sysctl(qoid, nlen + 2, buf, &j, 0, 0); 57088006Sluigi if (!nflag) 57188006Sluigi printf("%s%s", name, sep); 57288006Sluigi printf("%s", buf); 57388006Sluigi return (0); 57488006Sluigi } 57512946Sphk /* find an estimate of how much we need for this var */ 57612946Sphk j = 0; 57712946Sphk i = sysctl(oid, nlen, 0, &j, 0, 0); 57812946Sphk j += j; /* we want to be sure :-) */ 57912946Sphk 580162073Sru val = oval = malloc(j + 1); 581162073Sru if (val == NULL) { 582162073Sru warnx("malloc failed"); 583170558Sbde return (1); 584162073Sru } 58512946Sphk len = j; 58612946Sphk i = sysctl(oid, nlen, val, &len, 0, 0); 587162073Sru if (i || !len) { 588162073Sru free(oval); 58912946Sphk return (1); 590162073Sru } 59112946Sphk 59212946Sphk if (bflag) { 59312946Sphk fwrite(val, 1, len, stdout); 594162073Sru free(oval); 59512946Sphk return (0); 5961553Srgrimes } 59796234Sache val[len] = '\0'; 59888696Sphk fmt = buf; 59988696Sphk oidfmt(oid, nlen, fmt, &kind); 60012946Sphk p = val; 601217586Smdf ctltype = (kind & CTLTYPE); 602217616Smdf sign = ctl_sign[ctltype]; 603217616Smdf intlen = ctl_size[ctltype]; 604217616Smdf 605217586Smdf switch (ctltype) { 606217586Smdf case CTLTYPE_STRING: 60712946Sphk if (!nflag) 60885747Stobez printf("%s%s", name, sep); 609203917Suqs printf("%.*s", (int)len, p); 610162073Sru free(oval); 61112946Sphk return (0); 612122234Sdes 613217586Smdf case CTLTYPE_INT: 614217586Smdf case CTLTYPE_UINT: 615217586Smdf case CTLTYPE_LONG: 616217586Smdf case CTLTYPE_ULONG: 617217616Smdf case CTLTYPE_S64: 618217616Smdf case CTLTYPE_U64: 61912946Sphk if (!nflag) 62085747Stobez printf("%s%s", name, sep); 621170514Sdwmalone hexlen = 2 + (intlen * CHAR_BIT + 3) / 4; 622170513Sdwmalone sep1 = ""; 623170287Sdwmalone while (len >= intlen) { 624217586Smdf switch (kind & CTLTYPE) { 625217586Smdf case CTLTYPE_INT: 626217586Smdf case CTLTYPE_UINT: 627170514Sdwmalone umv = *(u_int *)p; 628170514Sdwmalone mv = *(int *)p; 629170287Sdwmalone break; 630217586Smdf case CTLTYPE_LONG: 631217586Smdf case CTLTYPE_ULONG: 632170514Sdwmalone umv = *(u_long *)p; 633170514Sdwmalone mv = *(long *)p; 634170287Sdwmalone break; 635217616Smdf case CTLTYPE_S64: 636217616Smdf case CTLTYPE_U64: 637217616Smdf umv = *(uint64_t *)p; 638217616Smdf mv = *(int64_t *)p; 639170287Sdwmalone break; 640170287Sdwmalone } 641170513Sdwmalone fputs(sep1, stdout); 642217586Smdf if (xflag) 643217586Smdf printf("%#0*jx", hexlen, umv); 644217586Smdf else if (!sign) 645170512Sdwmalone printf(hflag ? "%'ju" : "%ju", umv); 646170287Sdwmalone else if (fmt[1] == 'K') { 647170514Sdwmalone if (mv < 0) 648170512Sdwmalone printf("%jd", mv); 649134541Speter else 650170512Sdwmalone printf("%.1fC", (mv - 2732.0) / 10); 651134541Speter } else 652170513Sdwmalone printf(hflag ? "%'jd" : "%jd", mv); 653170513Sdwmalone sep1 = " "; 654170287Sdwmalone len -= intlen; 655170287Sdwmalone p += intlen; 65641019Sphk } 657162073Sru free(oval); 65812946Sphk return (0); 65912946Sphk 660217586Smdf case CTLTYPE_OPAQUE: 66112946Sphk i = 0; 66277332Sdes if (strcmp(fmt, "S,clockinfo") == 0) 66377332Sdes func = S_clockinfo; 66477332Sdes else if (strcmp(fmt, "S,timeval") == 0) 66577332Sdes func = S_timeval; 66677332Sdes else if (strcmp(fmt, "S,loadavg") == 0) 66777332Sdes func = S_loadavg; 668109097Sdillon else if (strcmp(fmt, "S,vmtotal") == 0) 669109097Sdillon func = S_vmtotal; 67077332Sdes else 67177332Sdes func = NULL; 67212946Sphk if (func) { 67312946Sphk if (!nflag) 67485747Stobez printf("%s%s", name, sep); 675163275Sharti i = (*func)(len, p); 676162073Sru free(oval); 677163275Sharti return (i); 67812946Sphk } 679102411Scharnier /* FALLTHROUGH */ 68012946Sphk default: 681162073Sru if (!oflag && !xflag) { 682162073Sru free(oval); 68312946Sphk return (1); 684162073Sru } 68512946Sphk if (!nflag) 68685747Stobez printf("%s%s", name, sep); 687203917Suqs printf("Format:%s Length:%zu Dump:0x", fmt, len); 68877332Sdes while (len-- && (xflag || p < val + 16)) 68912946Sphk printf("%02x", *p++); 69077332Sdes if (!xflag && len > 16) 69112946Sphk printf("..."); 692162073Sru free(oval); 69312946Sphk return (0); 6941553Srgrimes } 695162073Sru free(oval); 69612946Sphk return (1); 6971553Srgrimes} 6981553Srgrimes 69912946Sphkstatic int 700170512Sdwmalonesysctl_all(int *oid, int len) 7011553Srgrimes{ 70212946Sphk int name1[22], name2[22]; 70338533Sdfr int i, j; 70438533Sdfr size_t l1, l2; 7051553Srgrimes 70612946Sphk name1[0] = 0; 70712946Sphk name1[1] = 2; 70812946Sphk l1 = 2; 70912946Sphk if (len) { 71077928Sdd memcpy(name1+2, oid, len * sizeof(int)); 71112946Sphk l1 += len; 71212946Sphk } else { 71312946Sphk name1[2] = 1; 71412946Sphk l1++; 71512946Sphk } 71677332Sdes for (;;) { 71777928Sdd l2 = sizeof(name2); 71812946Sphk j = sysctl(name1, l1, name2, &l2, 0, 0); 71948956Sbillf if (j < 0) { 72012946Sphk if (errno == ENOENT) 721170512Sdwmalone return (0); 72212946Sphk else 723203917Suqs err(1, "sysctl(getnext) %d %zu", j, l2); 72448956Sbillf } 72512946Sphk 72677928Sdd l2 /= sizeof(int); 72712946Sphk 728170513Sdwmalone if (len < 0 || l2 < (unsigned int)len) 729170512Sdwmalone return (0); 73012946Sphk 73112946Sphk for (i = 0; i < len; i++) 73212946Sphk if (name2[i] != oid[i]) 733170512Sdwmalone return (0); 73412946Sphk 73512946Sphk i = show_var(name2, l2); 73612946Sphk if (!i && !bflag) 73712946Sphk putchar('\n'); 73812946Sphk 73977928Sdd memcpy(name1+2, name2, l2 * sizeof(int)); 74012946Sphk l1 = 2 + l2; 74112946Sphk } 7421553Srgrimes} 743