summaryrefslogtreecommitdiffstats
path: root/sbin/sysctl
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>1995-12-21 12:39:25 +0000
committerphk <phk@FreeBSD.org>1995-12-21 12:39:25 +0000
commit160da4bc8b11d5bd77d01a089018767822aa8995 (patch)
treef3e24d02e5a7a6b4d3c8ff434f3ed95b2dd53f6a /sbin/sysctl
parent15fd08703140e2413a5a6c4c6e6fb23c8310efba (diff)
downloadFreeBSD-src-160da4bc8b11d5bd77d01a089018767822aa8995.zip
FreeBSD-src-160da4bc8b11d5bd77d01a089018767822aa8995.tar.gz
The rewamped sysctl program that will find all the variables itself.
Also a couple of handy new options.
Diffstat (limited to 'sbin/sysctl')
-rw-r--r--sbin/sysctl/sysctl.852
-rw-r--r--sbin/sysctl/sysctl.c763
2 files changed, 372 insertions, 443 deletions
diff --git a/sbin/sysctl/sysctl.8 b/sbin/sysctl/sysctl.8
index 931ac35..c09b418 100644
--- a/sbin/sysctl/sysctl.8
+++ b/sbin/sysctl/sysctl.8
@@ -30,7 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" From: @(#)sysctl.8 8.1 (Berkeley) 6/6/93
-.\" $Id: sysctl.8,v 1.5 1995/02/16 00:28:40 wollman Exp $
+.\" $Id: sysctl.8,v 1.6 1995/02/20 19:42:42 guido Exp $
.\"
.Dd September 23, 1994
.Dt SYSCTL 8
@@ -40,15 +40,15 @@
.Nd get or set kernel state
.Sh SYNOPSIS
.Nm sysctl
-.Op Fl n
+.Op Fl bn
.Ar name ...
.Nm sysctl
-.Op Fl n
+.Op Fl bn
.Fl w
.Ar name=value ...
.Nm sysctl
-.Op Fl n
-.Fl aA
+.Op Fl bn
+.Fl aAX
.Sh DESCRIPTION
The
.Nm sysctl
@@ -57,16 +57,25 @@ appropriate privilege to set kernel state.
The state to be retrieved or set is described using a
``Management Information Base'' (``MIB'') style name,
described as a dotted set of components.
+.Pp
The
.Fl a
flag can be used to list all the currently available string or integer values.
+.Pp
The
.Fl A
-flag will list all the known MIB names including tables.
+flag will list all the known MIB names including opaques.
Those with string or integer values will be printed as with the
.Fl a
-flag; for the table values,
-the name of the utility to retrieve them is given.
+flag; for the opaque values,
+information about the format and the length is printed in addition the first
+few bytes is dumped in hex.
+.Pp
+The
+.Fl X
+flag is the same as
+.Fl A
+except the entire value of opaque variables is hexdumped.
.Pp
The
.Fl n
@@ -78,6 +87,12 @@ For example, to save the pagesize in variable psize, use:
set psize=`sysctl -n hw.pagesize`
.Ed
.Pp
+The
+.Fl b
+flag forces the value of the variable(s) to be output in raw, binary
+format. No names are printed and no terminating newlines are output.
+This is mostly useful with a single variable.
+.Pp
If just a MIB style name is given,
the corresponding value is retrieved.
If a value is to be set, the
@@ -87,16 +102,21 @@ by an equal sign and the new value to be used.
.Pp
The information available from
.Nm sysctl
-consists of integers, strings, and tables.
-The tabular information can only be retrieved by special
+consists of integers, strings, and opaques.
+.Nm sysctl
+only knows about a couple of opaque types, and will resort to hexdumps
+for the rest.
+The opaque information is much more useful if retrieved by special
purpose programs such as
.Nm ps ,
.Nm systat ,
and
.Nm netstat .
+.Pp
The string and integer information is summaried below.
For a detailed description of these variable see
.Xr sysctl 3 .
+.Pp
The changeable column indicates whether a process with appropriate
privilege can change the value.
.Bl -column net.inet.ip.forwardingxxxxxx integerxxx
@@ -187,6 +207,10 @@ Information about the load average history may be obtained with
.Bd -literal -offset indent -compact
sysctl vm.loadavg
.Ed
+.Pp
+More variables than these exist, and the best and likely only place
+to search for their deeper meaning is undoubtedly the source where
+they are defined.
.Sh FILES
.Bl -tag -width <netinet/icmpXvar.h> -compact
.It Pa <sys/sysctl.h>
@@ -208,6 +232,14 @@ definitions for fourth level UDP identifiers
.El
.Sh SEE ALSO
.Xr sysctl 3
+.Sh BUGS
+.Nm sysctl
+presently exploits an undocumented interface to the kernel
+sysctl facility to traverse the sysctl tree and to retrive format
+and name information.
+This correct interface is being thought about for the time being.
.Sh HISTORY
.Nm sysctl
first appeared in 4.4BSD.
+.Pp
+In FreeBSD 2.2 sysctl was significantly remodeled.
diff --git a/sbin/sysctl/sysctl.c b/sbin/sysctl/sysctl.c
index b66f9d1..11418fc 100644
--- a/sbin/sysctl/sysctl.c
+++ b/sbin/sysctl/sysctl.c
@@ -40,165 +40,89 @@ static char copyright[] =
#ifndef lint
/*static char sccsid[] = "From: @(#)sysctl.c 8.1 (Berkeley) 6/6/93"; */
static const char rcsid[] =
- "$Id: sysctl.c,v 1.7 1995/06/11 19:32:58 rgrimes Exp $";
+ "$Id: sysctl.c,v 1.8 1995/11/17 16:28:42 phk Exp $";
#endif /* not lint */
-#include <sys/param.h>
-#include <sys/gmon.h>
+#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
-#include <sys/socket.h>
-#include <vm/vm_param.h>
-#include <machine/cpu.h>
-
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-#include <netinet/icmp_var.h>
-#include <netinet/ip_var.h>
-#include <netinet/udp.h>
-#include <netinet/udp_var.h>
-#include <netinet/tcp.h>
-#include <netinet/tcp_seq.h>
-#include <netinet/tcp_timer.h>
-#include <netinet/tcp_var.h>
-#include <netinet/igmp_var.h>
+#include <sys/resource.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <ctype.h>
+#include <err.h>
-struct ctlname topname[] = CTL_NAMES;
-struct ctlname kernname[] = CTL_KERN_NAMES;
-struct ctlname vmname[] = CTL_VM_NAMES;
-struct ctlname netname[] = CTL_NET_NAMES;
-struct ctlname hwname[] = CTL_HW_NAMES;
-struct ctlname username[] = CTL_USER_NAMES;
-#ifdef CTL_MACHDEP_NAMES
-struct ctlname machdepname[] = CTL_MACHDEP_NAMES;
-#endif
-char names[BUFSIZ];
-
-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_FS */
- { netname, NET_MAXID }, /* CTL_NET */
- { 0, 0 }, /* CTL_DEBUG */
- { hwname, HW_MAXID }, /* CTL_HW */
-#ifdef CTL_MACHDEP_NAMES
- { machdepname, CPU_MAXID }, /* CTL_MACHDEP */
-#else
- { 0, 0 }, /* CTL_MACHDEP */
-#endif
- { username, USER_MAXID }, /* CTL_USER_NAMES */
-};
-
-int Aflag, aflag, nflag, wflag;
+static int Aflag, aflag, nflag, wflag, Xflag, bflag;
-/*
- * Variables requiring special processing.
- */
-#define CLOCK 0x00000001
-#define BOOTTIME 0x00000002
-#define CONSDEV 0x00000004
-#define DUMPDEV 0x00000008
+static int oidfmt(int *, int, char *, u_int *);
+static void parse(char *);
+static int show_var(int *, int);
+static int sysctl_all (int *oid, int len);
+static int name2oid(char *, int *);
+
+static void
+usage(void)
+{
+
+ (void)fprintf(stderr, "usage:\n%s",
+ "\tsysctl [-bnX] variable ...\n"
+ "\tsysctl [-bnX] -w variable=value ...\n"
+ "\tsysctl [-bnX] -a\n"
+ "\tsysctl [-bnX] -A\n"
+ );
+ exit(1);
+}
int
-main(argc, argv)
- int argc;
- char *argv[];
+main(int argc, char **argv)
{
extern char *optarg;
extern int optind;
- int ch, lvl1;
+ int ch;
+ setbuf(stdout,0);
+ setbuf(stderr,0);
- while ((ch = getopt(argc, argv, "Aanw")) != EOF) {
+ while ((ch = getopt(argc, argv, "AabnwX")) != EOF) {
switch (ch) {
-
- case 'A':
- Aflag = 1;
- break;
-
- case 'a':
- aflag = 1;
- break;
-
- case 'n':
- nflag = 1;
- break;
-
- case 'w':
- wflag = 1;
- break;
-
- default:
- usage();
+ 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;
- if (Aflag || aflag) {
- for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++)
- listall(topname[lvl1].ctl_name, &secondlevel[lvl1]);
- exit(0);
- }
+ if (Aflag || aflag)
+ exit (sysctl_all(0, 0));
if (argc == 0)
usage();
while (argc-- > 0)
- parse(*argv, 1);
+ parse(*argv++);
exit(0);
}
/*
- * List all variables known to the system.
- */
-listall(prefix, lp)
- char *prefix;
- struct list *lp;
-{
- int lvl2;
- char *cp, name[BUFSIZ];
-
- 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);
- parse(name, Aflag);
- }
-}
-
-/*
* Parse a name into a MIB entry.
* Lookup and print out the MIB entry if it exists.
* Set a new value if requested.
*/
-parse(string, flags)
- char *string;
- int flags;
+static void
+parse(char *string)
{
- int indx, type, state, size, len;
- int special = 0;
+ int len, i, j;
void *newval = 0;
int intval, newsize = 0;
quad_t quadval;
- struct list *lp;
int mib[CTL_MAXNAME];
- char *cp, *bufp, buf[BUFSIZ], strval[BUFSIZ];
+ char *cp, *bufp, buf[BUFSIZ];
+ u_int kind;
bufp = buf;
snprintf(buf, BUFSIZ, "%s", string);
@@ -214,350 +138,323 @@ parse(string, flags)
newval = cp;
newsize = strlen(cp);
}
- if ((indx = findname(string, "top", &bufp, &toplist)) == -1)
- return;
- mib[0] = indx;
- lp = &secondlevel[indx];
- if (lp->list == 0) {
- fprintf(stderr, "%s: class is not implemented\n",
- topname[indx]);
- 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;
- break;
- case KERN_BOOTTIME:
- special |= BOOTTIME;
- break;
- case KERN_DUMPDEV:
- special |= DUMPDEV;
- break;
- }
- break;
+ len = name2oid(bufp, mib);
- case CTL_HW:
- break;
+ if (len < 0)
+ errx(1, "Unknown oid '%s'", bufp);
- case CTL_VM:
- if (mib[1] == VM_LOADAVG) {
- double loads[3];
+ if (oidfmt(mib, len, 0, &kind))
+ err(1, "Couldn't find format of oid '%s'", bufp);
- getloadavg(loads, 3);
- if (!nflag)
- fprintf(stdout, "%s: ", string);
- fprintf(stdout, "%.2f %.2f %.2f\n",
- loads[0], loads[1], loads[2]);
- return;
+ if (!wflag) {
+ if ((kind & CTLTYPE) == CTLTYPE_NODE) {
+ sysctl_all(mib, len);
+ } else {
+ i = show_var(mib, len);
+ if (!i && !bflag)
+ putchar('\n');
}
- if (flags == 0)
- return;
- fprintf(stderr,
- "Use vmstat or systat to view %s information\n", string);
- return;
-
- case CTL_NET:
- if (mib[1] == PF_INET) {
- len = sysctl_inet(string, &bufp, mib, flags, &type,
- &special);
- if (len >= 0)
+ } else {
+ 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);
+
+ switch (kind & CTLTYPE) {
+ case CTLTYPE_INT:
+ intval = atoi(newval);
+ newval = &intval;
+ newsize = sizeof intval;
+ break;
break;
- return;
+ case CTLTYPE_STRING:
+ break;
+ case CTLTYPE_QUAD:
+ break;
+ sscanf(newval, "%qd", &quadval);
+ newval = &quadval;
+ newsize = sizeof quadval;
+ break;
+ default:
+ errx(1, "oid '%s' is type %d,"
+ " cannot set that", bufp);
}
- if (flags == 0)
- return;
- fprintf(stderr, "Use netstat to view %s information\n", string);
- return;
-
- case CTL_MACHDEP:
-#ifdef CPU_CONSDEV
- if (mib[1] == CPU_CONSDEV)
- special |= CONSDEV;
-#endif
- break;
-
- case CTL_FS:
- 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:
- intval = atoi(newval);
- newval = &intval;
- newsize = sizeof intval;
- break;
-
- case CTLTYPE_QUAD:
- sscanf(newval, "%qd", &quadval);
- newval = &quadval;
- newsize = sizeof quadval;
- 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:
- perror(string);
- return;
+ i = show_var(mib, len);
+ if (sysctl(mib, len, 0, 0, newval, newsize) == -1) {
+ if (!i && !bflag)
+ putchar('\n');
+ switch (errno) {
+ case EOPNOTSUPP:
+ errx(1, "%s: value is not available\n",
+ string);
+ case ENOTDIR:
+ errx(1, "%s: specification is incomplete\n",
+ string);
+ case ENOMEM:
+ errx(1, "%s: type is unknown to this program\n",
+ string);
+ default:
+ perror(string);
+ return;
+ }
}
+ if (!bflag)
+ printf(" -> ");
+ i = nflag;
+ nflag = 1;
+ j = show_var(mib, len);
+ if (!j && !bflag)
+ putchar('\n');
+ nflag = i;
}
- 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", string,
- ctime(&btp->tv_sec));
- else
- fprintf(stdout, "%d\n", btp->tv_sec);
- return;
- }
- if (special & (CONSDEV | DUMPDEV)) {
- dev_t dev = *(dev_t *)buf;
+}
- if ((special & DUMPDEV) && dev == NODEV && !nflag) {
- printf("%s = disabled\n", string);
- return;
- }
- if (!nflag)
- fprintf(stdout, "%s = %s\n", string,
- devname(dev,
- (special & CONSDEV) ? S_IFCHR : S_IFBLK));
- else
- fprintf(stdout, "0x%x\n", dev);
- return;
- }
- switch (type) {
- case CTLTYPE_INT:
- if (newsize == 0) {
- if (!nflag)
- fprintf(stdout, "%s = ", string);
- fprintf(stdout, "%d\n", *(int *)buf);
- } else {
- if (!nflag)
- fprintf(stdout, "%s: %d -> ", string,
- *(int *)buf);
- fprintf(stdout, "%d\n", *(int *)newval);
- }
- return;
+/* These functions will dump out various interesting structures. */
- 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", newval);
- }
- return;
+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, profhz = %d, stathz = %d }",
+ ci->hz, ci->tick, ci->profhz, ci->stathz);
+ return (0);
+}
- 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;
+static int
+S_loadavg(int l2, void *p)
+{
+ struct loadavg *tv = (struct loadavg*)p;
- case CTLTYPE_STRUCT:
- fprintf(stderr, "%s: unknown structure returned\n",
- string);
- return;
+ if (l2 != sizeof *tv)
+ err(-1, "S_loadavg %d != %d", l2, sizeof *tv);
- default:
- case CTLTYPE_NODE:
- fprintf(stderr, "%s: unknown type returned\n",
- string);
- return;
- }
+ printf("{ %.2f %.2f %.2f }",
+ (double)tv->ldavg[0]/(double)tv->fscale,
+ (double)tv->ldavg[1]/(double)tv->fscale,
+ (double)tv->ldavg[2]/(double)tv->fscale);
+ return (0);
}
+static int
+S_timeval(int l2, void *p)
+{
+ struct timeval *tv = (struct timeval*)p;
+ char *p1, *p2;
+
+ if (l2 != sizeof *tv)
+ err(-1, "S_timeval %d != %d", l2, sizeof *tv);
+ printf("{ sec = %ld, usec = %ld } ",
+ tv->tv_sec, tv->tv_usec);
+ p1 = strdup(ctime(&tv->tv_sec));
+ for (p2=p1; *p2 ; p2++)
+ if (*p2 == '\n')
+ *p2 = '\0';
+ fputs(p1, stdout);
+ return (0);
+}
-struct ctlname inetname[] = CTL_IPPROTO_NAMES;
-struct ctlname ipname[] = IPCTL_NAMES;
-struct ctlname icmpname[] = ICMPCTL_NAMES;
-struct ctlname udpname[] = UDPCTL_NAMES;
-struct ctlname tcpname[] = TCPCTL_NAMES;
-struct ctlname igmpname[] = IGMPCTL_NAMES;
-struct list inetlist = { inetname, IPPROTO_MAXID };
-struct list inetvars[] = {
- { ipname, IPCTL_MAXID }, /* ip */
- { icmpname, ICMPCTL_MAXID }, /* icmp */
- { igmpname, IGMPCTL_MAXID }, /* igmp */
- { 0, 0 }, /* ggp */
- { 0, 0 }, /* ipencap */
- { 0, 0 },
- { tcpname, TCPCTL_MAXID }, /* tcp */
- { 0, 0 },
- { 0, 0 }, /* egp */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 }, /* pup */
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { udpname, UDPCTL_MAXID }, /* udp */
-};
+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);
+ printf("{ major = %d, minor = %d }",
+ major(*d), minor(*d));
+ return (0);
+}
/*
- * handle internet requests
+ * These functions uses a presently undocumented interface to the kernel
+ * to walk the tree and get the type so it can print the value.
+ * This interface is under work and consideration, and should probably
+ * be killed with a big axe by the first person who can find the time.
+ * (be aware though, that the proper interface isn't as obvious as it
+ * may seem, there are various conflicting requirements.
*/
-int
-sysctl_inet(string, bufpp, mib, flags, typep, specialp)
- char *string;
- char **bufpp;
- int mib[];
- int flags;
- int *typep;
- int *specialp;
+
+static int
+name2oid(char *name, int *oidp)
{
- struct list *lp;
- int indx;
+ int oid[2];
+ int i, j;
+
+ oid[0] = 0;
+ oid[1] = 3;
+
+ j = CTL_MAXNAME * sizeof (int);
+ i = sysctl(oid, 2, oidp, &j, name, strlen(name));
+ if (i < 0)
+ return i;
+ j /= sizeof (int);
+ return (j);
+}
- if (*bufpp == NULL) {
- listall(string, &inetlist);
- return (-1);
- }
- if ((indx = findname(string, "third", bufpp, &inetlist)) == -1)
- return (-1);
- mib[2] = indx;
- if (indx <= IPPROTO_UDP && inetvars[indx].list != NULL)
- lp = &inetvars[indx];
- else if (!flags)
- return (-1);
- else {
- fprintf(stderr, "%s: no variables defined for this protocol\n",
- string);
- return (-1);
- }
- if (*bufpp == NULL) {
- listall(string, lp);
- return (-1);
- }
- if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
- return (-1);
- mib[3] = indx;
- *typep = lp->list[indx].ctl_type;
- return (4);
+static int
+oidfmt(int *oid, int len, char *fmt, u_int *kind)
+{
+ int qoid[CTL_MAXNAME+2];
+ u_char buf[BUFSIZ];
+ int i, j;
+
+ qoid[0] = 0;
+ qoid[1] = 4;
+ memcpy(qoid + 2, oid, len * sizeof(int));
+
+ 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 (kind)
+ *kind = *(u_int *)buf;
+
+ if (fmt)
+ strcpy(fmt, (char *)(buf + sizeof(u_int)));
+ return 0;
}
/*
- * Scan a list of names searching for a particular name.
+ * This formats and outputs the value of one variable
+ *
+ * Returns zero if anything was actually output.
+ * Returns one if didn't know what to do with this.
+ * Return minus one if we had errors.
*/
-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);
+static int
+show_var(int *oid, int nlen)
+{
+ u_char buf[BUFSIZ], *val, *p;
+ char name[BUFSIZ], *fmt;
+ int qoid[CTL_MAXNAME+2];
+ int i, j, len;
+ u_int kind;
+ int (*func)(int, void *) = 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 :-) */
+
+ val = alloca(j);
+ len = j;
+ i = sysctl(oid, nlen, val, &len, 0, 0);
+ if (i || !len)
+ return (1);
+
+ if (bflag) {
+ fwrite(val, 1, len, stdout);
+ return (0);
}
- for (i = 0; i < namelist->size; i++)
- if (namelist->list[i].ctl_name != NULL &&
- strcmp(name, namelist->list[i].ctl_name) == 0)
+
+ qoid[0] = 0;
+ qoid[1] = 4;
+ memcpy(qoid + 2, oid, nlen * sizeof(int));
+
+ 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;
+
+ fmt = (char *)(buf + sizeof(u_int));
+
+ qoid[1] = 1;
+ 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);
+
+ p = val;
+ switch (*fmt) {
+ case 'A':
+ if (!nflag)
+ printf("%s: ", name);
+ printf("%s", p);
+ return (0);
+
+ case 'I':
+ if (!nflag)
+ printf("%s: ", name);
+ printf("%d", *(int *)p);
+ return (0);
+
+ case 'T':
+ case 'S':
+ 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 (func) {
+ if (!nflag)
+ printf("%s: ", name);
+ return ((*func)(len, p));
+ }
+ /* FALL THROUGH */
+ default:
+ if (!Aflag)
+ return (1);
+ if (!nflag)
+ printf("%s: ", name);
+ printf("Format:%s Length:%d Dump:0x", fmt, len);
+ while (len--) {
+ printf("%02x", *p++);
+ if (Xflag || p < val+16)
+ continue;
+ printf("...");
break;
- if (i == namelist->size) {
- fprintf(stderr, "%s level name %s in %s is invalid\n",
- level, name, string);
- return (-1);
+ }
+ return (0);
}
- return (i);
+ return (1);
}
-usage()
+static int
+sysctl_all (int *oid, int len)
{
-
- (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n",
- "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...",
- "sysctl [-n] -a", "sysctl [-n] -A");
- exit(1);
+ int name1[22], name2[22];
+ int i, j, l1, l2;
+
+ name1[0] = 0;
+ name1[1] = 2;
+ l1 = 2;
+ if (len) {
+ memcpy(name1+2, oid, len*sizeof (int));
+ l1 += len;
+ } else {
+ name1[2] = 1;
+ l1++;
+ }
+ while (1) {
+ l2 = sizeof name2;
+ j = sysctl(name1, l1, name2, &l2, 0, 0);
+ if (j < 0)
+ if (errno == ENOENT)
+ return 0;
+ else
+ err(-1, "sysctl(getnext) %d %d", j, l2);
+
+ l2 /= sizeof (int);
+
+ if (l2 < len)
+ return 0;
+
+ for (i = 0; i < len; i++)
+ if (name2[i] != oid[i])
+ return 0;
+
+ i = show_var(name2, l2);
+ if (!i && !bflag)
+ putchar('\n');
+
+ memcpy(name1+2, name2, l2*sizeof (int));
+ l1 = 2 + l2;
+ }
}
OpenPOWER on IntegriCloud