X-Git-Url: https://git.saurik.com/apple/system_cmds.git/blobdiff_plain/1815bff58803503e37009deeb85cfa8c22acf9d9..45bc9d1542da654746b7a98b0fbafa8bf741d966:/sysctl.tproj/sysctl.c diff --git a/sysctl.tproj/sysctl.c b/sysctl.tproj/sysctl.c index fb0dbb4..3b16137 100644 --- a/sysctl.tproj/sysctl.c +++ b/sysctl.tproj/sysctl.c @@ -1,23 +1,22 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + /* + * Copyright (c) 1999-2010 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * - * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.0 (the 'License'). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License." + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ @@ -33,10 +32,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -87,14 +82,15 @@ setting values where the format is specified as unsigned integer. */ +#include #ifndef lint -static char copyright[] = +__unused static char copyright[] = "@(#) Copyright (c) 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)sysctl.c 8.5 (Berkeley) 5/9/95"; +__unused static char sccsid[] = "@(#)sysctl.c 8.5 (Berkeley) 5/9/95"; #endif /* not lint */ #include @@ -110,7 +106,6 @@ static char sccsid[] = "@(#)sysctl.c 8.5 (Berkeley) 5/9/95"; #else #include #endif /* __APPLE__ */ -#include #include #include @@ -146,7 +141,7 @@ struct list secondlevel[] = { { kernname, KERN_MAXID }, /* CTL_KERN */ { vmname, VM_MAXID }, /* CTL_VM */ { 0, 0 }, /* CTL_VFS */ - { 0, 0 }, /* CTL_NET */ + { 0, 0 }, /* CTL_NET */ { 0, CTL_DEBUG_MAXID }, /* CTL_DEBUG */ { hwname, HW_MAXID }, /* CTL_HW */ #ifdef CTL_MACHDEP_NAMES @@ -157,8 +152,9 @@ struct list secondlevel[] = { { username, USER_MAXID }, /* CTL_USER_NAMES */ }; -static int Aflag, aflag, bflag, nflag, wflag, Xflag; +static int Aflag, aflag, bflag, hflag, nflag, wflag, Xflag; static int foundSome = 0; +static int invalid_name_used = 0; void listall(char *prefix, struct list *lp); void old_parse(char *string, int flags); @@ -169,7 +165,7 @@ void usage(); static void parse(char *string, int flags); static int oidfmt(int *, int, char *, u_int *); -static int show_var(int *, int); +static int show_var(int *, int, int); static int sysctl_all (int *oid, int len); static int name2oid(char *, int *); @@ -194,6 +190,7 @@ main(argc, argv) case 'A': Aflag = 1; break; case 'a': aflag = 1; break; case 'b': bflag = 1; break; + case 'h': hflag = 1; break; case 'n': nflag = 1; break; case 'w': wflag = 1; break; case 'X': Xflag = Aflag = 1; break; @@ -212,9 +209,9 @@ main(argc, argv) } if (argc == 0) usage(); - for (; *argv != NULL; ++argv) + for (; *argv != NULL; ++argv) parse(*argv, 1); - exit(0); + exit(invalid_name_used ? 1 : 0); } /* @@ -346,10 +343,13 @@ old_parse(string, flags) break; case CTL_HW: + useUnsignedInt = 1; break; - case CTL_VM: - if (mib[1] == VM_LOADAVG) { + case CTL_VM: break; +#if 0 /* XXX Handled by the new sysctl mechanism */ + switch (mib[1]) { + case VM_LOADAVG: { /* XXX this is bogus */ double loads[3]; getloadavg(loads, 3); @@ -359,11 +359,39 @@ old_parse(string, flags) loads[0], loads[1], loads[2]); return; } + case VM_SWAPUSAGE: { + struct xsw_usage xsu; + int saved_errno; + + size = sizeof (xsu); + if (sysctl(mib, 2, &xsu, &size, NULL, 0) != 0) { + if (flags == 0) + return; + saved_errno = errno; + if (!nflag) + fprintf(stderr, "%s: ", string); + fprintf(stderr, "sysctl(VM_SWAPUSAGE): %s\n", + strerror(saved_errno)); + return; + } + + if (!nflag) + fprintf(stdout, "%s: ", string); + fprintf(stdout, + "total = %.2fM used = %.2fM free = %.2fM %s\n", + ((double) xsu.xsu_total) / (1024.0 * 1024.0), + ((double) xsu.xsu_used) / (1024.0 * 1024.0), + ((double) xsu.xsu_avail) / (1024.0 * 1024.0), + xsu.xsu_encrypted ? "(encrypted)" : ""); + return; + } + } if (flags == 0) return; fprintf(stderr, "Use vmstat or systat to view %s information\n", string); return; +#endif case CTL_DEBUG: mib[2] = CTL_DEBUG_VALUE; @@ -413,18 +441,33 @@ old_parse(string, flags) switch (type) { case CTLTYPE_INT: if (useUnsignedInt) { - uintval = strtoul(newval, 0, 0); + uintval = strtoul(newval, NULL, 0); + if ((uintval == 0) && (errno == EINVAL)) { + fprintf(stderr, "invalid argument: %s\n", + (char *)newval); + return; + } newval = &uintval; newsize = sizeof uintval; } else { - intval = atoi(newval); - newval = &intval; - newsize = sizeof intval; + intval = strtol(newval, NULL, 0); + if ((intval == 0) && (errno == EINVAL)) { + fprintf(stderr, "invalid argument: %s\n", + (char *)newval); + return; + } + newval = &intval; + newsize = sizeof intval; } break; case CTLTYPE_QUAD: - sscanf(newval, "%qd", &quadval); + quadval = strtoq(newval, NULL, 0); + if ((quadval == 0) && (errno == EINVAL)) { + fprintf(stderr, "invalid argument: %s\n", + (char *)newval); + return; + } newval = &quadval; newsize = sizeof quadval; break; @@ -435,7 +478,7 @@ old_parse(string, flags) if (flags == 0) return; switch (errno) { - case EOPNOTSUPP: + case ENOTSUP: fprintf(stderr, "%s: value is not available\n", string); return; case ENOTDIR: @@ -446,6 +489,10 @@ old_parse(string, flags) fprintf(stderr, "%s: type is unknown to this program\n", string); return; + case ENOENT: + fprintf(stderr, "%s: no such MIB\n", + string); + return; default: perror(string); return; @@ -468,7 +515,7 @@ old_parse(string, flags) fprintf(stdout, "%s = %s\n", string, ctime((time_t *) &btp->tv_sec)); else - fprintf(stdout, "%d\n", btp->tv_sec); + fprintf(stdout, "%ld\n", btp->tv_sec); return; } if (special & CONSDEV) { @@ -520,11 +567,11 @@ old_parse(string, flags) } return; + case CTLTYPE_NODE: case CTLTYPE_STRUCT: return; default: - case CTLTYPE_NODE: fprintf(stderr, "%s: unknown type returned\n", string); return; @@ -581,7 +628,7 @@ void vfsinit() for (loc = lastused, cnt = 0; cnt < maxtypenum; cnt++) { mib[3] = cnt; if (sysctl(mib, 4, &vfc, &buflen, (void *)0, (size_t)0) < 0) { - if (errno == EOPNOTSUPP) + if (errno == ENOTSUP) continue; perror("vfsinit"); free(vfsname); @@ -612,8 +659,14 @@ findname(string, level, bufp, namelist) char *name; int i; + /* Make 'sysctl kern.' style behave the same as 'sysctl kern' 3360872*/ + if (bufp[0][strlen(*bufp)-1] == '.') + bufp[0][strlen(*bufp)-1]='\0'; if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) { - fprintf(stderr, "%s: incomplete specification\n", string); + if (!foundSome) { + fprintf(stderr, "%s: incomplete specification\n", string); + invalid_name_used = 1; + } return (-1); } for (i = 0; i < namelist->size; i++) @@ -621,8 +674,11 @@ findname(string, level, bufp, namelist) strcmp(name, namelist->list[i].ctl_name) == 0) break; if (i == namelist->size) { - fprintf(stderr, "%s level name %s in %s is invalid\n", - level, name, string); + if (!foundSome) { + fprintf(stderr, "%s level name %s in %s is invalid\n", + level, name, string); + invalid_name_used = 1; + } return (-1); } return (i); @@ -658,6 +714,8 @@ parse(char *string, int flags) u_int kind; bufp = buf; + if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ) + errx(1, "MIB too long"); snprintf(buf, BUFSIZ, "%s", string); if ((cp = strchr(string, '=')) != NULL) { if (!wflag) @@ -683,8 +741,13 @@ parse(char *string, int flags) return; } + /* + * An non-zero return here is an OID space containing parameters which + * needs to be ignored in the interests of backward compatibility with + * pre-newsysctl sysctls. + */ if (oidfmt(mib, len, fmt, &kind)) - err(1, "couldn't find format of oid '%s'", bufp); + return; if (!wflag) { if ((kind & CTLTYPE) == CTLTYPE_NODE) { @@ -692,7 +755,7 @@ parse(char *string, int flags) foundSome = 1; old_parse (string, flags); } else { - i = show_var(mib, len); + i = show_var(mib, len, 1); if (!i && !bflag) putchar('\n'); } @@ -707,10 +770,22 @@ parse(char *string, int flags) case CTLTYPE_INT: if ((*fmt == 'I') && (*(fmt + 1) == 'U')) { uintval = (unsigned int) strtoul (newval, NULL, 0); + if ((uintval == 0) && + (errno == EINVAL)) { + errx(1, "invalid argument: %s", + (char *)newval); + return; + } newval = &uintval; newsize = sizeof uintval; } else { intval = (int) strtol(newval, NULL, 0); + if ((intval == 0) && + (errno == EINVAL)) { + errx(1, "invalid argument: %s", + (char *)newval); + return; + } newval = &intval; newsize = sizeof intval; } @@ -718,10 +793,13 @@ parse(char *string, int flags) case CTLTYPE_STRING: break; case CTLTYPE_QUAD: - break; - sscanf(newval, "%qd", &quadval); + quadval = strtoq(newval, NULL, 0); + if ((quadval == 0) && (errno == EINVAL)) { + errx(1, "invalid argument %s", (char *)newval); + return; + } newval = &quadval; - newsize = sizeof quadval; + newsize = sizeof(quadval); break; default: errx(1, "oid '%s' is type %d," @@ -729,12 +807,12 @@ parse(char *string, int flags) kind & CTLTYPE); } - i = show_var(mib, len); + i = show_var(mib, len, 1); if (sysctl(mib, len, 0, 0, newval, newsize) == -1) { if (!i && !bflag) putchar('\n'); switch (errno) { - case EOPNOTSUPP: + case ENOTSUP: errx(1, "%s: value is not available", string); case ENOTDIR: @@ -752,7 +830,7 @@ parse(char *string, int flags) printf(" -> "); i = nflag; nflag = 1; - j = show_var(mib, len); + j = show_var(mib, len, 1); if (!j && !bflag) putchar('\n'); nflag = i; @@ -765,9 +843,13 @@ static int S_clockinfo(int l2, void *p) { struct clockinfo *ci = (struct clockinfo*)p; - if (l2 != sizeof *ci) - err(1, "S_clockinfo %d != %d", l2, sizeof *ci); - printf("{ hz = %d, tick = %d, tickadj = %d, profhz = %d, stathz = %d }", + + if (l2 != sizeof(*ci)) { + warnx("S_clockinfo %d != %ld", l2, sizeof(*ci)); + return (1); + } + printf(hflag ? "{ hz = %'d, tick = %'d, tickadj = %'d, profhz = %'d, stathz = %'d }" : + "{ hz = %d, tick = %d, tickadj = %d, profhz = %d, stathz = %d }", ci->hz, ci->tick, ci->tickadj, ci->profhz, ci->stathz); return (0); } @@ -777,10 +859,11 @@ S_loadavg(int l2, void *p) { struct loadavg *tv = (struct loadavg*)p; - if (l2 != sizeof *tv) - err(1, "S_loadavg %d != %d", l2, sizeof *tv); - - printf("{ %.2f %.2f %.2f }", + if (l2 != sizeof(*tv)) { + warnx("S_loadavg %d != %ld", l2, sizeof(*tv)); + return (1); + } + printf(hflag ? "{ %'.2f %'.2f %'.2f }" : "{ %.2f %.2f %.2f }", (double)tv->ldavg[0]/(double)tv->fscale, (double)tv->ldavg[1]/(double)tv->fscale, (double)tv->ldavg[2]/(double)tv->fscale); @@ -794,16 +877,38 @@ S_timeval(int l2, void *p) time_t tv_sec; char *p1, *p2; - if (l2 != sizeof *tv) - err(1, "S_timeval %d != %d", l2, sizeof *tv); - printf("{ sec = %ld, usec = %ld } ", - (long) tv->tv_sec, (long) tv->tv_usec); + if (l2 != sizeof(*tv)) { + warnx("S_timeval %d != %ld", l2, sizeof(*tv)); + return (1); + } + printf(hflag ? "{ sec = %'jd, usec = %'ld } " : + "{ sec = %jd, usec = %ld } ", + (intmax_t)tv->tv_sec, (long)tv->tv_usec); tv_sec = tv->tv_sec; p1 = strdup(ctime(&tv_sec)); for (p2=p1; *p2 ; p2++) if (*p2 == '\n') *p2 = '\0'; fputs(p1, stdout); + free(p1); + return (0); +} + +static int +S_xswusage(int l2, void *p) +{ + struct xsw_usage *xsu = (struct xsw_usage *)p; + + if (l2 != sizeof(*xsu)) { + warnx("S_xswusage %d != %ld", l2, sizeof(*xsu)); + return (1); + } + fprintf(stdout, + "total = %.2fM used = %.2fM free = %.2fM %s", + ((double)xsu->xsu_total) / (1024.0 * 1024.0), + ((double)xsu->xsu_used) / (1024.0 * 1024.0), + ((double)xsu->xsu_avail) / (1024.0 * 1024.0), + xsu->xsu_encrypted ? "(encrypted)" : ""); return (0); } @@ -811,8 +916,11 @@ static int T_dev_t(int l2, void *p) { dev_t *d = (dev_t *)p; - if (l2 != sizeof *d) - err(1, "T_dev_T %d != %d", l2, sizeof *d); + + if (l2 != sizeof(*d)) { + warnx("T_dev_T %d != %ld", l2, sizeof(*d)); + return (1); + } if ((int)(*d) != -1) { if (minor(*d) > 255 || minor(*d) < 0) printf("{ major = %d, minor = 0x%x }", @@ -863,17 +971,27 @@ oidfmt(int *oid, int len, char *fmt, u_int *kind) qoid[1] = 4; memcpy(qoid + 2, oid, len * sizeof(int)); - j = sizeof buf; + j = sizeof(buf); i = sysctl(qoid, len + 2, buf, &j, 0, 0); - if (i) - err(1, "sysctl fmt %d %d %d", i, j, errno); + if (i) { + /* + * An ENOENT error return indicates that the OID in question + * is a node OID followed not by additional OID elements, but + * by integer parameters. We really do not want to support + * this type of thing going forward, but we alow it here for + * historical compatibility. Eventually, this will go away. + */ + if (errno == ENOENT) + return ENOENT; + err(1, "sysctl fmt %d %ld %d", i, j, errno); + } if (kind) *kind = *(u_int *)buf; if (fmt) strcpy(fmt, (char *)(buf + sizeof(u_int))); - return 0; + return (0); } /* @@ -885,12 +1003,13 @@ oidfmt(int *oid, int len, char *fmt, u_int *kind) */ static int -show_var(int *oid, int nlen) +show_var(int *oid, int nlen, int show_masked) { - u_char buf[BUFSIZ], *val, *p; + u_char buf[BUFSIZ], *val, *mval, *p; char name[BUFSIZ], /* descr[BUFSIZ], */ *fmt; int qoid[CTL_MAXNAME+2]; int i; + int retval; size_t j, len; u_int kind; int (*func)(int, void *) = 0; @@ -902,79 +1021,126 @@ show_var(int *oid, int nlen) j = sizeof name; i = sysctl(qoid, nlen + 2, name, &j, 0, 0); if (i || !j) - err(1, "sysctl name %d %d %d", i, j, errno); + err(1, "sysctl name %d %ld %d", i, j, errno); /* find an estimate of how much we need for this var */ j = 0; i = sysctl(oid, nlen, 0, &j, 0, 0); j += j; /* we want to be sure :-) */ - val = alloca(j); + val = mval = malloc(j); len = j; i = sysctl(oid, nlen, val, &len, 0, 0); - if (i || !len) - return (1); + if (i || !len) { + retval = 1; + goto RETURN; + } if (bflag) { fwrite(val, 1, len, stdout); - return (0); + retval = 0; + goto RETURN; } qoid[1] = 4; j = sizeof buf; i = sysctl(qoid, nlen + 2, buf, &j, 0, 0); + /* + * An ENOENT error return indicates that the OID in question + * is a node OID followed not by additional OID elements, but + * by integer parameters. We really do not want to support + * this type of thing going forward, but we alow it here for + * historical compatibility. Eventially, this will go away. + */ + if (i && errno == ENOENT) { + retval = 1; + goto RETURN; + } + if (i || !j) - err(1, "sysctl fmt %d %d %d", i, j, errno); + err(1, "sysctl fmt %d %ld %d", i, j, errno); kind = *(u_int *)buf; + if (!show_masked && (kind & CTLFLAG_MASKED)) { + retval = 1; + goto RETURN; + } fmt = (char *)(buf + sizeof(u_int)); p = val; switch (*fmt) { + case '-': + /* deprecated, do not print */ + retval = 0; + goto RETURN; + + case 'A': if (!nflag) printf("%s: ", name); printf("%s", p); - return (0); + retval = 0; + goto RETURN; case 'I': if (!nflag) printf("%s: ", name); fmt++; - val = ""; + val = (unsigned char *)""; while (len >= sizeof(int)) { if(*fmt == 'U') printf("%s%u", val, *(unsigned int *)p); else printf("%s%d", val, *(int *)p); - val = " "; + val = (unsigned char *)" "; len -= sizeof (int); p += sizeof (int); } - return (0); + retval = 0; + goto RETURN; case 'L': if (!nflag) printf("%s: ", name); fmt++; - val = ""; + val = (unsigned char *)""; while (len >= sizeof(long)) { if(*fmt == 'U') printf("%s%lu", val, *(unsigned long *)p); else printf("%s%ld", val, *(long *)p); - val = " "; + val = (unsigned char *)" "; len -= sizeof (long); p += sizeof (long); } - return (0); + retval = 0; + goto RETURN; case 'P': if (!nflag) printf("%s: ", name); printf("%p", *(void **)p); - return (0); + retval = 0; + goto RETURN; + + case 'Q': + if (!nflag) + printf("%s: ", name); + fmt++; + val = (unsigned char *)""; + while (len >= sizeof(long long)) { + if(*fmt == 'U') + printf("%s%llu", val, *(unsigned long long *)p); + else + printf("%s%lld", val, *(long long *)p); + val = (unsigned char *)" "; + len -= sizeof (long long); + p += sizeof (long long); + } + retval = 0; + goto RETURN; + case 'T': case 'S': @@ -982,16 +1148,20 @@ show_var(int *oid, int nlen) if (!strcmp(fmt, "S,clockinfo")) func = S_clockinfo; else if (!strcmp(fmt, "S,timeval")) func = S_timeval; else if (!strcmp(fmt, "S,loadavg")) func = S_loadavg; + else if (!strcmp(fmt, "S,xsw_usage")) func = S_xswusage; else if (!strcmp(fmt, "T,dev_t")) func = T_dev_t; if (func) { if (!nflag) printf("%s: ", name); - return ((*func)(len, p)); + retval = (*func)(len, p); + goto RETURN; } /* FALL THROUGH */ default: - if (!Aflag) - return (1); + if (!Aflag) { + retval = 1; + goto RETURN; + } if (!nflag) printf("%s: ", name); printf("Format:%s Length:%ld Dump:0x", fmt, len); @@ -1002,9 +1172,14 @@ show_var(int *oid, int nlen) printf("..."); break; } - return (0); + retval = 0; + goto RETURN; } - return (1); + + retval = 1; + RETURN: + free(mval); + return (retval); } static int @@ -1031,7 +1206,7 @@ sysctl_all (int *oid, int len) if (errno == ENOENT) return 0; else - err(1, "sysctl(getnext) %d %d", j, l2); + err(1, "sysctl(getnext) %d %ld", j, l2); } l2 /= sizeof (int); @@ -1043,7 +1218,7 @@ sysctl_all (int *oid, int len) if (name2[i] != oid[i]) return 0; - i = show_var(name2, l2); + i = show_var(name2, l2, 0); if (!i && !bflag) putchar('\n');