sysctl.c revision 212726
1163953Srrs/* 2169382Srrs * Copyright (c) 1993 3235828Stuexen * The Regents of the University of California. All rights reserved. 4235828Stuexen * 5163953Srrs * Redistribution and use in source and binary forms, with or without 6163953Srrs * modification, are permitted provided that the following conditions 7163953Srrs * are met: 8163953Srrs * 1. Redistributions of source code must retain the above copyright 9163953Srrs * notice, this list of conditions and the following disclaimer. 10228653Stuexen * 2. Redistributions in binary form must reproduce the above copyright 11163953Srrs * notice, this list of conditions and the following disclaimer in the 12163953Srrs * documentation and/or other materials provided with the distribution. 13163953Srrs * 4. Neither the name of the University nor the names of its contributors 14228653Stuexen * may be used to endorse or promote products derived from this software 15163953Srrs * without specific prior written permission. 16163953Srrs * 17163953Srrs * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18163953Srrs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19163953Srrs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20163953Srrs * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21163953Srrs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22163953Srrs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23163953Srrs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24163953Srrs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25163953Srrs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26163953Srrs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27163953Srrs * SUCH DAMAGE. 28163953Srrs */ 29163953Srrs 30163953Srrs#ifndef lint 31163953Srrsstatic const char copyright[] = 32163953Srrs"@(#) Copyright (c) 1993\n\ 33163953Srrs The Regents of the University of California. All rights reserved.\n"; 34163957Srrs#endif /* not lint */ 35235828Stuexen 36163953Srrs#ifndef lint 37163953Srrs#if 0 38167598Srrsstatic char sccsid[] = "@(#)from: sysctl.c 8.1 (Berkeley) 6/6/93"; 39163953Srrs#endif 40163953Srrsstatic const char rcsid[] = 41163953Srrs "$FreeBSD: head/sbin/sysctl/sysctl.c 212726 2010-09-16 10:53:01Z zec $"; 42163953Srrs#endif /* not lint */ 43163953Srrs 44172091Srrs#include <sys/param.h> 45163953Srrs#include <sys/time.h> 46163953Srrs#include <sys/resource.h> 47163953Srrs#include <sys/stat.h> 48163953Srrs#include <sys/sysctl.h> 49163953Srrs#include <sys/vmmeter.h> 50163953Srrs 51163953Srrs#include <ctype.h> 52163953Srrs#include <err.h> 53163953Srrs#include <errno.h> 54237715Stuexen#include <inttypes.h> 55163953Srrs#include <locale.h> 56163953Srrs#include <stdio.h> 57163953Srrs#include <stdlib.h> 58163953Srrs#include <string.h> 59171477Srrs#include <unistd.h> 60171477Srrs 61171477Srrsstatic int aflag, bflag, dflag, eflag, hflag, iflag; 62171477Srrsstatic int Nflag, nflag, oflag, qflag, xflag, warncount; 63171477Srrs 64171477Srrsstatic int oidfmt(int *, int, char *, u_int *); 65163953Srrsstatic void parse(char *); 66163953Srrsstatic int show_var(int *, int); 67163953Srrsstatic int sysctl_all(int *oid, int len); 68163953Srrsstatic int name2oid(char *, int *); 69163953Srrs 70163953Srrsstatic void set_T_dev_t(char *, void **, size_t *); 71171477Srrsstatic int set_IK(const char *, int *); 72171477Srrs 73171477Srrsstatic void 74171477Srrsusage(void) 75163953Srrs{ 76163953Srrs 77163953Srrs (void)fprintf(stderr, "%s\n%s\n", 78163953Srrs "usage: sysctl [-bdehiNnoqx] name[=value] ...", 79163953Srrs " sysctl [-bdehNnoqx] -a"); 80163953Srrs exit(1); 81163953Srrs} 82163953Srrs 83243882Sglebiusint 84163953Srrsmain(int argc, char **argv) 85169420Srrs{ 86169420Srrs int ch; 87228907Stuexen 88163953Srrs setlocale(LC_NUMERIC, ""); 89163953Srrs setbuf(stdout,0); 90163953Srrs setbuf(stderr,0); 91163953Srrs 92163953Srrs while ((ch = getopt(argc, argv, "AabdehiNnoqwxX")) != -1) { 93165647Srrs switch (ch) { 94163953Srrs case 'A': 95163953Srrs /* compatibility */ 96228907Stuexen aflag = oflag = 1; 97163953Srrs break; 98163953Srrs case 'a': 99163953Srrs aflag = 1; 100163953Srrs break; 101163953Srrs case 'b': 102163953Srrs bflag = 1; 103163953Srrs break; 104163953Srrs case 'd': 105163953Srrs dflag = 1; 106163953Srrs break; 107163953Srrs case 'e': 108163953Srrs eflag = 1; 109163953Srrs break; 110163953Srrs case 'h': 111243882Sglebius hflag = 1; 112163953Srrs break; 113169420Srrs case 'i': 114169420Srrs iflag = 1; 115228907Stuexen break; 116163953Srrs case 'N': 117163953Srrs Nflag = 1; 118163953Srrs break; 119163953Srrs case 'n': 120163953Srrs nflag = 1; 121163953Srrs break; 122163953Srrs case 'o': 123163953Srrs oflag = 1; 124163953Srrs break; 125163953Srrs case 'q': 126163953Srrs qflag = 1; 127163953Srrs break; 128169420Srrs case 'w': 129169420Srrs /* compatibility */ 130169420Srrs /* ignored */ 131163953Srrs break; 132228907Stuexen case 'X': 133163953Srrs /* compatibility */ 134163953Srrs aflag = xflag = 1; 135163953Srrs break; 136163953Srrs case 'x': 137163953Srrs xflag = 1; 138165647Srrs break; 139163953Srrs default: 140163953Srrs usage(); 141163953Srrs } 142228907Stuexen } 143163953Srrs argc -= optind; 144163953Srrs argv += optind; 145163953Srrs 146237715Stuexen if (Nflag && nflag) 147224641Stuexen usage(); 148163953Srrs if (aflag && argc == 0) 149224641Stuexen exit(sysctl_all(0, 0)); 150163953Srrs if (argc == 0) 151237715Stuexen usage(); 152221249Stuexen 153258454Stuexen warncount = 0; 154258454Stuexen while (argc-- > 0) 155258454Stuexen parse(*argv++); 156258454Stuexen exit(warncount); 157258454Stuexen} 158258454Stuexen 159163953Srrs/* 160163953Srrs * Parse a name into a MIB entry. 161225571Stuexen * Lookup and print out the MIB entry if it exists. 162163953Srrs * Set a new value if requested. 163221249Stuexen */ 164221249Stuexenstatic void 165221249Stuexenparse(char *string) 166221249Stuexen{ 167221249Stuexen int len, i, j; 168163953Srrs void *newval = 0; 169163953Srrs int intval; 170163953Srrs unsigned int uintval; 171163953Srrs long longval; 172221249Stuexen unsigned long ulongval; 173163953Srrs size_t newsize = 0; 174163953Srrs quad_t quadval; 175221249Stuexen int mib[CTL_MAXNAME]; 176221249Stuexen char *cp, *bufp, buf[BUFSIZ], *endptr, fmt[BUFSIZ]; 177258454Stuexen u_int kind; 178221249Stuexen 179258454Stuexen bufp = buf; 180163953Srrs if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ) 181163953Srrs errx(1, "oid too long: '%s'", string); 182221249Stuexen if ((cp = strchr(string, '=')) != NULL) { 183163953Srrs *strchr(buf, '=') = '\0'; 184163953Srrs *cp++ = '\0'; 185163953Srrs while (isspace(*cp)) 186228907Stuexen cp++; 187163953Srrs newval = cp; 188221249Stuexen newsize = strlen(cp); 189163953Srrs } 190163953Srrs len = name2oid(bufp, mib); 191163953Srrs 192163953Srrs if (len < 0) { 193163953Srrs if (iflag) 194163953Srrs return; 195225571Stuexen if (qflag) 196225571Stuexen exit(1); 197225584Stuexen else 198225571Stuexen errx(1, "unknown oid '%s'", bufp); 199163953Srrs } 200163953Srrs 201169420Srrs if (oidfmt(mib, len, fmt, &kind)) 202169420Srrs err(1, "couldn't find format of oid '%s'", bufp); 203163953Srrs 204221249Stuexen if (newval == NULL) { 205221249Stuexen if ((kind & CTLTYPE) == CTLTYPE_NODE) { 206163953Srrs if (dflag) { 207163953Srrs i = show_var(mib, len); 208163953Srrs if (!i && !bflag) 209228907Stuexen putchar('\n'); 210163953Srrs } 211221249Stuexen sysctl_all(mib, len); 212163953Srrs } else { 213163953Srrs i = show_var(mib, len); 214163953Srrs if (!i && !bflag) 215163953Srrs putchar('\n'); 216163953Srrs } 217163953Srrs } else { 218163953Srrs if ((kind & CTLTYPE) == CTLTYPE_NODE) 219225571Stuexen errx(1, "oid '%s' isn't a leaf node", bufp); 220225571Stuexen 221225571Stuexen if (!(kind & CTLFLAG_WR)) { 222163953Srrs if (kind & CTLFLAG_TUN) { 223163953Srrs warnx("oid '%s' is a read only tunable", bufp); 224169420Srrs errx(1, "Tunable values are set in /boot/loader.conf"); 225169420Srrs } else { 226221249Stuexen errx(1, "oid '%s' is read only", bufp); 227169420Srrs } 228163953Srrs } 229163953Srrs 230225571Stuexen if ((kind & CTLTYPE) == CTLTYPE_INT || 231163953Srrs (kind & CTLTYPE) == CTLTYPE_UINT || 232228907Stuexen (kind & CTLTYPE) == CTLTYPE_LONG || 233163953Srrs (kind & CTLTYPE) == CTLTYPE_ULONG || 234163953Srrs (kind & CTLTYPE) == CTLTYPE_QUAD) { 235163953Srrs if (strlen(newval) == 0) 236179783Srrs errx(1, "empty numeric value"); 237237715Stuexen } 238169420Srrs 239169420Srrs switch (kind & CTLTYPE) { 240237715Stuexen case CTLTYPE_INT: 241163953Srrs if (strcmp(fmt, "IK") == 0) { 242163953Srrs if (!set_IK(newval, &intval)) 243225571Stuexen errx(1, "invalid value '%s'", 244225571Stuexen (char *)newval); 245225571Stuexen } else { 246225571Stuexen intval = (int)strtol(newval, &endptr, 247225571Stuexen 0); 248165220Srrs if (endptr == newval || *endptr != '\0') 249169420Srrs errx(1, "invalid integer '%s'", 250169420Srrs (char *)newval); 251163953Srrs } 252163953Srrs newval = &intval; 253163953Srrs newsize = sizeof(intval); 254163953Srrs break; 255163953Srrs case CTLTYPE_UINT: 256172090Srrs uintval = (int) strtoul(newval, &endptr, 0); 257163953Srrs if (endptr == newval || *endptr != '\0') 258163953Srrs errx(1, "invalid unsigned integer '%s'", 259163953Srrs (char *)newval); 260163953Srrs newval = &uintval; 261224641Stuexen newsize = sizeof(uintval); 262169655Srrs break; 263224641Stuexen case CTLTYPE_LONG: 264224641Stuexen longval = strtol(newval, &endptr, 0); 265224641Stuexen if (endptr == newval || *endptr != '\0') 266224641Stuexen errx(1, "invalid long integer '%s'", 267163953Srrs (char *)newval); 268228907Stuexen newval = &longval; 269163953Srrs newsize = sizeof(longval); 270163953Srrs break; 271163953Srrs case CTLTYPE_ULONG: 272171572Srrs ulongval = strtoul(newval, &endptr, 0); 273163953Srrs if (endptr == newval || *endptr != '\0') 274163953Srrs errx(1, "invalid unsigned long integer" 275163953Srrs " '%s'", (char *)newval); 276163953Srrs newval = &ulongval; 277163953Srrs newsize = sizeof(ulongval); 278163953Srrs break; 279163953Srrs case CTLTYPE_STRING: 280228907Stuexen break; 281163953Srrs case CTLTYPE_QUAD: 282163953Srrs quadval = strtoq(newval, &endptr, 0); 283163953Srrs if (endptr == newval || *endptr != '\0') 284163953Srrs errx(1, "invalid quad integer" 285163953Srrs " '%s'", (char *)newval); 286163953Srrs newval = &quadval; 287169420Srrs newsize = sizeof(quadval); 288169420Srrs break; 289169420Srrs case CTLTYPE_OPAQUE: 290169420Srrs if (strcmp(fmt, "T,dev_t") == 0) { 291163953Srrs set_T_dev_t (newval, &newval, &newsize); 292163953Srrs break; 293172090Srrs } 294163953Srrs /* FALLTHROUGH */ 295163953Srrs default: 296228907Stuexen errx(1, "oid '%s' is type %d," 297163953Srrs " cannot set that", bufp, 298163953Srrs kind & CTLTYPE); 299163953Srrs } 300237715Stuexen 301237715Stuexen i = show_var(mib, len); 302163953Srrs if (sysctl(mib, len, 0, 0, newval, newsize) == -1) { 303163953Srrs if (!i && !bflag) 304163953Srrs putchar('\n'); 305237715Stuexen switch (errno) { 306221249Stuexen case EOPNOTSUPP: 307258454Stuexen errx(1, "%s: value is not available", 308258454Stuexen string); 309258454Stuexen case ENOTDIR: 310258454Stuexen errx(1, "%s: specification is incomplete", 311258454Stuexen string); 312258454Stuexen case ENOMEM: 313163953Srrs errx(1, "%s: type is unknown to this program", 314163953Srrs string); 315163953Srrs default: 316163953Srrs warn("%s", string); 317221249Stuexen warncount++; 318221249Stuexen return; 319221249Stuexen } 320221249Stuexen } 321221249Stuexen if (!bflag) 322163953Srrs printf(" -> "); 323163953Srrs i = nflag; 324163953Srrs nflag = 1; 325163953Srrs j = show_var(mib, len); 326221249Stuexen if (!j && !bflag) 327163953Srrs putchar('\n'); 328163953Srrs nflag = i; 329221249Stuexen } 330221249Stuexen} 331258454Stuexen 332221249Stuexen/* These functions will dump out various interesting structures. */ 333258454Stuexen 334163953Srrsstatic int 335163953SrrsS_clockinfo(int l2, void *p) 336221249Stuexen{ 337163953Srrs struct clockinfo *ci = (struct clockinfo*)p; 338163953Srrs 339163953Srrs if (l2 != sizeof(*ci)) { 340228907Stuexen warnx("S_clockinfo %d != %zu", l2, sizeof(*ci)); 341163953Srrs return (1); 342221249Stuexen } 343163953Srrs printf(hflag ? "{ hz = %'d, tick = %'d, profhz = %'d, stathz = %'d }" : 344163953Srrs "{ hz = %d, tick = %d, profhz = %d, stathz = %d }", 345163953Srrs ci->hz, ci->tick, ci->profhz, ci->stathz); 346163953Srrs return (0); 347163953Srrs} 348163953Srrs 349163953Srrsstatic int 350163953SrrsS_loadavg(int l2, void *p) 351169420Srrs{ 352169420Srrs struct loadavg *tv = (struct loadavg*)p; 353169420Srrs 354163953Srrs if (l2 != sizeof(*tv)) { 355221249Stuexen warnx("S_loadavg %d != %zu", l2, sizeof(*tv)); 356221249Stuexen return (1); 357163953Srrs } 358163953Srrs printf(hflag ? "{ %'.2f %'.2f %'.2f }" : "{ %.2f %.2f %.2f }", 359163953Srrs (double)tv->ldavg[0]/(double)tv->fscale, 360228907Stuexen (double)tv->ldavg[1]/(double)tv->fscale, 361163953Srrs (double)tv->ldavg[2]/(double)tv->fscale); 362221249Stuexen return (0); 363163953Srrs} 364163953Srrs 365163953Srrsstatic int 366163953SrrsS_timeval(int l2, void *p) 367163953Srrs{ 368163953Srrs struct timeval *tv = (struct timeval*)p; 369163953Srrs time_t tv_sec; 370163953Srrs char *p1, *p2; 371163953Srrs 372169420Srrs if (l2 != sizeof(*tv)) { 373169420Srrs warnx("S_timeval %d != %zu", l2, sizeof(*tv)); 374169420Srrs return (1); 375221249Stuexen } 376169420Srrs printf(hflag ? "{ sec = %'jd, usec = %'ld } " : 377163953Srrs "{ sec = %jd, usec = %ld } ", 378163953Srrs (intmax_t)tv->tv_sec, tv->tv_usec); 379163953Srrs tv_sec = tv->tv_sec; 380163953Srrs p1 = strdup(ctime(&tv_sec)); 381228907Stuexen for (p2=p1; *p2 ; p2++) 382163953Srrs if (*p2 == '\n') 383163953Srrs *p2 = '\0'; 384163953Srrs fputs(p1, stdout); 385237715Stuexen free(p1); 386163953Srrs return (0); 387169420Srrs} 388163953Srrs 389163953Srrsstatic int 390163953SrrsS_vmtotal(int l2, void *p) 391228907Stuexen{ 392163953Srrs struct vmtotal *v = (struct vmtotal *)p; 393163953Srrs int pageKilo = getpagesize() / 1024; 394179783Srrs 395237715Stuexen if (l2 != sizeof(*v)) { 396163953Srrs warnx("S_vmtotal %d != %zu", l2, sizeof(*v)); 397163953Srrs return (1); 398163953Srrs } 399169420Srrs 400163953Srrs printf( 401163953Srrs "\nSystem wide totals computed every five seconds:" 402163953Srrs " (values in kilobytes)\n"); 403163953Srrs printf("===============================================\n"); 404163953Srrs printf( 405163953Srrs "Processes:\t\t(RUNQ: %hd Disk Wait: %hd Page Wait: " 406163953Srrs "%hd Sleep: %hd)\n", 407163953Srrs v->t_rq, v->t_dw, v->t_pw, v->t_sl); 408163953Srrs printf( 409228907Stuexen "Virtual Memory:\t\t(Total: %dK Active: %dK)\n", 410163953Srrs v->t_vm * pageKilo, v->t_avm * pageKilo); 411163953Srrs printf("Real Memory:\t\t(Total: %dK Active: %dK)\n", 412163953Srrs v->t_rm * pageKilo, v->t_arm * pageKilo); 413163953Srrs printf("Shared Virtual Memory:\t(Total: %dK Active: %dK)\n", 414163953Srrs v->t_vmshr * pageKilo, v->t_avmshr * pageKilo); 415163953Srrs printf("Shared Real Memory:\t(Total: %dK Active: %dK)\n", 416163953Srrs v->t_rmshr * pageKilo, v->t_armshr * pageKilo); 417163953Srrs printf("Free Memory Pages:\t%dK\n", v->t_free * pageKilo); 418163953Srrs 419163953Srrs return (0); 420169420Srrs} 421163953Srrs 422163953Srrsstatic int 423163953SrrsT_dev_t(int l2, void *p) 424163953Srrs{ 425163953Srrs dev_t *d = (dev_t *)p; 426163953Srrs 427163953Srrs if (l2 != sizeof(*d)) { 428163953Srrs warnx("T_dev_T %d != %zu", l2, sizeof(*d)); 429172090Srrs return (1); 430163953Srrs } 431228907Stuexen printf("%s", devname(*d, S_IFCHR)); 432163953Srrs return (0); 433163953Srrs} 434163953Srrs 435237715Stuexenstatic void 436171572Srrsset_T_dev_t(char *path, void **val, size_t *size) 437171572Srrs{ 438163953Srrs static struct stat statb; 439163953Srrs 440237715Stuexen if (strcmp(path, "none") && strcmp(path, "off")) { 441221249Stuexen int rc = stat (path, &statb); 442258454Stuexen if (rc) { 443258454Stuexen err(1, "cannot stat %s", path); 444258454Stuexen } 445258454Stuexen 446258454Stuexen if (!S_ISCHR(statb.st_mode)) { 447258454Stuexen errx(1, "must specify a device special file."); 448163953Srrs } 449163953Srrs } else { 450163953Srrs statb.st_rdev = NODEV; 451221249Stuexen } 452221249Stuexen *val = (void *) &statb.st_rdev; 453221249Stuexen *size = sizeof(statb.st_rdev); 454221249Stuexen} 455221249Stuexen 456163953Srrsstatic int 457163953Srrsset_IK(const char *str, int *val) 458163953Srrs{ 459163953Srrs float temp; 460221249Stuexen int len, kelv; 461163953Srrs const char *p; 462163953Srrs char *endptr; 463221249Stuexen 464221249Stuexen if ((len = strlen(str)) == 0) 465258454Stuexen return (0); 466221249Stuexen p = &str[len - 1]; 467258454Stuexen if (*p == 'C' || *p == 'F') { 468163953Srrs temp = strtof(str, &endptr); 469163953Srrs if (endptr == str || endptr != p) 470221249Stuexen return (0); 471163953Srrs if (*p == 'F') 472163953Srrs temp = (temp - 32) * 5 / 9; 473163953Srrs kelv = temp * 10 + 2732; 474228907Stuexen } else { 475163953Srrs kelv = (int)strtol(str, &endptr, 10); 476221249Stuexen if (endptr == str || *endptr != '\0') 477163953Srrs return (0); 478163953Srrs } 479163953Srrs *val = kelv; 480163953Srrs return (1); 481163953Srrs} 482163953Srrs 483163953Srrs/* 484169420Srrs * These functions uses a presently undocumented interface to the kernel 485169420Srrs * to walk the tree and get the type so it can print the value. 486163953Srrs * This interface is under work and consideration, and should probably 487221249Stuexen * be killed with a big axe by the first person who can find the time. 488221249Stuexen * (be aware though, that the proper interface isn't as obvious as it 489163953Srrs * may seem, there are various conflicting requirements. 490163953Srrs */ 491163953Srrs 492228907Stuexenstatic int 493163953Srrsname2oid(char *name, int *oidp) 494221249Stuexen{ 495163953Srrs int oid[2]; 496163953Srrs int i; 497163953Srrs size_t j; 498163953Srrs 499163953Srrs oid[0] = 0; 500163953Srrs oid[1] = 3; 501163953Srrs 502163953Srrs j = CTL_MAXNAME * sizeof(int); 503169420Srrs i = sysctl(oid, 2, oidp, &j, name, strlen(name)); 504169420Srrs if (i < 0) 505221249Stuexen return (i); 506169420Srrs j /= sizeof(int); 507163953Srrs return (j); 508163953Srrs} 509163953Srrs 510163953Srrsstatic int 511228907Stuexenoidfmt(int *oid, int len, char *fmt, u_int *kind) 512163953Srrs{ 513163953Srrs int qoid[CTL_MAXNAME+2]; 514163953Srrs u_char buf[BUFSIZ]; 515179783Srrs int i; 516237715Stuexen size_t j; 517169420Srrs 518169420Srrs qoid[0] = 0; 519237715Stuexen qoid[1] = 4; 520163953Srrs memcpy(qoid + 2, oid, len * sizeof(int)); 521163953Srrs 522163953Srrs j = sizeof(buf); 523169420Srrs i = sysctl(qoid, len + 2, buf, &j, 0, 0); 524169420Srrs if (i) 525163953Srrs err(1, "sysctl fmt %d %zu %d", i, j, errno); 526172090Srrs 527224641Stuexen if (kind) 528224641Stuexen *kind = *(u_int *)buf; 529224641Stuexen 530224641Stuexen if (fmt) 531224641Stuexen strcpy(fmt, (char *)(buf + sizeof(u_int))); 532224641Stuexen return (0); 533163953Srrs} 534163953Srrs 535163953Srrs/* 536172091Srrs * This formats and outputs the value of one variable 537172091Srrs * 538172091Srrs * Returns zero if anything was actually output. 539172091Srrs * Returns one if didn't know what to do with this. 540172091Srrs * Return minus one if we had errors. 541206137Stuexen */ 542206137Stuexen 543206137Stuexenstatic int 544172091Srrsshow_var(int *oid, int nlen) 545172091Srrs{ 546172091Srrs u_char buf[BUFSIZ], *val, *oval, *p; 547172091Srrs char name[BUFSIZ], *fmt; 548172091Srrs const char *sep, *sep1; 549172091Srrs int qoid[CTL_MAXNAME+2]; 550172091Srrs uintmax_t umv; 551172091Srrs intmax_t mv; 552172091Srrs int i, hexlen; 553172091Srrs size_t intlen; 554172091Srrs size_t j, len; 555172091Srrs u_int kind; 556172091Srrs int (*func)(int, void *); 557172091Srrs 558172091Srrs /* Silence GCC. */ 559172091Srrs umv = mv = intlen = 0; 560172091Srrs 561172091Srrs bzero(buf, BUFSIZ); 562172091Srrs bzero(name, BUFSIZ); 563172091Srrs qoid[0] = 0; 564172091Srrs memcpy(qoid + 2, oid, nlen * sizeof(int)); 565172091Srrs 566212712Stuexen qoid[1] = 1; 567212712Stuexen j = sizeof(name); 568172091Srrs i = sysctl(qoid, nlen + 2, name, &j, 0, 0); 569172091Srrs if (i || !j) 570172091Srrs err(1, "sysctl name %d %zu %d", i, j, errno); 571172091Srrs 572163953Srrs if (Nflag) { 573163953Srrs printf("%s", name); 574169420Srrs return (0); 575169420Srrs } 576163953Srrs 577163953Srrs if (eflag) 578163953Srrs sep = "="; 579163953Srrs else 580163953Srrs sep = ": "; 581163953Srrs 582228907Stuexen if (dflag) { /* just print description */ 583163953Srrs qoid[1] = 5; 584163953Srrs j = sizeof(buf); 585163953Srrs i = sysctl(qoid, nlen + 2, buf, &j, 0, 0); 586163953Srrs if (!nflag) 587163953Srrs printf("%s%s", name, sep); 588163953Srrs printf("%s", buf); 589163953Srrs return (0); 590163953Srrs } 591237715Stuexen /* find an estimate of how much we need for this var */ 592171990Srrs j = 0; 593171990Srrs i = sysctl(oid, nlen, 0, &j, 0, 0); 594163953Srrs j += j; /* we want to be sure :-) */ 595163953Srrs 596163953Srrs val = oval = malloc(j + 1); 597171990Srrs if (val == NULL) { 598163953Srrs warnx("malloc failed"); 599163953Srrs return (1); 600163953Srrs } 601224641Stuexen len = j; 602163953Srrs i = sysctl(oid, nlen, val, &len, 0, 0); 603163953Srrs if (i || !len) { 604163953Srrs free(oval); 605166675Srrs return (1); 606171990Srrs } 607163953Srrs 608163953Srrs if (bflag) { 609163953Srrs fwrite(val, 1, len, stdout); 610169420Srrs free(oval); 611169420Srrs return (0); 612169420Srrs } 613163953Srrs val[len] = '\0'; 614163953Srrs fmt = buf; 615163953Srrs oidfmt(oid, nlen, fmt, &kind); 616163953Srrs p = val; 617163953Srrs switch (*fmt) { 618216825Stuexen case 'A': 619163953Srrs if (!nflag) 620169420Srrs printf("%s%s", name, sep); 621169420Srrs printf("%.*s", (int)len, p); 622169420Srrs free(oval); 623163953Srrs return (0); 624163953Srrs 625169420Srrs case 'I': 626169420Srrs case 'L': 627163953Srrs case 'Q': 628163953Srrs if (!nflag) 629163953Srrs printf("%s%s", name, sep); 630163953Srrs switch (*fmt) { 631163953Srrs case 'I': intlen = sizeof(int); break; 632163953Srrs case 'L': intlen = sizeof(long); break; 633169420Srrs case 'Q': intlen = sizeof(quad_t); break; 634169420Srrs } 635169420Srrs hexlen = 2 + (intlen * CHAR_BIT + 3) / 4; 636171990Srrs sep1 = ""; 637171990Srrs while (len >= intlen) { 638171990Srrs switch (*fmt) { 639221249Stuexen case 'I': 640171990Srrs umv = *(u_int *)p; 641216822Stuexen mv = *(int *)p; 642171990Srrs break; 643171990Srrs case 'L': 644171990Srrs umv = *(u_long *)p; 645171990Srrs mv = *(long *)p; 646216822Stuexen break; 647171990Srrs case 'Q': 648171990Srrs umv = *(u_quad_t *)p; 649171990Srrs mv = *(quad_t *)p; 650179783Srrs break; 651171990Srrs } 652163953Srrs fputs(sep1, stdout); 653165647Srrs if (fmt[1] == 'U') 654243882Sglebius printf(hflag ? "%'ju" : "%ju", umv); 655163953Srrs else if (fmt[1] == 'X') 656169420Srrs printf("%#0*jx", hexlen, umv); 657169420Srrs else if (fmt[1] == 'K') { 658163953Srrs if (mv < 0) 659163953Srrs printf("%jd", mv); 660163953Srrs else 661163953Srrs printf("%.1fC", (mv - 2732.0) / 10); 662163953Srrs } else 663163953Srrs printf(hflag ? "%'jd" : "%jd", mv); 664163953Srrs sep1 = " "; 665163953Srrs len -= intlen; 666163953Srrs p += intlen; 667163953Srrs } 668165647Srrs free(oval); 669163953Srrs return (0); 670163953Srrs 671163953Srrs case 'P': 672163953Srrs if (!nflag) 673163953Srrs printf("%s%s", name, sep); 674163953Srrs printf("%p", *(void **)p); 675169420Srrs free(oval); 676169420Srrs return (0); 677163953Srrs 678163953Srrs case 'T': 679163953Srrs case 'S': 680163953Srrs i = 0; 681163953Srrs if (strcmp(fmt, "S,clockinfo") == 0) 682163953Srrs func = S_clockinfo; 683163953Srrs else if (strcmp(fmt, "S,timeval") == 0) 684163953Srrs func = S_timeval; 685163953Srrs else if (strcmp(fmt, "S,loadavg") == 0) 686169420Srrs func = S_loadavg; 687163953Srrs else if (strcmp(fmt, "S,vmtotal") == 0) 688163953Srrs func = S_vmtotal; 689163953Srrs else if (strcmp(fmt, "T,dev_t") == 0) 690163953Srrs func = T_dev_t; 691163953Srrs else 692169420Srrs func = NULL; 693163953Srrs if (func) { 694163953Srrs if (!nflag) 695163953Srrs printf("%s%s", name, sep); 696224641Stuexen i = (*func)(len, p); 697163953Srrs free(oval); 698163953Srrs return (i); 699163953Srrs } 700163953Srrs /* FALLTHROUGH */ 701163953Srrs default: 702163953Srrs if (!oflag && !xflag) { 703163953Srrs free(oval); 704163953Srrs return (1); 705163953Srrs } 706163953Srrs if (!nflag) 707163953Srrs printf("%s%s", name, sep); 708163953Srrs printf("Format:%s Length:%zu Dump:0x", fmt, len); 709163953Srrs while (len-- && (xflag || p < val + 16)) 710169420Srrs printf("%02x", *p++); 711163953Srrs if (!xflag && len > 16) 712163953Srrs printf("..."); 713163953Srrs free(oval); 714163953Srrs return (0); 715169420Srrs } 716163953Srrs free(oval); 717163953Srrs return (1); 718163953Srrs} 719163953Srrs 720163953Srrsstatic int 721169420Srrssysctl_all(int *oid, int len) 722163953Srrs{ 723163953Srrs int name1[22], name2[22]; 724163953Srrs int i, j; 725163953Srrs size_t l1, l2; 726163953Srrs 727163953Srrs name1[0] = 0; 728237715Stuexen name1[1] = 2; 729224641Stuexen l1 = 2; 730224641Stuexen if (len) { 731163953Srrs memcpy(name1+2, oid, len * sizeof(int)); 732163953Srrs l1 += len; 733163953Srrs } else { 734237715Stuexen name1[2] = 1; 735163953Srrs l1++; 736163953Srrs } 737163953Srrs for (;;) { 738163953Srrs l2 = sizeof(name2); 739163953Srrs j = sysctl(name1, l1, name2, &l2, 0, 0); 740163953Srrs if (j < 0) { 741163953Srrs if (errno == ENOENT) 742237715Stuexen return (0); 743163953Srrs else 744163953Srrs err(1, "sysctl(getnext) %d %zu", j, l2); 745185694Srrs } 746185694Srrs 747185694Srrs l2 /= sizeof(int); 748163953Srrs 749163953Srrs if (len < 0 || l2 < (unsigned int)len) 750163953Srrs return (0); 751163953Srrs 752163953Srrs for (i = 0; i < len; i++) 753163953Srrs if (name2[i] != oid[i]) 754163953Srrs return (0); 755163953Srrs 756163953Srrs i = show_var(name2, l2); 757163953Srrs if (!i && !bflag) 758163953Srrs putchar('\n'); 759163953Srrs 760163953Srrs memcpy(name1+2, name2, l2 * sizeof(int)); 761163953Srrs l1 = 2 + l2; 762163953Srrs } 763163953Srrs} 764163953Srrs