diff --git a/usr.sbin/sysctl/Makefile b/usr.sbin/sysctl/Makefile new file mode 100644 index 000000000000..40d12d2fede4 --- /dev/null +++ b/usr.sbin/sysctl/Makefile @@ -0,0 +1,6 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= sysctl +MAN8= sysctl.0 + +.include diff --git a/usr.sbin/sysctl/pathconf.c b/usr.sbin/sysctl/pathconf.c new file mode 100644 index 000000000000..4b60ccfb1c09 --- /dev/null +++ b/usr.sbin/sysctl/pathconf.c @@ -0,0 +1,229 @@ +/* + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +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[] = "@(#)pathconf.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include +#include +#include + +#include +#include +#include +#include + +#define PC_NAMES { \ + { 0, 0 }, \ + { "link_max", CTLTYPE_INT }, \ + { "max_canon", CTLTYPE_INT }, \ + { "max_input", CTLTYPE_INT }, \ + { "name_max", CTLTYPE_INT }, \ + { "path_max", CTLTYPE_INT }, \ + { "pipe_buf", CTLTYPE_INT }, \ + { "chown_restricted", CTLTYPE_INT }, \ + { "no_trunc", CTLTYPE_INT }, \ + { "vdisable", CTLTYPE_INT }, \ +} +#define PC_MAXID 10 + +struct ctlname pcnames[] = PC_NAMES; +char names[BUFSIZ]; + +struct list { + struct ctlname *list; + int size; +}; +struct list pclist = { pcnames, PC_MAXID }; + +int Aflag, aflag, nflag, wflag, stdinflag; + +int +main(argc, argv) + int argc; + char *argv[]; +{ + extern char *optarg; + extern int optind; + char *path; + int ch; + + while ((ch = getopt(argc, argv, "Aan")) != EOF) { + switch (ch) { + + case 'A': + Aflag = 1; + break; + + case 'a': + aflag = 1; + break; + + case 'n': + nflag = 1; + break; + + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if (argc == 0) + usage(); + path = *argv++; + if (strcmp(path, "-") == 0) + stdinflag = 1; + argc--; + if (Aflag || aflag) { + listall(path, &pclist); + exit(0); + } + if (argc == 0) + usage(); + while (argc-- > 0) + parse(path, *argv, 1); + exit(0); +} + +/* + * List all variables known to the system. + */ +listall(path, lp) + char *path; + struct list *lp; +{ + int lvl2; + + if (lp->list == 0) + return; + for (lvl2 = 0; lvl2 < lp->size; lvl2++) { + if (lp->list[lvl2].ctl_name == 0) + continue; + parse(path, lp->list[lvl2].ctl_name, Aflag); + } +} + +/* + * Parse a name into an index. + * Lookup and print out the attribute if it exists. + */ +parse(pathname, string, flags) + char *pathname; + char *string; + int flags; +{ + int indx, value; + char *bufp, buf[BUFSIZ]; + + bufp = buf; + snprintf(buf, BUFSIZ, "%s", string); + if ((indx = findname(string, "top", &bufp, &pclist)) == -1) + return; + if (bufp) { + fprintf(stderr, "name %s in %s is unknown\n", *bufp, string); + return; + } + if (stdinflag) + value = fpathconf(0, indx); + else + value = pathconf(pathname, indx); + if (value == -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; + } + } + if (!nflag) + fprintf(stdout, "%s = ", string); + fprintf(stdout, "%d\n", value); +} + +/* + * Scan a list of names searching for a particular name. + */ +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); +} + +usage() +{ + + (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n", + "pathname [-n] variable ...", + "pathname [-n] -a", "pathname [-n] -A"); + exit(1); +} diff --git a/usr.sbin/sysctl/sysctl.8 b/usr.sbin/sysctl/sysctl.8 new file mode 100644 index 000000000000..9def5093a221 --- /dev/null +++ b/usr.sbin/sysctl/sysctl.8 @@ -0,0 +1,208 @@ +.\" Copyright (c) 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 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. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)sysctl.8 8.1 (Berkeley) 6/6/93 +.\" +.Dd "June 6, 1993" +.Dt SYSCTL 8 +.Os +.Sh NAME +.Nm sysctl +.Nd get or set kernel state +.Sh SYNOPSIS +.Nm sysctl +.Op Fl n +.Ar name ... +.Nm sysctl +.Op Fl n +.Fl w +.Ar name=value ... +.Nm sysctl +.Op Fl n +.Fl aA +.Sh DESCRIPTION +The +.Nm sysctl +utility retrieves kernel state and allows processes with +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. +The +.Fl a +flag can be used to list all the currently available string or integer values. +The +.Fl A +flag will list all the known MIB names including tables. +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. +.Pp +The +.Fl n +flag specifies that the printing of the field name should be +suppressed and that only its value should be output. +This flag is useful for setting shell variables. +For example, to save the pagesize in variable psize, use: +.Bd -literal -offset indent -compact +set psize=`sysctl -n hw.pagesize` +.Ed +.Pp +If just a MIB style name is given, +the corresponding value is retrieved. +If a value is to be set, the +.Fl w +flag must be specified and the MIB name followed +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 +purpose programs such as +.Nm ps , +.Nm systat , +and +.Nm netstat . +The string and integer information is summaried below. +For a detailed description of these variable see +.Xr sysctl 3 . +The changeable column indicates whether a process with appropriate +privilege can change the value. +.Bl -column net.inet.ip.forwardingxxxxxx integerxxx +.It Sy Name Type Changeable +.It kern.ostype string no +.It kern.osrelease string no +.It kern.osrevision integer no +.It kern.version string no +.It kern.maxvnodes integer yes +.It kern.maxproc integer yes +.It kern.maxfiles integer yes +.It kern.argmax integer no +.It kern.securelevel integer raise only +.It kern.hostname string yes +.It kern.hostid integer yes +.It kern.clockrate struct no +.It kern.posix1version integer no +.It kern.ngroups integer no +.It kern.job_control integer no +.It kern.saved_ids integer no +.It kern.link_max integer no +.It kern.max_canon integer no +.It kern.max_input integer no +.It kern.name_max integer no +.It kern.path_max integer no +.It kern.pipe_buf integer no +.It kern.chown_restricted integer no +.It kern.no_trunc integer no +.It kern.vdisable integer no +.It kern.boottime struct no +.It vm.loadavg struct no +.It machdep.console_device dev_t no +.It net.inet.ip.forwarding integer yes +.It net.inet.ip.redirect integer yes +.It net.inet.ip.ttl integer yes +.It net.inet.icmp.maskrepl integer yes +.It net.inet.udp.checksum integer yes +.It hw.machine string no +.It hw.model string no +.It hw.ncpu integer no +.It hw.byteorder integer no +.It hw.physmem integer no +.It hw.usermem integer no +.It hw.pagesize integer no +.It user.cs_path string no +.It user.bc_base_max integer no +.It user.bc_dim_max integer no +.It user.bc_scale_max integer no +.It user.bc_string_max integer no +.It user.coll_weights_max integer no +.It user.expr_nest_max integer no +.It user.line_max integer no +.It user.re_dup_max integer no +.It user.posix2_version integer no +.It user.posix2_c_bind integer no +.It user.posix2_c_dev integer no +.It user.posix2_char_term integer no +.It user.posix2_fort_dev integer no +.It user.posix2_fort_run integer no +.It user.posix2_localedef integer no +.It user.posix2_sw_dev integer no +.It user.posix2_upe integer no +.El +.Sh EXAMPLES +.Pp +For example, to retrieve the maximum number of processes allowed +in the system, one would use the follow request: +.Bd -literal -offset indent -compact +sysctl kern.maxproc +.Ed +.Pp +To set the maximum number of processes allowed +in the system to 1000, one would use the follow request: +.Bd -literal -offset indent -compact +sysctl -w kern.maxproc=1000 +.Ed +.Pp +Information about the system clock rate may be obtained with: +.Bd -literal -offset indent -compact +sysctl kern.clockrate +.Ed +.Pp +Information about the load average history may be obtained with +.Bd -literal -offset indent -compact +sysctl vm.loadavg +.Ed +.Sh FILES +.Bl -tag -width -compact +.It Pa +definitions for top level identifiers, second level kernel and hardware +identifiers, and user level identifiers +.It Pa +definitions for second level network identifiers +.It Pa +definitions for third level profiling identifiers +.It Pa +definitions for second level virtual memory identifiers +.It Pa +definitions for third level Internet identifiers and +fourth level IP identifiers +.It Pa +definitions for fourth level ICMP identifiers +.It Pa +definitions for fourth level UDP identifiers +.El +.Sh SEE ALSO +.Xr sysctl 3 +.Sh HISTORY +.Nm sysctl +first appeared in 4.4BSD. diff --git a/usr.sbin/sysctl/sysctl.c b/usr.sbin/sysctl/sysctl.c new file mode 100644 index 000000000000..a3426868b4f2 --- /dev/null +++ b/usr.sbin/sysctl/sysctl.c @@ -0,0 +1,572 @@ +/* + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +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.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +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; +struct ctlname debugname[CTL_DEBUG_MAXID]; +#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, CTL_DEBUG_MAXID }, /* 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; + +/* + * Variables requiring special processing. + */ +#define CLOCK 0x00000001 +#define BOOTTIME 0x00000002 +#define CONSDEV 0x00000004 + +int +main(argc, argv) + int argc; + char *argv[]; +{ + extern char *optarg; + extern int optind; + int ch, lvl1; + + while ((ch = getopt(argc, argv, "Aanw")) != 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(); + } + } + argc -= optind; + argv += optind; + + if (Aflag || aflag) { + debuginit(); + for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++) + listall(topname[lvl1].ctl_name, &secondlevel[lvl1]); + exit(0); + } + if (argc == 0) + usage(); + while (argc-- > 0) + parse(*argv, 1); + 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; +{ + int indx, type, state, size, len; + int special = 0; + void *newval = 0; + int intval, newsize = 0; + quad_t quadval; + struct list *lp; + 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_DEBUG) + debuginit(); + 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; + } + break; + + case CTL_HW: + break; + + case CTL_VM: + if (mib[1] == VM_LOADAVG) { + 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_NET: + if (mib[1] == PF_INET) { + len = sysctl_inet(string, &bufp, mib, flags, &type); + if (len >= 0) + break; + return; + } + if (flags == 0) + return; + fprintf(stderr, "Use netstat 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_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; + } + } + 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(&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, "%d\n", *(int *)buf); + } else { + if (!nflag) + fprintf(stdout, "%s: %d -> ", string, + *(int *)buf); + fprintf(stdout, "%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", 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: + fprintf(stderr, "%s: unknown structure returned\n", + string); + return; + + default: + case CTLTYPE_NODE: + fprintf(stderr, "%s: unknown type returned\n", + string); + return; + } +} + +/* + * Initialize the set of debugging names + */ +debuginit() +{ + int mib[3], size, loc, i; + + if (secondlevel[CTL_DEBUG].list != 0) + return; + secondlevel[CTL_DEBUG].list = debugname; + mib[0] = CTL_DEBUG; + mib[2] = CTL_DEBUG_NAME; + for (loc = 0, 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; + } +} + +struct ctlname inetname[] = CTL_IPPROTO_NAMES; +struct ctlname ipname[] = IPCTL_NAMES; +struct ctlname icmpname[] = ICMPCTL_NAMES; +struct ctlname udpname[] = UDPCTL_NAMES; +struct list inetlist = { inetname, IPPROTO_MAXID }; +struct list inetvars[] = { + { ipname, IPCTL_MAXID }, /* ip */ + { icmpname, ICMPCTL_MAXID }, /* icmp */ + { 0, 0 }, /* igmp */ + { 0, 0 }, /* ggmp */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, /* 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 */ +}; + +/* + * handle internet requests + */ +sysctl_inet(string, bufpp, mib, flags, typep) + char *string; + char **bufpp; + int mib[]; + int flags; + int *typep; +{ + struct list *lp; + int indx; + + 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); +} + +/* + * Scan a list of names searching for a particular name. + */ +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); +} + +usage() +{ + + (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); +}