]> git.saurik.com Git - apple/system_cmds.git/blobdiff - sysctl.tproj/sysctl.c
system_cmds-597.90.1.tar.gz
[apple/system_cmds.git] / sysctl.tproj / sysctl.c
index 631ad4094b8a6dfc1afa5a383d88946d0f33c6de..3b16137a38687189a2fee0cb23266b5c58a054e0 100644 (file)
@@ -1,23 +1,22 @@
-/*
- * Copyright (c) 1999-2004 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@
  */
  * 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.
  setting values where the format is specified as unsigned integer.
  */
  
+#include <sys/cdefs.h>
 #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 <sys/param.h>
@@ -156,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);
@@ -193,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;
@@ -213,7 +211,7 @@ main(argc, argv)
                usage();
        for (; *argv != NULL; ++argv) 
                parse(*argv, 1);
-       exit(0);
+       exit(invalid_name_used ? 1 : 0);
 }
 
 /*
@@ -348,7 +346,8 @@ old_parse(string, flags)
                useUnsignedInt = 1;
                break;
 
-       case CTL_VM:
+       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];
@@ -392,6 +391,7 @@ old_parse(string, flags)
                fprintf(stderr,
                    "Use vmstat or systat to view %s information\n", string);
                return;
+#endif
         
        case CTL_DEBUG:
                mib[2] = CTL_DEBUG_VALUE;
@@ -441,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;
@@ -463,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:
@@ -474,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;
@@ -496,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) {
@@ -548,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;
@@ -609,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);
@@ -644,7 +663,10 @@ findname(string, level, bufp, namelist)
        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++)
@@ -652,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);
@@ -689,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)
@@ -714,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) {
@@ -738,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;
                                }
@@ -750,8 +794,12 @@ parse(char *string, int flags)
                                break;
                        case CTLTYPE_QUAD:
                                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,"
@@ -764,7 +812,7 @@ parse(char *string, int flags)
                        if (!i && !bflag)
                                putchar('\n');
                        switch (errno) {
-                       case EOPNOTSUPP:
+                       case ENOTSUP:
                                errx(1, "%s: value is not available", 
                                        string);
                        case ENOTDIR:
@@ -795,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);
 }
@@ -807,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);
@@ -824,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);
 }
 
@@ -841,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 }",
@@ -893,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);
 }
 
 /*
@@ -933,7 +1021,7 @@ show_var(int *oid, int nlen, int show_masked)
        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;
@@ -957,8 +1045,20 @@ show_var(int *oid, int nlen, int show_masked)
        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)) {
@@ -987,13 +1087,13 @@ show_var(int *oid, int nlen, int show_masked)
                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);
                }
@@ -1004,13 +1104,13 @@ show_var(int *oid, int nlen, int show_masked)
                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);
                }
@@ -1028,13 +1128,13 @@ show_var(int *oid, int nlen, int show_masked)
                if (!nflag)
                        printf("%s: ", name);
                fmt++;
-               val = "";
+               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 = " ";
+                       val = (unsigned char *)" ";
                        len -= sizeof (long long);
                        p += sizeof (long long);
                }
@@ -1048,6 +1148,7 @@ show_var(int *oid, int nlen, int show_masked)
                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)
@@ -1105,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);