sysctl.c revision 164718
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: head/sbin/sysctl/sysctl.c 164718 2006-11-28 12:46:02Z ru $"; 421553Srgrimes#endif /* not lint */ 431553Srgrimes 4492066Sluigi#ifdef __i386__ 4592066Sluigi#include <sys/reboot.h> /* used for bootdev parsing */ 4692066Sluigi#endif 4791217Sbde#include <sys/param.h> 4891217Sbde#include <sys/time.h> 4991217Sbde#include <sys/resource.h> 501553Srgrimes#include <sys/stat.h> 511553Srgrimes#include <sys/sysctl.h> 52109097Sdillon#include <sys/vmmeter.h> 531553Srgrimes 5430602Scharnier#include <ctype.h> 5530602Scharnier#include <err.h> 561553Srgrimes#include <errno.h> 57122233Sdes#include <locale.h> 581553Srgrimes#include <stdio.h> 591553Srgrimes#include <stdlib.h> 601553Srgrimes#include <string.h> 6130602Scharnier#include <unistd.h> 621553Srgrimes 63150167Srwatsonstatic int aflag, bflag, dflag, eflag, hflag, Nflag, nflag, oflag; 64150167Srwatsonstatic int qflag, xflag; 651553Srgrimes 6612946Sphkstatic int oidfmt(int *, int, char *, u_int *); 6712946Sphkstatic void parse(char *); 6812946Sphkstatic int show_var(int *, int); 6912946Sphkstatic int sysctl_all (int *oid, int len); 7012946Sphkstatic int name2oid(char *, int *); 711553Srgrimes 72121542Speterstatic void set_T_dev_t (char *, void **, size_t *); 73161951Sumestatic int set_IK(char *, int *); 7488696Sphk 7512946Sphkstatic void 7612946Sphkusage(void) 7712946Sphk{ 781553Srgrimes 7977330Sdes (void)fprintf(stderr, "%s\n%s\n", 80152995Sru "usage: sysctl [-bdehNnoqx] name[=value] ...", 81152995Sru " sysctl [-bdehNnoqx] -a"); 8212946Sphk exit(1); 8312946Sphk} 841553Srgrimes 851553Srgrimesint 8612946Sphkmain(int argc, char **argv) 871553Srgrimes{ 8812946Sphk int ch; 89122233Sdes 90122233Sdes setlocale(LC_NUMERIC, ""); 9112946Sphk setbuf(stdout,0); 9212946Sphk setbuf(stderr,0); 931553Srgrimes 94150167Srwatson while ((ch = getopt(argc, argv, "AabdehNnoqwxX")) != -1) { 951553Srgrimes switch (ch) { 9671034Sdes case 'A': 9777330Sdes /* compatibility */ 9877330Sdes aflag = oflag = 1; 9971034Sdes break; 10071034Sdes case 'a': 10171034Sdes aflag = 1; 10271034Sdes break; 10371034Sdes case 'b': 10471034Sdes bflag = 1; 10571034Sdes break; 10688006Sluigi case 'd': 10788006Sluigi dflag = 1; 10888006Sluigi break; 10985747Stobez case 'e': 11085747Stobez eflag = 1; 11185747Stobez break; 112122233Sdes case 'h': 113122233Sdes hflag = 1; 114122233Sdes 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(); 1511553Srgrimes while (argc-- > 0) 15212946Sphk parse(*argv++); 1531553Srgrimes exit(0); 1541553Srgrimes} 1551553Srgrimes 1561553Srgrimes/* 1571553Srgrimes * Parse a name into a MIB entry. 1581553Srgrimes * Lookup and print out the MIB entry if it exists. 1591553Srgrimes * Set a new value if requested. 1601553Srgrimes */ 16112946Sphkstatic void 16212946Sphkparse(char *string) 1631553Srgrimes{ 16412946Sphk int len, i, j; 1651553Srgrimes void *newval = 0; 16678434Spirzyk int intval; 16778434Spirzyk unsigned int uintval; 16878434Spirzyk long longval; 16978434Spirzyk unsigned long ulongval; 17078434Spirzyk size_t newsize = 0; 1711553Srgrimes quad_t quadval; 1721553Srgrimes int mib[CTL_MAXNAME]; 173116383Srwatson char *cp, *bufp, buf[BUFSIZ], *endptr, fmt[BUFSIZ]; 17412946Sphk u_int kind; 1751553Srgrimes 1761553Srgrimes bufp = buf; 177140818Sssouhlal if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ) 178140818Sssouhlal errx(1, "oid too long: '%s'", string); 1791553Srgrimes if ((cp = strchr(string, '=')) != NULL) { 1801553Srgrimes *strchr(buf, '=') = '\0'; 1811553Srgrimes *cp++ = '\0'; 1821553Srgrimes while (isspace(*cp)) 1831553Srgrimes cp++; 1841553Srgrimes newval = cp; 1851553Srgrimes newsize = strlen(cp); 1861553Srgrimes } 18712946Sphk len = name2oid(bufp, mib); 1881553Srgrimes 189150167Srwatson if (len < 0) { 190150167Srwatson if (qflag) 191150167Srwatson exit(1); 192150167Srwatson else 193150167Srwatson errx(1, "unknown oid '%s'", bufp); 194150167Srwatson } 1951553Srgrimes 19688696Sphk if (oidfmt(mib, len, fmt, &kind)) 19730602Scharnier err(1, "couldn't find format of oid '%s'", bufp); 1981553Srgrimes 19977330Sdes if (newval == NULL) { 20012946Sphk if ((kind & CTLTYPE) == CTLTYPE_NODE) { 201144998Smdodd if (dflag) { 202144998Smdodd i = show_var(mib, len); 203144998Smdodd if (!i && !bflag) 204144998Smdodd putchar('\n'); 205144998Smdodd } 20612946Sphk sysctl_all(mib, len); 20712946Sphk } else { 20812946Sphk i = show_var(mib, len); 20912946Sphk if (!i && !bflag) 21012946Sphk putchar('\n'); 2111553Srgrimes } 21212946Sphk } else { 21312946Sphk if ((kind & CTLTYPE) == CTLTYPE_NODE) 21412946Sphk errx(1, "oid '%s' isn't a leaf node", bufp); 2151553Srgrimes 216121849Ssilby if (!(kind & CTLFLAG_WR)) { 217121306Ssilby if (kind & CTLFLAG_TUN) { 218121849Ssilby warnx("oid '%s' is a read only tunable", bufp); 219121849Ssilby errx(1, "Tunable values are set in /boot/loader.conf"); 220121306Ssilby } else { 221121306Ssilby errx(1, "oid '%s' is read only", bufp); 222121849Ssilby } 223121306Ssilby } 224116383Srwatson 225116383Srwatson if ((kind & CTLTYPE) == CTLTYPE_INT || 226116383Srwatson (kind & CTLTYPE) == CTLTYPE_UINT || 227116383Srwatson (kind & CTLTYPE) == CTLTYPE_LONG || 228126472Sdd (kind & CTLTYPE) == CTLTYPE_ULONG || 229126472Sdd (kind & CTLTYPE) == CTLTYPE_QUAD) { 230116383Srwatson if (strlen(newval) == 0) 231116383Srwatson errx(1, "empty numeric value"); 232116383Srwatson } 233122234Sdes 23412946Sphk switch (kind & CTLTYPE) { 23512946Sphk case CTLTYPE_INT: 236161951Sume if (strcmp(fmt, "IK") == 0) { 237161951Sume if (!set_IK((char*)newval, &intval)) 238161951Sume errx(1, "invalid value '%s'", 239161951Sume newval); 240161951Sume } else { 241161951Sume intval = (int)strtol(newval, &endptr, 242161951Sume 0); 243161951Sume if (endptr == newval || *endptr != '\0') 244161951Sume errx(1, "invalid integer '%s'", 245161951Sume newval); 246161951Sume } 24712946Sphk newval = &intval; 24877928Sdd newsize = sizeof(intval); 2491553Srgrimes break; 25078434Spirzyk case CTLTYPE_UINT: 251116383Srwatson uintval = (int) strtoul(newval, &endptr, 0); 252116383Srwatson if (endptr == newval || *endptr != '\0') 253116383Srwatson errx(1, "invalid unsigned integer '%s'", 254116383Srwatson newval); 25578434Spirzyk newval = &uintval; 25678434Spirzyk newsize = sizeof uintval; 25712946Sphk break; 25878434Spirzyk case CTLTYPE_LONG: 259116383Srwatson longval = strtol(newval, &endptr, 0); 260116383Srwatson if (endptr == newval || *endptr != '\0') 261116383Srwatson errx(1, "invalid long integer '%s'", 262116383Srwatson newval); 26378434Spirzyk newval = &longval; 26478434Spirzyk newsize = sizeof longval; 26578434Spirzyk break; 26678434Spirzyk case CTLTYPE_ULONG: 267116383Srwatson ulongval = strtoul(newval, &endptr, 0); 268116383Srwatson if (endptr == newval || *endptr != '\0') 269116383Srwatson errx(1, "invalid unsigned long integer" 270116383Srwatson " '%s'", newval); 27178434Spirzyk newval = &ulongval; 27278434Spirzyk newsize = sizeof ulongval; 27378434Spirzyk break; 27412946Sphk case CTLTYPE_STRING: 27512946Sphk break; 27612946Sphk case CTLTYPE_QUAD: 27712946Sphk sscanf(newval, "%qd", &quadval); 27812946Sphk newval = &quadval; 27977928Sdd newsize = sizeof(quadval); 28012946Sphk break; 28188696Sphk case CTLTYPE_OPAQUE: 28288696Sphk if (strcmp(fmt, "T,dev_t") == 0) { 28388696Sphk set_T_dev_t ((char*)newval, &newval, &newsize); 28488696Sphk break; 28588696Sphk } 28688696Sphk /* FALLTHROUGH */ 28712946Sphk default: 28812946Sphk errx(1, "oid '%s' is type %d," 28931214Sjdp " cannot set that", bufp, 29031214Sjdp kind & CTLTYPE); 2911553Srgrimes } 2921553Srgrimes 29312946Sphk i = show_var(mib, len); 29412946Sphk if (sysctl(mib, len, 0, 0, newval, newsize) == -1) { 29512946Sphk if (!i && !bflag) 29612946Sphk putchar('\n'); 29712946Sphk switch (errno) { 29812946Sphk case EOPNOTSUPP: 299122234Sdes errx(1, "%s: value is not available", 30012946Sphk string); 30112946Sphk case ENOTDIR: 302122234Sdes errx(1, "%s: specification is incomplete", 30312946Sphk string); 30412946Sphk case ENOMEM: 305122234Sdes errx(1, "%s: type is unknown to this program", 30612946Sphk string); 30712946Sphk default: 30830602Scharnier warn("%s", string); 30912946Sphk return; 31012946Sphk } 31112946Sphk } 31212946Sphk if (!bflag) 31312946Sphk printf(" -> "); 31412946Sphk i = nflag; 31512946Sphk nflag = 1; 31612946Sphk j = show_var(mib, len); 31712946Sphk if (!j && !bflag) 31812946Sphk putchar('\n'); 31912946Sphk nflag = i; 32012946Sphk } 32112946Sphk} 3221553Srgrimes 32312946Sphk/* These functions will dump out various interesting structures. */ 3241553Srgrimes 32512946Sphkstatic int 32612946SphkS_clockinfo(int l2, void *p) 32712946Sphk{ 32812946Sphk struct clockinfo *ci = (struct clockinfo*)p; 32997232Salfred if (l2 != sizeof(*ci)) { 33097232Salfred warnx("S_clockinfo %d != %d", l2, sizeof(*ci)); 33197232Salfred return (0); 33297232Salfred } 333122233Sdes printf(hflag ? "{ hz = %'d, tick = %'d, profhz = %'d, stathz = %'d }" : 334122233Sdes "{ hz = %d, tick = %d, profhz = %d, stathz = %d }", 33594752Sphk ci->hz, ci->tick, ci->profhz, ci->stathz); 33612946Sphk return (0); 33712946Sphk} 3381553Srgrimes 33912946Sphkstatic int 34012946SphkS_loadavg(int l2, void *p) 34112946Sphk{ 34212946Sphk struct loadavg *tv = (struct loadavg*)p; 3438857Srgrimes 34497232Salfred if (l2 != sizeof(*tv)) { 34597232Salfred warnx("S_loadavg %d != %d", l2, sizeof(*tv)); 34697232Salfred return (0); 34797232Salfred } 348122233Sdes printf(hflag ? "{ %'.2f %'.2f %'.2f }" : "{ %.2f %.2f %.2f }", 34912946Sphk (double)tv->ldavg[0]/(double)tv->fscale, 35012946Sphk (double)tv->ldavg[1]/(double)tv->fscale, 35112946Sphk (double)tv->ldavg[2]/(double)tv->fscale); 35212946Sphk return (0); 35312946Sphk} 3541553Srgrimes 35512946Sphkstatic int 35612946SphkS_timeval(int l2, void *p) 35712946Sphk{ 35812946Sphk struct timeval *tv = (struct timeval*)p; 35937266Sbde time_t tv_sec; 36012946Sphk char *p1, *p2; 3611553Srgrimes 36297232Salfred if (l2 != sizeof(*tv)) { 36397232Salfred warnx("S_timeval %d != %d", l2, sizeof(*tv)); 36497232Salfred return (0); 36597232Salfred } 366122233Sdes printf(hflag ? "{ sec = %'ld, usec = %'ld } " : 367122233Sdes "{ sec = %ld, usec = %ld } ", 36812946Sphk tv->tv_sec, tv->tv_usec); 36937266Sbde tv_sec = tv->tv_sec; 37037266Sbde p1 = strdup(ctime(&tv_sec)); 37112946Sphk for (p2=p1; *p2 ; p2++) 37212946Sphk if (*p2 == '\n') 37312946Sphk *p2 = '\0'; 37412946Sphk fputs(p1, stdout); 37512946Sphk return (0); 37612946Sphk} 3771553Srgrimes 37812946Sphkstatic int 379109097SdillonS_vmtotal(int l2, void *p) 380109097Sdillon{ 381109097Sdillon struct vmtotal *v = (struct vmtotal *)p; 382109113Sdillon int pageKilo = getpagesize() / 1024; 383109097Sdillon 384109097Sdillon if (l2 != sizeof(*v)) { 385109097Sdillon warnx("S_vmtotal %d != %d", l2, sizeof(*v)); 386109097Sdillon return (0); 387109097Sdillon } 388109097Sdillon 389109113Sdillon printf( 390109113Sdillon "\nSystem wide totals computed every five seconds:" 391109113Sdillon " (values in kilobytes)\n"); 392109097Sdillon printf("===============================================\n"); 393109113Sdillon printf( 394164718Sru "Processes:\t\t(RUNQ: %hd Disk Wait: %hd Page Wait: " 395164718Sru "%hd Sleep: %hd)\n", 396109113Sdillon v->t_rq, v->t_dw, v->t_pw, v->t_sl); 397109113Sdillon printf( 398164718Sru "Virtual Memory:\t\t(Total: %dK, Active %dK)\n", 399164718Sru v->t_vm * pageKilo, v->t_avm * pageKilo); 400164718Sru printf("Real Memory:\t\t(Total: %dK Active %dK)\n", 401164718Sru v->t_rm * pageKilo, v->t_arm * pageKilo); 402164718Sru printf("Shared Virtual Memory:\t(Total: %dK Active: %dK)\n", 403164718Sru v->t_vmshr * pageKilo, v->t_avmshr * pageKilo); 404164718Sru printf("Shared Real Memory:\t(Total: %dK Active: %dK)\n", 405164718Sru v->t_rmshr * pageKilo, v->t_armshr * pageKilo); 406164718Sru printf("Free Memory Pages:\t%dK\n", v->t_free * pageKilo); 407122234Sdes 408109097Sdillon return (0); 409109097Sdillon} 410109097Sdillon 411109097Sdillonstatic int 41212946SphkT_dev_t(int l2, void *p) 41312946Sphk{ 41412946Sphk dev_t *d = (dev_t *)p; 41597232Salfred if (l2 != sizeof(*d)) { 41697232Salfred warnx("T_dev_T %d != %d", l2, sizeof(*d)); 41797232Salfred return (0); 41897232Salfred } 41961514Sphk if ((int)(*d) != -1) { 42061514Sphk if (minor(*d) > 255 || minor(*d) < 0) 42161514Sphk printf("{ major = %d, minor = 0x%x }", 42261514Sphk major(*d), minor(*d)); 42361514Sphk else 42461514Sphk printf("{ major = %d, minor = %d }", 42561514Sphk major(*d), minor(*d)); 42661514Sphk } 42712946Sphk return (0); 42812946Sphk} 4291553Srgrimes 43088696Sphkstatic void 431121542Speterset_T_dev_t (char *path, void **val, size_t *size) 43288696Sphk{ 43388696Sphk static struct stat statb; 43488696Sphk 43588696Sphk if (strcmp(path, "none") && strcmp(path, "off")) { 43688696Sphk int rc = stat (path, &statb); 43788696Sphk if (rc) { 43888696Sphk err(1, "cannot stat %s", path); 43988696Sphk } 44088696Sphk 44188696Sphk if (!S_ISCHR(statb.st_mode)) { 44288696Sphk errx(1, "must specify a device special file."); 44388696Sphk } 44488696Sphk } else { 44588696Sphk statb.st_rdev = NODEV; 44688696Sphk } 44788696Sphk *val = (char*) &statb.st_rdev; 44888696Sphk *size = sizeof statb.st_rdev; 44988696Sphk} 45088696Sphk 451161951Sumestatic int 452161951Sumeset_IK(char *str, int *val) 453161951Sume{ 454161951Sume float temp; 455161951Sume int len, kelv; 456161951Sume char *p, *endptr; 457161951Sume 458161951Sume if ((len = strlen(str)) == 0) 459161951Sume return (0); 460161951Sume p = &str[len - 1]; 461161951Sume if (*p == 'C' || *p == 'F') { 462161951Sume *p = '\0'; 463161951Sume temp = strtof(str, &endptr); 464161951Sume if (endptr == str || *endptr != '\0') 465161951Sume return (0); 466161951Sume if (*p == 'F') 467161951Sume temp = (temp - 32) * 5 / 9; 468161951Sume kelv = temp * 10 + 2732; 469161951Sume } else { 470161951Sume kelv = (int)strtol(str, &endptr, 10); 471161951Sume if (endptr == str || *endptr != '\0') 472161951Sume return (0); 473161951Sume } 474161951Sume *val = kelv; 475161951Sume return (1); 476161951Sume} 477161951Sume 47812946Sphk/* 47912946Sphk * These functions uses a presently undocumented interface to the kernel 48012946Sphk * to walk the tree and get the type so it can print the value. 48112946Sphk * This interface is under work and consideration, and should probably 48212946Sphk * be killed with a big axe by the first person who can find the time. 48312946Sphk * (be aware though, that the proper interface isn't as obvious as it 48412946Sphk * may seem, there are various conflicting requirements. 48512946Sphk */ 4861553Srgrimes 48712946Sphkstatic int 48812946Sphkname2oid(char *name, int *oidp) 48912946Sphk{ 49012946Sphk int oid[2]; 49138533Sdfr int i; 49238533Sdfr size_t j; 4931553Srgrimes 49412946Sphk oid[0] = 0; 49512946Sphk oid[1] = 3; 4961553Srgrimes 49777928Sdd j = CTL_MAXNAME * sizeof(int); 49812946Sphk i = sysctl(oid, 2, oidp, &j, name, strlen(name)); 499122234Sdes if (i < 0) 50012946Sphk return i; 50177928Sdd j /= sizeof(int); 50212946Sphk return (j); 5031553Srgrimes} 5041553Srgrimes 50512946Sphkstatic int 50612946Sphkoidfmt(int *oid, int len, char *fmt, u_int *kind) 50712946Sphk{ 50812946Sphk int qoid[CTL_MAXNAME+2]; 50912946Sphk u_char buf[BUFSIZ]; 51038533Sdfr int i; 51138533Sdfr size_t j; 5121553Srgrimes 51312946Sphk qoid[0] = 0; 51412946Sphk qoid[1] = 4; 51512946Sphk memcpy(qoid + 2, oid, len * sizeof(int)); 5161553Srgrimes 51777928Sdd j = sizeof(buf); 51812946Sphk i = sysctl(qoid, len + 2, buf, &j, 0, 0); 51912946Sphk if (i) 52030602Scharnier err(1, "sysctl fmt %d %d %d", i, j, errno); 5211553Srgrimes 52212946Sphk if (kind) 52312946Sphk *kind = *(u_int *)buf; 52412946Sphk 52512946Sphk if (fmt) 52612946Sphk strcpy(fmt, (char *)(buf + sizeof(u_int))); 52712946Sphk return 0; 5281553Srgrimes} 5291553Srgrimes 5301553Srgrimes/* 53112946Sphk * This formats and outputs the value of one variable 53212946Sphk * 53312946Sphk * Returns zero if anything was actually output. 53412946Sphk * Returns one if didn't know what to do with this. 53512946Sphk * Return minus one if we had errors. 5361553Srgrimes */ 53712946Sphk 53812946Sphkstatic int 53912946Sphkshow_var(int *oid, int nlen) 5401553Srgrimes{ 541162073Sru u_char buf[BUFSIZ], *val, *oval, *p; 54285747Stobez char name[BUFSIZ], *fmt, *sep; 54312946Sphk int qoid[CTL_MAXNAME+2]; 54438533Sdfr int i; 54538533Sdfr size_t j, len; 54612946Sphk u_int kind; 54777332Sdes int (*func)(int, void *); 5481553Srgrimes 549144997Smdodd bzero(buf, BUFSIZ); 550144997Smdodd bzero(name, BUFSIZ); 55142456Sdes qoid[0] = 0; 55242456Sdes memcpy(qoid + 2, oid, nlen * sizeof(int)); 55342456Sdes 55442456Sdes qoid[1] = 1; 55577928Sdd j = sizeof(name); 55642456Sdes i = sysctl(qoid, nlen + 2, name, &j, 0, 0); 55742456Sdes if (i || !j) 55842456Sdes err(1, "sysctl name %d %d %d", i, j, errno); 55942456Sdes 56071034Sdes if (Nflag) { 56171034Sdes printf("%s", name); 56271034Sdes return (0); 56371034Sdes } 56471034Sdes 56585747Stobez if (eflag) 56685747Stobez sep = "="; 56785747Stobez else 56885747Stobez sep = ": "; 56985747Stobez 57088006Sluigi if (dflag) { /* just print description */ 57188006Sluigi qoid[1] = 5; 57288006Sluigi j = sizeof(buf); 57388006Sluigi i = sysctl(qoid, nlen + 2, buf, &j, 0, 0); 57488006Sluigi if (!nflag) 57588006Sluigi printf("%s%s", name, sep); 57688006Sluigi printf("%s", buf); 57788006Sluigi return (0); 57888006Sluigi } 57912946Sphk /* find an estimate of how much we need for this var */ 58012946Sphk j = 0; 58112946Sphk i = sysctl(oid, nlen, 0, &j, 0, 0); 58212946Sphk j += j; /* we want to be sure :-) */ 58312946Sphk 584162073Sru val = oval = malloc(j + 1); 585162073Sru if (val == NULL) { 586162073Sru warnx("malloc failed"); 587162073Sru return (-1); 588162073Sru } 58912946Sphk len = j; 59012946Sphk i = sysctl(oid, nlen, val, &len, 0, 0); 591162073Sru if (i || !len) { 592162073Sru free(oval); 59312946Sphk return (1); 594162073Sru } 59512946Sphk 59612946Sphk if (bflag) { 59712946Sphk fwrite(val, 1, len, stdout); 598162073Sru free(oval); 59912946Sphk return (0); 6001553Srgrimes } 60196234Sache val[len] = '\0'; 60288696Sphk fmt = buf; 60388696Sphk oidfmt(oid, nlen, fmt, &kind); 60412946Sphk p = val; 60512946Sphk switch (*fmt) { 60612946Sphk case 'A': 60712946Sphk if (!nflag) 60885747Stobez printf("%s%s", name, sep); 609106829Speter printf("%.*s", len, p); 610162073Sru free(oval); 61112946Sphk return (0); 612122234Sdes 61312946Sphk case 'I': 61412946Sphk if (!nflag) 61585747Stobez printf("%s%s", name, sep); 61662622Sjhb fmt++; 61741019Sphk val = ""; 61841019Sphk while (len >= sizeof(int)) { 619122233Sdes fputs(val, stdout); 620160963Snjl if (*fmt == 'U') 621161256Sobrien printf(hflag ? "%'u" : "%u", 622161256Sobrien *(unsigned int *)p); 623161256Sobrien else if (*fmt == 'X') 624161256Sobrien printf(hflag ? "%'#010x" : "%#010x", 625161256Sobrien *(unsigned int *)p); 626134541Speter else if (*fmt == 'K') { 627161313Sru if (*(int *)p < 0) 628161313Sru printf("%d", *(int *)p); 629134541Speter else 630160963Snjl printf("%.1fC", 631161313Sru (*(int *)p - 2732.0) / 10); 632134541Speter } else 633122233Sdes printf(hflag ? "%'d" : "%d", *(int *)p); 63441019Sphk val = " "; 63577332Sdes len -= sizeof(int); 63677332Sdes p += sizeof(int); 63741019Sphk } 638162073Sru free(oval); 63912946Sphk return (0); 64012946Sphk 64138533Sdfr case 'L': 64238533Sdfr if (!nflag) 64385747Stobez printf("%s%s", name, sep); 64462622Sjhb fmt++; 64562975Sphk val = ""; 64662975Sphk while (len >= sizeof(long)) { 647122233Sdes fputs(val, stdout); 648160963Snjl if (*fmt == 'U') 649161256Sobrien printf(hflag ? "%'lu" : "%lu", 650161256Sobrien *(unsigned long *)p); 651161256Sobrien else if (*fmt == 'X') 652161256Sobrien printf(hflag ? "%'#018lx" : "%#018lx", 653161256Sobrien *(unsigned long *)p); 654134541Speter else if (*fmt == 'K') { 655134541Speter if (*(long *)p < 0) 656134541Speter printf("%ld", *(long *)p); 657134541Speter else 658160963Snjl printf("%.1fC", 659160963Snjl (*(long *)p - 2732.0) / 10); 660134541Speter } else 661122233Sdes printf(hflag ? "%'ld" : "%ld", *(long *)p); 66262975Sphk val = " "; 66377332Sdes len -= sizeof(long); 66477332Sdes p += sizeof(long); 66562975Sphk } 666162073Sru free(oval); 66738533Sdfr return (0); 66838533Sdfr 66938533Sdfr case 'P': 67038533Sdfr if (!nflag) 67185747Stobez printf("%s%s", name, sep); 67238533Sdfr printf("%p", *(void **)p); 673162073Sru free(oval); 67438533Sdfr return (0); 67538533Sdfr 67612946Sphk case 'T': 67712946Sphk case 'S': 67812946Sphk i = 0; 67977332Sdes if (strcmp(fmt, "S,clockinfo") == 0) 68077332Sdes func = S_clockinfo; 68177332Sdes else if (strcmp(fmt, "S,timeval") == 0) 68277332Sdes func = S_timeval; 68377332Sdes else if (strcmp(fmt, "S,loadavg") == 0) 68477332Sdes func = S_loadavg; 685109097Sdillon else if (strcmp(fmt, "S,vmtotal") == 0) 686109097Sdillon func = S_vmtotal; 68777332Sdes else if (strcmp(fmt, "T,dev_t") == 0) 68877332Sdes func = T_dev_t; 68977332Sdes else 69077332Sdes func = NULL; 69112946Sphk if (func) { 69212946Sphk if (!nflag) 69385747Stobez printf("%s%s", name, sep); 694163275Sharti i = (*func)(len, p); 695162073Sru free(oval); 696163275Sharti return (i); 69712946Sphk } 698102411Scharnier /* FALLTHROUGH */ 69912946Sphk default: 700162073Sru if (!oflag && !xflag) { 701162073Sru free(oval); 70212946Sphk return (1); 703162073Sru } 70412946Sphk if (!nflag) 70585747Stobez printf("%s%s", name, sep); 70612946Sphk printf("Format:%s Length:%d Dump:0x", fmt, len); 70777332Sdes while (len-- && (xflag || p < val + 16)) 70812946Sphk printf("%02x", *p++); 70977332Sdes if (!xflag && len > 16) 71012946Sphk printf("..."); 711162073Sru free(oval); 71212946Sphk return (0); 7131553Srgrimes } 714162073Sru free(oval); 71512946Sphk return (1); 7161553Srgrimes} 7171553Srgrimes 71812946Sphkstatic int 71912946Sphksysctl_all (int *oid, int len) 7201553Srgrimes{ 72112946Sphk int name1[22], name2[22]; 72238533Sdfr int i, j; 72338533Sdfr size_t l1, l2; 7241553Srgrimes 72512946Sphk name1[0] = 0; 72612946Sphk name1[1] = 2; 72712946Sphk l1 = 2; 72812946Sphk if (len) { 72977928Sdd memcpy(name1+2, oid, len * sizeof(int)); 73012946Sphk l1 += len; 73112946Sphk } else { 73212946Sphk name1[2] = 1; 73312946Sphk l1++; 73412946Sphk } 73577332Sdes for (;;) { 73677928Sdd l2 = sizeof(name2); 73712946Sphk j = sysctl(name1, l1, name2, &l2, 0, 0); 73848956Sbillf if (j < 0) { 73912946Sphk if (errno == ENOENT) 74012946Sphk return 0; 74112946Sphk else 74230602Scharnier err(1, "sysctl(getnext) %d %d", j, l2); 74348956Sbillf } 74412946Sphk 74577928Sdd l2 /= sizeof(int); 74612946Sphk 74712946Sphk if (l2 < len) 74812946Sphk return 0; 74912946Sphk 75012946Sphk for (i = 0; i < len; i++) 75112946Sphk if (name2[i] != oid[i]) 75212946Sphk return 0; 75312946Sphk 75412946Sphk i = show_var(name2, l2); 75512946Sphk if (!i && !bflag) 75612946Sphk putchar('\n'); 75712946Sphk 75877928Sdd memcpy(name1+2, name2, l2 * sizeof(int)); 75912946Sphk l1 = 2 + l2; 76012946Sphk } 7611553Srgrimes} 762