]> git.saurik.com Git - apple/system_cmds.git/blobdiff - sysctl.tproj/sysctl.c
system_cmds-790.20.2.tar.gz
[apple/system_cmds.git] / sysctl.tproj / sysctl.c
index 76b8a6f9244e8c4b178ded79a71961508cbf4c64..606459a7d56787ec0b72d5d720e550862685bed6 100644 (file)
@@ -1,27 +1,3 @@
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * Copyright (c) 1999-2003 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 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, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
 /*
  * Copyright (c) 1993
  *     The Regents of the University of California.  All rights reserved.
 /*
  * Copyright (c) 1993
  *     The Regents of the University of California.  All rights reserved.
  * 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.
  * 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.
  * 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.
  * SUCH DAMAGE.
  */
 
  * SUCH DAMAGE.
  */
 
- /*
- Modified November 1, 2000, by Ryan Rempel, ryan.rempel@utoronto.ca
- The Darwin sysctl mechanism is in a state of flux. Parts of the kernel use the old
- style of BSD sysctl definition, and other parts use the new style. The sysctl (8)
- command that shipped with Darwin 1.2 (OS X PB) did not allow you to access
- all possible sysctl values. In particular, it did not permit access to sysctl values
- created by kernel extensions--hence my particular interest. The freeBSD sysctl (8)
- command compiled and ran under Darwin 1.2, and it did permit access to 
- sysctl values created by kernel extensions, as well as several others. However, it 
- did not permit access to many other values which the Darwin 1.2 sysctl could access.
- What I have done is merge the Darwin 1.2 sysctl and the freeBSD sysctl. Essentially,
- there are two points of merger. When showing all values (i.e. -a, -A, or -X), sysctl now
- runs the Darwin 1.2 routine to show all values, and then the freeBSD routine. This does
- result in some duplication. When getting or setting a particular value, sysctl now tries
- the freeBSD way first. If it cannot find the value, then it tries the Darwin 1.2 way.
- There are a few oddities which this creates (aside from some duplication with -a, -A,
- and -X). The freeBSD version of sysctl now supports two extra options, -b and -X. 
- In this syctl, those options are supported where the value is retrieved by the freeBSD
- routine, and have no effect where the value is retrieved by the Darwin 1.2 routine.
- The freeBSD sysctl uses a ':' to separate the name and the value, whereas Darwin 1.2's
- sysctl uses a '='. I have left this way, as it lets you know which routine was used,
- should it matter.
- I have also fixed several lines which gave warnings previously, one of which appears
- to have been an actual bug (bufp was dereferenced when it shouldn't have been).
- I have also incoporated my previous patch to permit setting kern.hostid as an unsigned 
- integer. In the freeBSD side of the code, I have incorporated a general fix for
- setting values where the format is specified as unsigned integer.
- */
+#include <sys/cdefs.h>
 #ifndef lint
 #ifndef lint
-static char copyright[] =
+__unused static const char copyright[] =
 "@(#) Copyright (c) 1993\n\
        The Regents of the University of California.  All rights reserved.\n";
 #endif /* not lint */
 
 #ifndef lint
 "@(#) 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";
+#if 0
+static char sccsid[] = "@(#)from: sysctl.c     8.1 (Berkeley) 6/6/93";
+#endif
+__unused static const char rcsid[] =
+  "$FreeBSD$";
 #endif /* not lint */
 
 #include <sys/param.h>
 #endif /* not lint */
 
 #include <sys/param.h>
-#include <sys/gmon.h>
-#include <sys/mount.h>
+#include <sys/time.h>
+#include <sys/resource.h>
 #include <sys/stat.h>
 #include <sys/sysctl.h>
 #include <sys/stat.h>
 #include <sys/sysctl.h>
-#include <sys/socket.h>
 #ifdef __APPLE__
 #include <mach/machine/vm_param.h>
 #include <mach/machine/vm_types.h>
 #include <mach/mach_types.h>
 #ifdef __APPLE__
 #include <mach/machine/vm_param.h>
 #include <mach/machine/vm_types.h>
 #include <mach/mach_types.h>
-#else
-#include <vm/vm_param.h>
-#endif /* __APPLE__ */
-#include <machine/cpu.h>
+#else // !__APPLE__
+#include <sys/vmmeter.h>
+#endif // !__APPLE__
 
 
-#include <errno.h>
 #include <ctype.h>
 #include <ctype.h>
-#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <locale.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 
-#include <sys/types.h>
-#include <sys/resource.h>
-#include <err.h>
-
-struct ctlname topname[] = CTL_NAMES;
-struct ctlname kernname[] = CTL_KERN_NAMES;
-struct ctlname vmname[] = CTL_VM_NAMES;
-struct ctlname hwname[] = CTL_HW_NAMES;
-struct ctlname username[] = CTL_USER_NAMES;
-struct ctlname debugname[CTL_DEBUG_MAXID];
-struct ctlname *vfsname;
-#ifdef CTL_MACHDEP_NAMES
-struct ctlname machdepname[] = CTL_MACHDEP_NAMES;
-#endif
-char names[BUFSIZ];
-int lastused;
-
-struct list {
-       struct  ctlname *list;
-       int     size;
-};
-struct list toplist = { topname, CTL_MAXID };
-struct list secondlevel[] = {
-       { 0, 0 },                       /* CTL_UNSPEC */
-       { kernname, KERN_MAXID },       /* CTL_KERN */
-       { vmname, VM_MAXID },           /* CTL_VM */
-       { 0, 0 },                       /* CTL_VFS */
-       { 0, 0 },                       /* CTL_NET */
-       { 0, CTL_DEBUG_MAXID },         /* CTL_DEBUG */
-       { 0,0 },                        /* CTL_HW */
-#ifdef CTL_MACHDEP_NAMES
-       { machdepname, CPU_MAXID },     /* CTL_MACHDEP */
-#else
-       { 0, 0 },                       /* CTL_MACHDEP */
-#endif
-       { username, USER_MAXID },       /* CTL_USER_NAMES */
-};
-
-static int     Aflag, aflag, bflag, nflag, wflag, Xflag;
-static int     foundSome = 0;
-
-void listall(char *prefix, struct list *lp);
-void old_parse(char *string, int flags);
-void debuginit();
-void vfsinit();
-int  findname(char *string, char *level, char **bufp, struct list *namelist);
-void usage();
+static int     aflag, bflag, dflag, eflag, hflag, iflag;
+static int     Nflag, nflag, oflag, qflag, xflag, warncount;
 
 
-static void    parse(char *string, int flags);
 static int     oidfmt(int *, int, char *, u_int *);
 static int     oidfmt(int *, int, char *, u_int *);
+static void    parse(const char *);
+#ifdef __APPLE__
 static int     show_var(int *, int, int);
 static int     show_var(int *, int, int);
-static int     sysctl_all (int *oid, int len);
+#else
+static int     show_var(int *, int);
+#endif
+static int     sysctl_all(int *oid, int len);
 static int     name2oid(char *, int *);
 
 static int     name2oid(char *, int *);
 
-/*
- * Variables requiring special processing.
- */
-#define        CLOCK           0x00000001
-#define        BOOTTIME        0x00000002
-#define        CONSDEV         0x00000004
+#ifndef __APPLE__
+static int     set_IK(const char *, int *);
+#endif
 
 
-int
-main(argc, argv)
-       int argc;
-       char *argv[];
-{
-//     extern char *optarg;   // unused
-       extern int optind;
-       int ch, lvl1;
+#ifdef __APPLE__
+// Shims for FreeBSD source compatibility.
+#define CTLTYPE_UINT 0xa
+#define CTLTYPE_LONG 0xb
+#define CTLTYPE_ULONG 0xc
+#define CTLTYPE_S64 0xd
+#define CTLTYPE_U64 0xe
+
+#define CTLFLAG_TUN 0
+
+// Support for CTL_USER
+const struct ctlname names[] = CTL_NAMES;
+const struct ctlname user_names[] = CTL_USER_NAMES;
+const int user_names_count = sizeof(user_names) / sizeof(*user_names);
+#endif
 
 
-       while ((ch = getopt(argc, argv, "AabnwX")) != EOF) {
-               switch (ch) {
-                       case 'A': Aflag = 1; break;
-                       case 'a': aflag = 1; break;
-                       case 'b': bflag = 1; break;
-                       case 'n': nflag = 1; break;
-                       case 'w': wflag = 1; break;
-                       case 'X': Xflag = Aflag = 1; break;
-                       default: usage();
-               }
-       }
-       argc -= optind;
-       argv += optind;
+static void
+usage(void)
+{
 
 
-       if (argc == 0 && (Aflag || aflag)) {
-               debuginit();
-               vfsinit();
-               for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++)
-                       listall(topname[lvl1].ctl_name, &secondlevel[lvl1]);
-               exit (sysctl_all(0, 0));
-       }
-       if (argc == 0)
-               usage();
-       for (; *argv != NULL; ++argv)
-               parse(*argv, 1);
-       exit(0);
+       (void)fprintf(stderr, "%s\n%s\n",
+           "usage: sysctl [-bdehiNnoqx] name[=value] ...",
+           "       sysctl [-bdehNnoqx] -a");
+       exit(1);
 }
 
 }
 
-/*
- * List all variables known to the system.
- */
-void
-listall(prefix, lp)
-       char *prefix;
-       struct list *lp;
+int
+main(int argc, char **argv)
 {
 {
-       int lvl2;
-       char *cp, name[BUFSIZ];
+       int ch;
 
 
-       if (lp->list == 0)
-               return;
-       strcpy(name, prefix);
-       cp = &name[strlen(name)];
-       *cp++ = '.';
-       for (lvl2 = 0; lvl2 < lp->size; lvl2++) {
-               if (lp->list[lvl2].ctl_name == 0)
-                       continue;
-               strcpy(cp, lp->list[lvl2].ctl_name);
-               old_parse(name, Aflag);
-       }
-}
+       setlocale(LC_NUMERIC, "");
+       setbuf(stdout,0);
+       setbuf(stderr,0);
 
 
-/*
- * Parse a name into a MIB entry.
- * Lookup and print out the MIB entry if it exists.
- * Set a new value if requested.
- */
-void
-old_parse(string, flags)
-       char *string;
-       int flags;
-{
-       int indx, type, state, len;
-       size_t size;
-       int special = 0;
-       void *newval = 0;
-       int intval, newsize = 0;
-       unsigned int uintval;
-       int useUnsignedInt = 0;
-       quad_t quadval;
-       struct list *lp;
-       struct vfsconf vfc;
-       int mib[CTL_MAXNAME];
-       char *cp, *bufp, buf[BUFSIZ] /*, strval[BUFSIZ] */ ;
-
-       bufp = buf;
-       snprintf(buf, BUFSIZ, "%s", string);
-       if ((cp = strchr(string, '=')) != NULL) {
-               if (!wflag) {
-                       fprintf(stderr, "Must specify -w to set variables\n");
-                       exit(2);
-               }
-               *strchr(buf, '=') = '\0';
-               *cp++ = '\0';
-               while (isspace(*cp))
-                       cp++;
-               newval = cp;
-               newsize = strlen(cp);
-       }
-       if ((indx = findname(string, "top", &bufp, &toplist)) == -1)
-               return;
-       mib[0] = indx;
-       if (indx == CTL_VFS)
-               vfsinit();
-       if (indx == CTL_DEBUG)
-               debuginit();
-       lp = &secondlevel[indx];
-       if (lp->list == 0) {
-               if (!foundSome) fprintf(stderr, "%s: class is not implemented\n",
-                   topname[indx].ctl_name);
-               return;
-       }
-       if (bufp == NULL) {
-               listall(topname[indx].ctl_name, lp);
-               return;
-       }
-       if ((indx = findname(string, "second", &bufp, lp)) == -1)
-               return;
-       mib[1] = indx;
-       type = lp->list[indx].ctl_type;
-       len = 2;
-       switch (mib[0]) {
-
-       case CTL_KERN:
-               switch (mib[1]) {
-               case KERN_PROF:
-                       mib[2] = GPROF_STATE;
-                       size = sizeof state;
-                       if (sysctl(mib, 3, &state, &size, NULL, 0) < 0) {
-                               if (flags == 0)
-                                       return;
-                               if (!nflag)
-                                       fprintf(stdout, "%s: ", string);
-                               fprintf(stderr,
-                                   "kernel is not compiled for profiling\n");
-                               return;
-                       }
-                       if (!nflag)
-                               fprintf(stdout, "%s: %s\n", string,
-                                   state == GMON_PROF_OFF ? "off" : "running");
-                       return;
-               case KERN_VNODE:
-               case KERN_FILE:
-                       if (flags == 0)
-                               return;
-                       fprintf(stderr,
-                           "Use pstat to view %s information\n", string);
-                       return;
-               case KERN_PROC:
-                       if (flags == 0)
-                               return;
-                       fprintf(stderr,
-                           "Use ps to view %s information\n", string);
-                       return;
-               case KERN_CLOCKRATE:
-                       special |= CLOCK;
+       while ((ch = getopt(argc, argv, "AabdehiNnoqwxX")) != -1) {
+               switch (ch) {
+               case 'A':
+                       /* compatibility */
+                       aflag = oflag = 1;
                        break;
                        break;
-               case KERN_BOOTTIME:
-                       special |= BOOTTIME;
+               case 'a':
+                       aflag = 1;
                        break;
                        break;
-               case KERN_HOSTID:
-                       useUnsignedInt = 1;
+               case 'b':
+                       bflag = 1;
                        break;
                        break;
-               }
-               break;
-
-       case CTL_HW:
-               useUnsignedInt = 1;
-               break;
-
-       case CTL_VM:
-               if (mib[1] == VM_LOADAVG) {     /* XXX this is bogus */
-                       double loads[3];
-
-                       getloadavg(loads, 3);
-                       if (!nflag)
-                               fprintf(stdout, "%s: ", string);
-                       fprintf(stdout, "%.2f %.2f %.2f\n", 
-                           loads[0], loads[1], loads[2]);
-                       return;
-               }
-               if (flags == 0)
-                       return;
-               fprintf(stderr,
-                   "Use vmstat or systat to view %s information\n", string);
-               return;
-        
-       case CTL_DEBUG:
-               mib[2] = CTL_DEBUG_VALUE;
-               len = 3;
-               break;
-
-       case CTL_MACHDEP:
-#ifdef CPU_CONSDEV
-               if (mib[1] == CPU_CONSDEV)
-                       special |= CONSDEV;
-#endif
-               break;
-
-       case CTL_VFS:
-               mib[3] = mib[1];
-               mib[1] = VFS_GENERIC;
-               mib[2] = VFS_CONF;
-               len = 4;
-               size = sizeof vfc;
-               if (sysctl(mib, 4, &vfc, &size, (void *)0, (size_t)0) < 0) {
-                       perror("vfs print");
-                       return;
-               }
-               if (flags == 0 && vfc.vfc_refcount == 0)
-                       return;
-               if (!nflag)
-                       fprintf(stdout, "%s has %d mounted instance%s\n",
-                           string, vfc.vfc_refcount,
-                           vfc.vfc_refcount != 1 ? "s" : "");
-               else
-                       fprintf(stdout, "%d\n", vfc.vfc_refcount);
-               return;
-
-       case CTL_USER:
-               break;
-
-       default:
-               fprintf(stderr, "Illegal top level value: %d\n", mib[0]);
-               return;
-       
-       }
-       if (bufp) {
-               fprintf(stderr, "name %s in %s is unknown\n", bufp, string);
-               return;
-       }
-       if (newsize > 0) {
-               switch (type) {
-               case CTLTYPE_INT:
-                       if (useUnsignedInt) {   
-                               uintval = strtoul(newval, 0, 0);
-                               newval = &uintval;
-                               newsize = sizeof uintval;
-                       } else {
-                       intval = atoi(newval);
-                       newval = &intval;
-                       newsize = sizeof intval;
-                       }
+               case 'd':
+                       dflag = 1;
                        break;
                        break;
-
-               case CTLTYPE_QUAD:
-                       sscanf(newval, "%qd", &quadval);
-                       newval = &quadval;
-                       newsize = sizeof quadval;
+               case 'e':
+                       eflag = 1;
+                       break;
+               case 'h':
+                       hflag = 1;
+                       break;
+               case 'i':
+                       iflag = 1;
+                       break;
+               case 'N':
+                       Nflag = 1;
+                       break;
+               case 'n':
+                       nflag = 1;
+                       break;
+               case 'o':
+                       oflag = 1;
+                       break;
+               case 'q':
+                       qflag = 1;
+                       break;
+               case 'w':
+                       /* compatibility */
+                       /* ignored */
+                       break;
+               case 'X':
+                       /* compatibility */
+                       aflag = xflag = 1;
+                       break;
+               case 'x':
+                       xflag = 1;
                        break;
                        break;
-               }
-       }
-       size = BUFSIZ;
-       if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) {
-               if (flags == 0)
-                       return;
-               switch (errno) {
-               case EOPNOTSUPP:
-                       fprintf(stderr, "%s: value is not available\n", string);
-                       return;
-               case ENOTDIR:
-                       fprintf(stderr, "%s: specification is incomplete\n",
-                           string);
-                       return;
-               case ENOMEM:
-                       fprintf(stderr, "%s: type is unknown to this program\n",
-                           string);
-                       return;
                default:
                default:
-                       perror(string);
-                       return;
-               }
-       }
-       if (special & CLOCK) {
-               struct clockinfo *clkp = (struct clockinfo *)buf;
-
-               if (!nflag)
-                       fprintf(stdout, "%s: ", string);
-               fprintf(stdout,
-                   "hz = %d, tick = %d, profhz = %d, stathz = %d\n",
-                   clkp->hz, clkp->tick, clkp->profhz, clkp->stathz);
-               return;
-       }
-       if (special & BOOTTIME) {
-               struct timeval *btp = (struct timeval *)buf;
-
-               if (!nflag)
-                       fprintf(stdout, "%s = %s\n", string,
-                           ctime((time_t *) &btp->tv_sec));
-               else
-                       fprintf(stdout, "%d\n", btp->tv_sec);
-               return;
-       }
-       if (special & CONSDEV) {
-               dev_t dev = *(dev_t *)buf;
-
-               if (!nflag)
-                       fprintf(stdout, "%s = %s\n", string,
-                           devname(dev, S_IFCHR));
-               else
-                       fprintf(stdout, "0x%x\n", dev);
-               return;
-       }
-       switch (type) {
-       case CTLTYPE_INT:
-               if (newsize == 0) {
-                       if (!nflag)
-                               fprintf(stdout, "%s = ", string);
-                       fprintf(stdout, useUnsignedInt ? "%u\n" : "%d\n", *(int *)buf);
-               } else {
-                       if (!nflag)
-                               fprintf(stdout, useUnsignedInt ? "%s: %u -> " : "%s: %d -> ", 
-                                       string, *(int *)buf);
-                       fprintf(stdout, useUnsignedInt ? "%u\n" : "%d\n", *(int *)newval);
-               }
-               return;
-
-       case CTLTYPE_STRING:
-               if (newsize == 0) {
-                       if (!nflag)
-                               fprintf(stdout, "%s = ", string);
-                       fprintf(stdout, "%s\n", buf);
-               } else {
-                       if (!nflag)
-                               fprintf(stdout, "%s: %s -> ", string, buf);
-                       fprintf(stdout, "%s\n", (char *) newval);
-               }
-               return;
-
-       case CTLTYPE_QUAD:
-               if (newsize == 0) {
-                       if (!nflag)
-                               fprintf(stdout, "%s = ", string);
-                       fprintf(stdout, "%qd\n", *(quad_t *)buf);
-               } else {
-                       if (!nflag)
-                               fprintf(stdout, "%s: %qd -> ", string,
-                                   *(quad_t *)buf);
-                       fprintf(stdout, "%qd\n", *(quad_t *)newval);
-               }
-               return;
-
-       case CTLTYPE_STRUCT:
-               return;
-
-       default:
-       case CTLTYPE_NODE:
-               fprintf(stderr, "%s: unknown type returned\n",
-                   string);
-               return;
-       }
-}
-
-/*
- * Initialize the set of debugging names
- */
-void debuginit()
-{
-       int mib[3], loc, i;
-       size_t size;
-
-       if (secondlevel[CTL_DEBUG].list != 0)
-               return;
-       secondlevel[CTL_DEBUG].list = debugname;
-       mib[0] = CTL_DEBUG;
-       mib[2] = CTL_DEBUG_NAME;
-       for (loc = lastused, i = 0; i < CTL_DEBUG_MAXID; i++) {
-               mib[1] = i;
-               size = BUFSIZ - loc;
-               if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1)
-                       continue;
-               debugname[i].ctl_name = &names[loc];
-               debugname[i].ctl_type = CTLTYPE_INT;
-               loc += size;
-       }
-       lastused = loc;
-}
-
-/*
- * Initialize the set of filesystem names
- */
-void vfsinit()
-{
-       int mib[4], maxtypenum, cnt, loc, size;
-       struct vfsconf vfc;
-       size_t buflen;
-
-       if (secondlevel[CTL_VFS].list != 0)
-               return;
-       mib[0] = CTL_VFS;
-       mib[1] = VFS_GENERIC;
-       mib[2] = VFS_MAXTYPENUM;
-       buflen = 4;
-       if (sysctl(mib, 3, &maxtypenum, &buflen, (void *)0, (size_t)0) < 0)
-               return;
-       if ((vfsname = malloc(maxtypenum * sizeof(*vfsname))) == 0)
-               return;
-       memset(vfsname, 0, maxtypenum * sizeof(*vfsname));
-       mib[2] = VFS_CONF;
-       buflen = sizeof vfc;
-       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)
-                               continue;
-                       perror("vfsinit");
-                       free(vfsname);
-                       return;
+                       usage();
                }
                }
-               strcat(&names[loc], vfc.vfc_name);
-               vfsname[cnt].ctl_name = &names[loc];
-               vfsname[cnt].ctl_type = CTLTYPE_INT;
-               size = strlen(vfc.vfc_name) + 1;
-               loc += size;
-       }
-       lastused = loc;
-       secondlevel[CTL_VFS].list = vfsname;
-       secondlevel[CTL_VFS].size = maxtypenum;
-       return;
-}
-
-/*
- * Scan a list of names searching for a particular name.
- */
-int
-findname(string, level, bufp, namelist)
-       char *string;
-       char *level;
-       char **bufp;
-       struct list *namelist;
-{
-       char *name;
-       int i;
-
-       if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
-               fprintf(stderr, "%s: incomplete specification\n", string);
-               return (-1);
        }
        }
-       for (i = 0; i < namelist->size; i++)
-               if (namelist->list[i].ctl_name != NULL &&
-                   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);
-               return (-1);
-       }
-       return (i);
-}
+       argc -= optind;
+       argv += optind;
 
 
-void usage()
-{
+       if (Nflag && nflag)
+               usage();
+       if (aflag && argc == 0)
+               exit(sysctl_all(0, 0));
+       if (argc == 0)
+               usage();
 
 
-       (void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n",
-               "usage: sysctl [-bn] variable ...",
-               "       sysctl [-bn] -w variable=value ...",
-               "       sysctl [-bn] -a",
-               "       sysctl [-bn] -A",
-               "       sysctl [-bn] -X");
-       exit(1);
+       warncount = 0;
+       while (argc-- > 0)
+               parse(*argv++);
+       exit(warncount);
 }
 
 /*
 }
 
 /*
@@ -648,53 +190,63 @@ void usage()
  * Set a new value if requested.
  */
 static void
  * Set a new value if requested.
  */
 static void
-parse(char *string, int flags)
+parse(const char *string)
 {
        int len, i, j;
        void *newval = 0;
 {
        int len, i, j;
        void *newval = 0;
-       int intval, newsize = 0;
+       int intval;
        unsigned int uintval;
        unsigned int uintval;
-       quad_t quadval;
+       long longval;
+       unsigned long ulongval;
+       size_t newsize = 0;
+       int64_t i64val;
+       uint64_t u64val;
        int mib[CTL_MAXNAME];
        int mib[CTL_MAXNAME];
-       char *cp, *bufp, buf[BUFSIZ], fmt[BUFSIZ];
+       char *cp, *bufp, buf[BUFSIZ], *endptr, fmt[BUFSIZ];
        u_int kind;
 
        u_int kind;
 
-       bufp = buf;
-       snprintf(buf, BUFSIZ, "%s", string);
-       if ((cp = strchr(string, '=')) != NULL) {
-               if (!wflag)
-                       errx(2, "must specify -w to set variables");
-               *strchr(buf, '=') = '\0';
-               *cp++ = '\0';
+       cp = buf;
+       if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ)
+               errx(1, "oid too long: '%s'", string);
+       bufp = strsep(&cp, "=");
+       if (cp != NULL) {
                while (isspace(*cp))
                        cp++;
                newval = cp;
                newsize = strlen(cp);
                while (isspace(*cp))
                        cp++;
                newval = cp;
                newsize = strlen(cp);
-       } else {
-               if (wflag)
-                       usage();
        }
        len = name2oid(bufp, mib);
 
        if (len < 0) {
        }
        len = name2oid(bufp, mib);
 
        if (len < 0) {
-               if (cp != NULL) {
-                       while (*cp != '\0') cp--;
-                       *cp = '=';
-               }
-               old_parse (string, flags);
-               return;
+               if (iflag)
+                       return;
+               if (qflag)
+                       exit(1);
+               else
+                       errx(1, "unknown oid '%s'", bufp);
        }
 
        if (oidfmt(mib, len, fmt, &kind))
                err(1, "couldn't find format of oid '%s'", bufp);
 
        }
 
        if (oidfmt(mib, len, fmt, &kind))
                err(1, "couldn't find format of oid '%s'", bufp);
 
-       if (!wflag) {
+       if (newval == NULL || dflag) {
                if ((kind & CTLTYPE) == CTLTYPE_NODE) {
                if ((kind & CTLTYPE) == CTLTYPE_NODE) {
+                       if (dflag) {
+#ifdef __APPLE__
+                               i = show_var(mib, len, 1);
+#else
+                               i = show_var(mib, len);
+#endif
+                               if (!i && !bflag)
+                                       putchar('\n');
+                       }
                        sysctl_all(mib, len);
                        sysctl_all(mib, len);
-                       foundSome = 1;
-                       old_parse (string, flags);
                } else {
                } else {
+#ifdef __APPLE__
                        i = show_var(mib, len, 1);
                        i = show_var(mib, len, 1);
+#else
+                       i = show_var(mib, len);
+#endif
                        if (!i && !bflag)
                                putchar('\n');
                }
                        if (!i && !bflag)
                                putchar('\n');
                }
@@ -702,51 +254,117 @@ parse(char *string, int flags)
                if ((kind & CTLTYPE) == CTLTYPE_NODE)
                        errx(1, "oid '%s' isn't a leaf node", bufp);
 
                if ((kind & CTLTYPE) == CTLTYPE_NODE)
                        errx(1, "oid '%s' isn't a leaf node", bufp);
 
-               if (!(kind&CTLFLAG_WR))
-                       errx(1, "oid '%s' is read only", bufp);
-       
+               if (!(kind & CTLFLAG_WR)) {
+                       if (kind & CTLFLAG_TUN) {
+                               warnx("oid '%s' is a read only tunable", bufp);
+                               errx(1, "Tunable values are set in /boot/loader.conf");
+                       } else {
+                               errx(1, "oid '%s' is read only", bufp);
+                       }
+               }
+
+               if ((kind & CTLTYPE) == CTLTYPE_INT ||
+                   (kind & CTLTYPE) == CTLTYPE_UINT ||
+                   (kind & CTLTYPE) == CTLTYPE_LONG ||
+                   (kind & CTLTYPE) == CTLTYPE_ULONG ||
+                   (kind & CTLTYPE) == CTLTYPE_S64 ||
+                   (kind & CTLTYPE) == CTLTYPE_U64) {
+                       if (strlen(newval) == 0)
+                               errx(1, "empty numeric value");
+               }
+
                switch (kind & CTLTYPE) {
                        case CTLTYPE_INT:
                switch (kind & CTLTYPE) {
                        case CTLTYPE_INT:
-                               if ((*fmt == 'I') && (*(fmt + 1) == 'U')) {
-                                       uintval = (unsigned int) strtoul (newval, NULL, 0);
-                                       newval = &uintval;
-                                       newsize = sizeof uintval;
-                               } else {
-                                       intval = (int) strtol(newval, NULL, 0);
-                                       newval = &intval;
-                                       newsize = sizeof intval;
+                               if (strcmp(fmt, "IK") == 0) {
+#ifndef __APPLE__
+                                       if (!set_IK(newval, &intval))
+#endif
+                                               errx(1, "invalid value '%s'",
+                                                   (char *)newval);
+                               } else {
+                                       intval = (int)strtol(newval, &endptr,
+                                           0);
+                                       if (endptr == newval || *endptr != '\0')
+                                               errx(1, "invalid integer '%s'",
+                                                   (char *)newval);
                                }
                                }
+                               newval = &intval;
+                               newsize = sizeof(intval);
+                               break;
+                       case CTLTYPE_UINT:
+                               uintval = (int) strtoul(newval, &endptr, 0);
+                               if (endptr == newval || *endptr != '\0')
+                                       errx(1, "invalid unsigned integer '%s'",
+                                           (char *)newval);
+                               newval = &uintval;
+                               newsize = sizeof(uintval);
+                               break;
+                       case CTLTYPE_LONG:
+                               longval = strtol(newval, &endptr, 0);
+                               if (endptr == newval || *endptr != '\0')
+                                       errx(1, "invalid long integer '%s'",
+                                           (char *)newval);
+                               newval = &longval;
+                               newsize = sizeof(longval);
+                               break;
+                       case CTLTYPE_ULONG:
+                               ulongval = strtoul(newval, &endptr, 0);
+                               if (endptr == newval || *endptr != '\0')
+                                       errx(1, "invalid unsigned long integer"
+                                           " '%s'", (char *)newval);
+                               newval = &ulongval;
+                               newsize = sizeof(ulongval);
                                break;
                        case CTLTYPE_STRING:
                                break;
                                break;
                        case CTLTYPE_STRING:
                                break;
-                       case CTLTYPE_QUAD:
+                       case CTLTYPE_S64:
+                               i64val = strtoimax(newval, &endptr, 0);
+                               if (endptr == newval || *endptr != '\0')
+                                       errx(1, "invalid int64_t '%s'",
+                                           (char *)newval);
+                               newval = &i64val;
+                               newsize = sizeof(i64val);
                                break;
                                break;
-                               sscanf(newval, "%qd", &quadval);
-                               newval = &quadval;
-                               newsize = sizeof quadval;
+                       case CTLTYPE_U64:
+                               u64val = strtoumax(newval, &endptr, 0);
+                               if (endptr == newval || *endptr != '\0')
+                                       errx(1, "invalid uint64_t '%s'",
+                                           (char *)newval);
+                               newval = &u64val;
+                               newsize = sizeof(u64val);
                                break;
                                break;
+                       case CTLTYPE_OPAQUE:
+                               /* FALLTHROUGH */
                        default:
                                errx(1, "oid '%s' is type %d,"
                                        " cannot set that", bufp,
                                        kind & CTLTYPE);
                }
 
                        default:
                                errx(1, "oid '%s' is type %d,"
                                        " cannot set that", bufp,
                                        kind & CTLTYPE);
                }
 
+#ifdef __APPLE__
                i = show_var(mib, len, 1);
                i = show_var(mib, len, 1);
+#else
+               i = show_var(mib, len);
+#endif
                if (sysctl(mib, len, 0, 0, newval, newsize) == -1) {
                        if (!i && !bflag)
                                putchar('\n');
                        switch (errno) {
                if (sysctl(mib, len, 0, 0, newval, newsize) == -1) {
                        if (!i && !bflag)
                                putchar('\n');
                        switch (errno) {
+#ifdef __APPLE__
+                       case ENOTSUP:
+#endif // __APPLE__
                        case EOPNOTSUPP:
                        case EOPNOTSUPP:
-                               errx(1, "%s: value is not available", 
+                               errx(1, "%s: value is not available",
                                        string);
                        case ENOTDIR:
                                        string);
                        case ENOTDIR:
-                               errx(1, "%s: specification is incomplete", 
+                               errx(1, "%s: specification is incomplete",
                                        string);
                        case ENOMEM:
                                        string);
                        case ENOMEM:
-                               errx(1, "%s: type is unknown to this program", 
+                               errx(1, "%s: type is unknown to this program",
                                        string);
                        default:
                                warn("%s", string);
                                        string);
                        default:
                                warn("%s", string);
+                               warncount++;
                                return;
                        }
                }
                                return;
                        }
                }
@@ -754,7 +372,11 @@ parse(char *string, int flags)
                        printf(" -> ");
                i = nflag;
                nflag = 1;
                        printf(" -> ");
                i = nflag;
                nflag = 1;
+#ifdef __APPLE__
                j = show_var(mib, len, 1);
                j = show_var(mib, len, 1);
+#else
+               j = show_var(mib, len);
+#endif
                if (!j && !bflag)
                        putchar('\n');
                nflag = i;
                if (!j && !bflag)
                        putchar('\n');
                nflag = i;
@@ -767,10 +389,20 @@ static int
 S_clockinfo(int l2, void *p)
 {
        struct clockinfo *ci = (struct clockinfo*)p;
 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 }",
-               ci->hz, ci->tick, ci->tickadj, ci->profhz, ci->stathz);
+
+       if (l2 != sizeof(*ci)) {
+               warnx("S_clockinfo %d != %zu", l2, sizeof(*ci));
+               return (1);
+       }
+#ifdef __APPLE__
+       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);
+#else
+       printf(hflag ? "{ hz = %'d, tick = %'d, profhz = %'d, stathz = %'d }" :
+               "{ hz = %d, tick = %d, profhz = %d, stathz = %d }",
+               ci->hz, ci->tick, ci->profhz, ci->stathz);
+#endif
        return (0);
 }
 
        return (0);
 }
 
@@ -779,10 +411,11 @@ S_loadavg(int l2, void *p)
 {
        struct loadavg *tv = (struct loadavg*)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 != %zu", 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);
                (double)tv->ldavg[0]/(double)tv->fscale,
                (double)tv->ldavg[1]/(double)tv->fscale,
                (double)tv->ldavg[2]/(double)tv->fscale);
@@ -796,16 +429,101 @@ S_timeval(int l2, void *p)
        time_t tv_sec;
        char *p1, *p2;
 
        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 != %zu", 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);
        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);
+}
+
+#ifndef __APPLE__
+static int
+S_vmtotal(int l2, void *p)
+{
+       struct vmtotal *v = (struct vmtotal *)p;
+       int pageKilo = getpagesize() / 1024;
+
+       if (l2 != sizeof(*v)) {
+               warnx("S_vmtotal %d != %zu", l2, sizeof(*v));
+               return (1);
+       }
+
+       printf(
+           "\nSystem wide totals computed every five seconds:"
+           " (values in kilobytes)\n");
+       printf("===============================================\n");
+       printf(
+           "Processes:\t\t(RUNQ: %hd Disk Wait: %hd Page Wait: "
+           "%hd Sleep: %hd)\n",
+           v->t_rq, v->t_dw, v->t_pw, v->t_sl);
+       printf(
+           "Virtual Memory:\t\t(Total: %dK Active: %dK)\n",
+           v->t_vm * pageKilo, v->t_avm * pageKilo);
+       printf("Real Memory:\t\t(Total: %dK Active: %dK)\n",
+           v->t_rm * pageKilo, v->t_arm * pageKilo);
+       printf("Shared Virtual Memory:\t(Total: %dK Active: %dK)\n",
+           v->t_vmshr * pageKilo, v->t_avmshr * pageKilo);
+       printf("Shared Real Memory:\t(Total: %dK Active: %dK)\n",
+           v->t_rmshr * pageKilo, v->t_armshr * pageKilo);
+       printf("Free Memory:\t%dK\n", v->t_free * pageKilo);
+
+       return (0);
+}
+
+static int
+set_IK(const char *str, int *val)
+{
+       float temp;
+       int len, kelv;
+       const char *p;
+       char *endptr;
+
+       if ((len = strlen(str)) == 0)
+               return (0);
+       p = &str[len - 1];
+       if (*p == 'C' || *p == 'F') {
+               temp = strtof(str, &endptr);
+               if (endptr == str || endptr != p)
+                       return (0);
+               if (*p == 'F')
+                       temp = (temp - 32) * 5 / 9;
+               kelv = temp * 10 + 2732;
+       } else {
+               kelv = (int)strtol(str, &endptr, 10);
+               if (endptr == str || *endptr != '\0')
+                       return (0);
+       }
+       *val = kelv;
+       return (1);
+}
+#endif // !__APPLE__
+
+#ifdef __APPLE__
+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);
 }
 
        return (0);
 }
 
@@ -813,8 +531,11 @@ static int
 T_dev_t(int l2, void *p)
 {
        dev_t *d = (dev_t *)p;
 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 }",
        if ((int)(*d) != -1) {
                if (minor(*d) > 255 || minor(*d) < 0)
                        printf("{ major = %d, minor = 0x%x }",
@@ -826,6 +547,28 @@ T_dev_t(int l2, void *p)
        return (0);
 }
 
        return (0);
 }
 
+static int
+S_quads(int len, void *p)
+{
+       size_t size = sizeof(int64_t);
+       if (len & (size-1)) {
+               return 1;
+       }
+       while (len > 0) {
+               int64_t i = *(int64_t *)p;
+               printf("%llu", i);
+               if (len > size) {
+                       len -= size;
+                       p = (uintptr_t)p + size;
+                       printf(" ");
+               } else {
+                       break;
+               }
+       }
+       return 0;
+}
+#endif // __APPLE__
+
 /*
  * These functions uses a presently undocumented interface to the kernel
  * to walk the tree and get the type so it can print the value.
 /*
  * These functions uses a presently undocumented interface to the kernel
  * to walk the tree and get the type so it can print the value.
@@ -842,15 +585,36 @@ name2oid(char *name, int *oidp)
        int i;
        size_t j;
 
        int i;
        size_t j;
 
+#ifdef __APPLE__
+       // Support for CTL_USER
+       const char *user = names[CTL_USER].ctl_name;
+       j = strlen(user);
+       if (!strncmp(name, user, j)) {
+               oidp[0] = CTL_USER;
+               if (name[j] == '.') {
+                       for (i = 1; i < user_names_count; ++i) {
+                               if (!strcmp(&name[j+1], user_names[i].ctl_name)) {
+                                       oidp[1] = i;
+                                       return 2;
+                               }
+                       }
+                       return -1;
+               } else if (name[j] == 0) {
+                       return 1;
+               }
+               return -1;
+       }
+#endif
+
        oid[0] = 0;
        oid[1] = 3;
 
        oid[0] = 0;
        oid[1] = 3;
 
-       j = CTL_MAXNAME * sizeof (int);
+       j = CTL_MAXNAME * sizeof(int);
        i = sysctl(oid, 2, oidp, &j, name, strlen(name));
        i = sysctl(oid, 2, oidp, &j, name, strlen(name));
-       if (i < 0) 
-               return i;
-       j /= sizeof (int);
-       return (j);
+       if (i < 0)
+               return (i);
+       j /= sizeof(int);
+       return (int)j;
 }
 
 static int
 }
 
 static int
@@ -865,19 +629,92 @@ oidfmt(int *oid, int len, char *fmt, u_int *kind)
        qoid[1] = 4;
        memcpy(qoid + 2, oid, len * sizeof(int));
 
        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);
        i = sysctl(qoid, len + 2, buf, &j, 0, 0);
+#ifdef __APPLE__
+       if (i && errno == ENOENT) {
+               // Support for CTL_USER
+               if (oid[0] == CTL_USER) {
+                       if (len == 1) {
+                               *kind = CTLTYPE_NODE;
+                               return 0;
+                       } else if (len == 2 && oid[1] < user_names_count) {
+                               *kind = user_names[oid[1]].ctl_type;
+                               return 0;
+                       }
+               }
+               return 1;
+       }
+#endif
        if (i)
        if (i)
-               err(1, "sysctl fmt %d %d %d", i, j, errno);
+               err(1, "sysctl fmt %d %zu %d", i, j, errno);
 
        if (kind)
 
        if (kind)
+#ifdef __APPLE__
+               memcpy(kind, buf, sizeof(*kind));
+#else
                *kind = *(u_int *)buf;
                *kind = *(u_int *)buf;
+#endif
 
        if (fmt)
                strcpy(fmt, (char *)(buf + sizeof(u_int)));
 
        if (fmt)
                strcpy(fmt, (char *)(buf + sizeof(u_int)));
-       return 0;
+
+#ifdef __APPLE__
+       // Map Darwin sysctl types to FreeBSD types.
+       // - 0 with "I" -> CTLTYPE_INT
+       // - 0 with "S," -> CTLTYPE_STRUCT
+       // - CTLTYPE_INT with "IU" -> CTLTYPE_UINT
+       // - CTLTYPE_INT with "L" -> CTLTYPE_LONG
+       // - CTLTYPE_QUAD -> CTLTYPE_S64
+       // - CTLTYPE_QUAD with "*U" -> CTLTYPE_U64
+       if (kind) {
+               switch (*kind & CTLTYPE) {
+                       case 0:
+                       case CTLTYPE_INT:
+                               if (buf[sizeof(u_int)] == 'S') {
+                                       *kind = (*kind & ~CTLTYPE) | CTLTYPE_STRUCT;
+                               } else if (buf[sizeof(u_int)] == 'I') {
+                                       *kind = (*kind & ~CTLTYPE) | CTLTYPE_INT;
+                                       if (buf[sizeof(u_int)+1] == 'U') {
+                                               *kind = (*kind & ~CTLTYPE) | CTLTYPE_UINT;
+                                       }
+                               } else if (buf[sizeof(u_int)] == 'L') {
+                                       *kind = (*kind & ~CTLTYPE) | CTLTYPE_LONG;
+                    if (buf[sizeof(u_int)+1] == 'U') {
+                        *kind = (*kind & ~CTLTYPE) | CTLTYPE_ULONG;
+                    }
+                               }
+                               break;
+                       case CTLTYPE_QUAD:
+                               *kind = (*kind & ~CTLTYPE);
+                               if (fmt && strchr(fmt, 'U')) {
+                                       *kind |= CTLTYPE_U64;
+                               } else {
+                                       *kind |= CTLTYPE_S64;
+                               }
+                               break;
+               }
+       }
+#endif
+
+       return (0);
 }
 
 }
 
+static int ctl_sign[CTLTYPE+1] = {
+       [CTLTYPE_INT] = 1,
+       [CTLTYPE_LONG] = 1,
+       [CTLTYPE_S64] = 1,
+};
+
+static int ctl_size[CTLTYPE+1] = {
+       [CTLTYPE_INT] = sizeof(int),
+       [CTLTYPE_UINT] = sizeof(u_int),
+       [CTLTYPE_LONG] = sizeof(long),
+       [CTLTYPE_ULONG] = sizeof(u_long),
+       [CTLTYPE_S64] = sizeof(int64_t),
+       [CTLTYPE_U64] = sizeof(int64_t),
+};
+
 /*
  * This formats and outputs the value of one variable
  *
 /*
  * This formats and outputs the value of one variable
  *
@@ -885,219 +722,284 @@ oidfmt(int *oid, int len, char *fmt, u_int *kind)
  * Returns one if didn't know what to do with this.
  * Return minus one if we had errors.
  */
  * Returns one if didn't know what to do with this.
  * Return minus one if we had errors.
  */
-
 static int
 static int
+#ifdef __APPLE__
 show_var(int *oid, int nlen, int show_masked)
 show_var(int *oid, int nlen, int show_masked)
+#else
+show_var(int *oid, int nlen)
+#endif
 {
 {
-       u_char buf[BUFSIZ], *val, *mval, *p;
-       char name[BUFSIZ], /* descr[BUFSIZ], */ *fmt;
+       u_char buf[BUFSIZ], *val, *oval, *p;
+       char name[BUFSIZ], *fmt;
+       const char *sep, *sep1;
        int qoid[CTL_MAXNAME+2];
        int qoid[CTL_MAXNAME+2];
-       int i;
-       int retval;
+       uintmax_t umv;
+       intmax_t mv;
+       int i, hexlen, sign, ctltype;
+       size_t intlen;
        size_t j, len;
        u_int kind;
        size_t j, len;
        u_int kind;
-       int (*func)(int, void *) = 0;
+       int (*func)(int, void *);
+
+       /* Silence GCC. */
+       umv = mv = intlen = 0;
 
 
+       bzero(buf, BUFSIZ);
+       bzero(name, BUFSIZ);
        qoid[0] = 0;
        memcpy(qoid + 2, oid, nlen * sizeof(int));
 
        qoid[0] = 0;
        memcpy(qoid + 2, oid, nlen * sizeof(int));
 
+#ifdef __APPLE__
+       // Support for CTL_USER
+       if (nlen >= 1 && oid[0] == CTL_USER) {
+               const char *user_name = "";
+               sep = "";
+               i = oid[1];
+               if (nlen == 2 && i > 0 && i < user_names_count) {
+                       user_name = user_names[i].ctl_name;
+                       sep = ".";
+               }
+               j = snprintf(name, sizeof(name), "%s%s%s",
+                            names[CTL_USER].ctl_name, sep, user_name);
+               i = 0;
+       } else {
+#endif
        qoid[1] = 1;
        qoid[1] = 1;
-       j = sizeof name;
+       j = sizeof(name);
        i = sysctl(qoid, nlen + 2, name, &j, 0, 0);
        if (i || !j)
        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 %zu %d", i, j, errno);
+#ifdef __APPLE__
+       }
+#endif
+
+       if (Nflag) {
+               printf("%s", name);
+               return (0);
+       }
 
 
+       if (eflag)
+               sep = "=";
+       else
+               sep = ": ";
+
+       if (dflag) {    /* just print description */
+               qoid[1] = 5;
+               j = sizeof(buf);
+               i = sysctl(qoid, nlen + 2, buf, &j, 0, 0);
+               if (!nflag)
+                       printf("%s%s", name, sep);
+               printf("%s", buf);
+               return (0);
+       }
        /* 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 :-) */
 
        /* 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 = mval = malloc(j);
+       val = oval = malloc(j + 1);
+       if (val == NULL) {
+               warnx("malloc failed");
+               return (1);
+       }
        len = j;
        i = sysctl(oid, nlen, val, &len, 0, 0);
        if (i || !len) {
        len = j;
        i = sysctl(oid, nlen, val, &len, 0, 0);
        if (i || !len) {
-               retval = 1;
-               goto RETURN;
+               free(oval);
+               return (1);
        }
 
        if (bflag) {
                fwrite(val, 1, len, stdout);
        }
 
        if (bflag) {
                fwrite(val, 1, len, stdout);
-               retval = 0;
-               goto RETURN;
+               free(oval);
+               return (0);
        }
        }
+       val[len] = '\0';
+       fmt = (char *)buf;
+       oidfmt(oid, nlen, fmt, &kind);
+       p = val;
+       ctltype = (kind & CTLTYPE);
+       sign = ctl_sign[ctltype];
+       intlen = ctl_size[ctltype];
 
 
-       qoid[1] = 4;
-       j = sizeof buf;
-       i = sysctl(qoid, nlen + 2, buf, &j, 0, 0);
-       if (i || !j)
-               err(1, "sysctl fmt %d %d %d", i, j, errno);
-
-       kind = *(u_int *)buf;
+#ifdef __APPLE__
        if (!show_masked && (kind & CTLFLAG_MASKED)) {
        if (!show_masked && (kind & CTLFLAG_MASKED)) {
-               retval = 1;
-               goto RETURN;
+               free(oval);
+               return (1);
        }
        }
+#endif
 
 
-       fmt = (char *)(buf + sizeof(u_int));
-       
-       /* XXX special-case hack for hw.physmem */
-       if ((oid[0] == CTL_HW) && (oid[1] == HW_PHYSMEM))
-               fmt = "IU";
-
-       p = val;
-       switch (*fmt) {
-       case '-':
-               /* deprecated, do not print */
-               retval = 0;
-               goto RETURN;
-               
-
-       case 'A':
-               if (!nflag)
-                       printf("%s: ", name);
-               printf("%s", p);
-               retval = 0;
-               goto RETURN;
-               
-       case 'I':
-               if (!nflag)
-                       printf("%s: ", name);
-               fmt++;
-               val = "";
-               while (len >= sizeof(int)) {
-                       if(*fmt == 'U')
-                               printf("%s%u", val, *(unsigned int *)p);
-                       else
-                               printf("%s%d", val, *(int *)p);
-                       val = " ";
-                       len -= sizeof (int);
-                       p += sizeof (int);
-               }
-               retval = 0;
-               goto RETURN;
-
-       case 'L':
-               if (!nflag)
-                       printf("%s: ", name);
-               fmt++;
-               val = "";
-               while (len >= sizeof(long)) {
-                       if(*fmt == 'U')
-                               printf("%s%lu", val, *(unsigned long *)p);
-                       else
-                               printf("%s%ld", val, *(long *)p);
-                       val = " ";
-                       len -= sizeof (long);
-                       p += sizeof (long);
-               }
-               retval = 0;
-               goto RETURN;
-
-       case 'P':
+       switch (ctltype) {
+       case CTLTYPE_STRING:
                if (!nflag)
                if (!nflag)
-                       printf("%s: ", name);
-               printf("%p", *(void **)p);
-               retval = 0;
-               goto RETURN;
+                       printf("%s%s", name, sep);
+               printf("%.*s", (int)len, p);
+               free(oval);
+               return (0);
 
 
-       case 'Q':
+       case CTLTYPE_INT:
+       case CTLTYPE_UINT:
+       case CTLTYPE_LONG:
+       case CTLTYPE_ULONG:
+       case CTLTYPE_S64:
+       case CTLTYPE_U64:
                if (!nflag)
                if (!nflag)
-                       printf("%s: ", name);
-               fmt++;
-               val = "";
-               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 = " ";
-                       len -= sizeof (long long);
-                       p += sizeof (long long);
+                       printf("%s%s", name, sep);
+               hexlen = (int)(2 + (intlen * CHAR_BIT + 3) / 4);
+               sep1 = "";
+               while (len >= intlen) {
+                       switch (kind & CTLTYPE) {
+                       case CTLTYPE_INT:
+                       case CTLTYPE_UINT:
+                               umv = *(u_int *)(void *)p;
+                               mv = *(int *)(void *)p;
+                               break;
+                       case CTLTYPE_LONG:
+                       case CTLTYPE_ULONG:
+                               umv = *(u_long *)(void *)p;
+                               mv = *(long *)(void *)p;
+                               break;
+                       case CTLTYPE_S64:
+                       case CTLTYPE_U64:
+                               umv = *(uint64_t *)(void *)p;
+                               mv = *(int64_t *)(void *)p;
+                               break;
+                       }
+                       fputs(sep1, stdout);
+                       if (xflag)
+                               printf("%#0*jx", hexlen, umv);
+                       else if (!sign)
+                               printf(hflag ? "%'ju" : "%ju", umv);
+                       else if (fmt[1] == 'K') {
+                               if (mv < 0)
+                                       printf("%jd", mv);
+                               else
+                                       printf("%.1fC", (mv - 2732.0) / 10);
+                       } else
+                               printf(hflag ? "%'jd" : "%jd", mv);
+                       sep1 = " ";
+                       len -= intlen;
+                       p += intlen;
                }
                }
-               retval = 0;
-               goto RETURN;
-
+               free(oval);
+               return (0);
 
 
-       case 'T':
-       case 'S':
+       case CTLTYPE_OPAQUE:
                i = 0;
                i = 0;
-               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, "T,dev_t"))       func = T_dev_t;
+               if (strcmp(fmt, "S,clockinfo") == 0)
+                       func = S_clockinfo;
+               else if (strcmp(fmt, "S,timeval") == 0)
+                       func = S_timeval;
+               else if (strcmp(fmt, "S,loadavg") == 0)
+                       func = S_loadavg;
+#ifdef __APPLE__
+               else if (!strcmp(fmt, "S,xsw_usage"))
+                       func = S_xswusage;
+               else if (!strcmp(fmt, "T,dev_t"))
+                       func = T_dev_t;
+               else if (!strcmp(fmt, "Q"))
+                       func = S_quads;
+#else // !__APPLE__
+               else if (strcmp(fmt, "S,vmtotal") == 0)
+                       func = S_vmtotal;
+#endif // !__APPLE__
+               else
+                       func = NULL;
                if (func) {
                        if (!nflag)
                if (func) {
                        if (!nflag)
-                               printf("%s: ", name);
-                       retval = (*func)(len, p);
-                       goto RETURN;
+                               printf("%s%s", name, sep);
+                       i = (*func)((int)len, p);
+                       free(oval);
+                       return (i);
                }
                }
-               /* FALL THROUGH */
+               /* FALLTHROUGH */
        default:
        default:
-               if (!Aflag) {
-                       retval = 1;
-                       goto RETURN;
+               if (!oflag && !xflag) {
+                       free(oval);
+                       return (1);
                }
                if (!nflag)
                }
                if (!nflag)
-                       printf("%s: ", name);
-               printf("Format:%s Length:%ld Dump:0x", fmt, len);
-               while (len--) {
+                       printf("%s%s", name, sep);
+               printf("Format:%s Length:%zu Dump:0x", fmt, len);
+               while (len-- && (xflag || p < val + 16))
                        printf("%02x", *p++);
                        printf("%02x", *p++);
-                       if (Xflag || p < val+16)
-                               continue;
+               if (!xflag && len > 16)
                        printf("...");
                        printf("...");
-                       break;
-               }
-               retval = 0;
-               goto RETURN;
+               free(oval);
+               return (0);
        }
        }
+       free(oval);
+       return (1);
+}
 
 
-       retval = 1;
-       RETURN:
-       free(mval);
-       return (retval);
+#ifdef __APPLE__
+// Support for CTL_USER
+static void
+sysctl_all_user(int *oid, int len)
+{
+       int i, j;
+       if (len > 1 || (len == 1 && oid[0] != CTL_USER)) {
+               return;
+       }
+       for (i = 0; i < user_names_count; ++i) {
+               int oid[2] = { CTL_USER, i };
+               j = show_var(oid, 2, 0);
+               if (!j && !bflag) {
+                       putchar('\n');
+               }
+       }
 }
 }
+#endif
 
 static int
 
 static int
-sysctl_all (int *oid, int len)
+sysctl_all(int *oid, int len)
 {
        int name1[22], name2[22];
        int i, j;
        size_t l1, l2;
 
 {
        int name1[22], name2[22];
        int i, j;
        size_t l1, l2;
 
+#ifdef __APPLE__
+       sysctl_all_user(oid, len);
+#endif
+
        name1[0] = 0;
        name1[1] = 2;
        l1 = 2;
        if (len) {
        name1[0] = 0;
        name1[1] = 2;
        l1 = 2;
        if (len) {
-               memcpy(name1+2, oid, len*sizeof (int));
+               memcpy(name1+2, oid, len * sizeof(int));
                l1 += len;
        } else {
                name1[2] = 1;
                l1++;
        }
                l1 += len;
        } else {
                name1[2] = 1;
                l1++;
        }
-       while (1) {
-               l2 = sizeof name2;
-               j = sysctl(name1, l1, name2, &l2, 0, 0);
+       for (;;) {
+               l2 = sizeof(name2);
+               j = sysctl(name1, (u_int)l1, name2, &l2, 0, 0);
                if (j < 0) {
                        if (errno == ENOENT)
                if (j < 0) {
                        if (errno == ENOENT)
-                               return 0;
+                               return (0);
                        else
                        else
-                               err(1, "sysctl(getnext) %d %d", j, l2);
+                               err(1, "sysctl(getnext) %d %zu", j, l2);
                }
 
                }
 
-               l2 /= sizeof (int);
+               l2 /= sizeof(int);
 
 
-               if (l2 < len)
-                       return 0;
+               if (len < 0 || l2 < (unsigned int)len)
+                       return (0);
 
                for (i = 0; i < len; i++)
                        if (name2[i] != oid[i])
 
                for (i = 0; i < len; i++)
                        if (name2[i] != oid[i])
-                               return 0;
+                               return (0);
 
 
-               i = show_var(name2, l2, 0);
+#ifdef __APPLE__
+               i = show_var(name2, (u_int)l2, 0);
+#else
+               i = show_var(name2, (u_int)l2);
+#endif
                if (!i && !bflag)
                        putchar('\n');
 
                if (!i && !bflag)
                        putchar('\n');
 
-               memcpy(name1+2, name2, l2*sizeof (int));
+               memcpy(name1+2, name2, l2 * sizeof(int));
                l1 = 2 + l2;
        }
 }
                l1 = 2 + l2;
        }
 }