diff options
Diffstat (limited to 'sbin/sysctl/sysctl.c')
-rw-r--r-- | sbin/sysctl/sysctl.c | 229 |
1 files changed, 168 insertions, 61 deletions
diff --git a/sbin/sysctl/sysctl.c b/sbin/sysctl/sysctl.c index a9c2b7a..8fad089 100644 --- a/sbin/sysctl/sysctl.c +++ b/sbin/sysctl/sysctl.c @@ -56,13 +56,17 @@ static const char rcsid[] = #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sysexits.h> #include <unistd.h> +static const char *conffile; + static int aflag, bflag, dflag, eflag, hflag, iflag; -static int Nflag, nflag, oflag, qflag, Tflag, Wflag, xflag, warncount; +static int Nflag, nflag, oflag, qflag, Tflag, Wflag, xflag; static int oidfmt(int *, int, char *, u_int *); -static void parse(const char *); +static int parsefile(const char *); +static int parse(const char *, int); static int show_var(int *, int); static int sysctl_all(int *oid, int len); static int name2oid(char *, int *); @@ -74,7 +78,7 @@ usage(void) { (void)fprintf(stderr, "%s\n%s\n", - "usage: sysctl [-bdehiNnoqTWx] name[=value] ...", + "usage: sysctl [-bdehiNnoqTWx] [-f filename] name[=value] ...", " sysctl [-bdehNnoqTWx] -a"); exit(1); } @@ -83,12 +87,13 @@ int main(int argc, char **argv) { int ch; + int warncount = 0; setlocale(LC_NUMERIC, ""); setbuf(stdout,0); setbuf(stderr,0); - while ((ch = getopt(argc, argv, "AabdehiNnoqTwWxX")) != -1) { + while ((ch = getopt(argc, argv, "Aabdef:hiNnoqTwWxX")) != -1) { switch (ch) { case 'A': /* compatibility */ @@ -106,6 +111,9 @@ main(int argc, char **argv) case 'e': eflag = 1; break; + case 'f': + conffile = optarg; + break; case 'h': hflag = 1; break; @@ -152,13 +160,17 @@ main(int argc, char **argv) usage(); if (aflag && argc == 0) exit(sysctl_all(0, 0)); - if (argc == 0) + if (argc == 0 && conffile == NULL) usage(); warncount = 0; + if (conffile != NULL) + warncount += parsefile(conffile); + while (argc-- > 0) - parse(*argv++); - exit(warncount); + warncount += parse(*argv++, 0); + + return (warncount); } /* @@ -166,8 +178,8 @@ main(int argc, char **argv) * Lookup and print out the MIB entry if it exists. * Set a new value if requested. */ -static void -parse(const char *string) +static int +parse(const char *string, int lineno) { int len, i, j; void *newval = 0; @@ -179,13 +191,20 @@ parse(const char *string) int64_t i64val; uint64_t u64val; int mib[CTL_MAXNAME]; - char *cp, *bufp, buf[BUFSIZ], *endptr, fmt[BUFSIZ]; + char *cp, *bufp, buf[BUFSIZ], *endptr, fmt[BUFSIZ], line[BUFSIZ]; u_int kind; + if (lineno) + snprintf(line, sizeof(line), " at line %d", lineno); + else + line[0] = '\0'; + cp = buf; - if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ) - errx(1, "oid too long: '%s'", string); - bufp = strsep(&cp, "="); + if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ) { + warn("oid too long: '%s'%s", string, line); + return (1); + } + bufp = strsep(&cp, "=:"); if (cp != NULL) { /* Tflag just lists tunables, do not allow assignment */ if (Tflag || Wflag) { @@ -194,6 +213,14 @@ parse(const char *string) } while (isspace(*cp)) cp++; + /* Strip a pair of " or ' if any. */ + switch (*cp) { + case '\"': + case '\'': + if (cp[strlen(cp) - 1] == *cp) + cp[strlen(cp) - 1] = '\0'; + cp++; + } newval = cp; newsize = strlen(cp); } @@ -201,15 +228,22 @@ parse(const char *string) if (len < 0) { if (iflag) - return; + return (0); if (qflag) - exit(1); - else - errx(1, "unknown oid '%s'", bufp); + return (1); + else { + warn("unknown oid '%s'%s", bufp, line); + return (1); + } } - if (oidfmt(mib, len, fmt, &kind)) - err(1, "couldn't find format of oid '%s'", bufp); + if (oidfmt(mib, len, fmt, &kind)) { + warn("couldn't find format of oid '%s'%s", bufp, line); + if (iflag) + return (1); + else + exit(1); + } if (newval == NULL || dflag) { if ((kind & CTLTYPE) == CTLTYPE_NODE) { @@ -225,16 +259,18 @@ parse(const char *string) putchar('\n'); } } else { - if ((kind & CTLTYPE) == CTLTYPE_NODE) - errx(1, "oid '%s' isn't a leaf node", bufp); + if ((kind & CTLTYPE) == CTLTYPE_NODE) { + warn("oid '%s' isn't a leaf node%s", bufp, line); + return (1); + } 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); - } + warnx("oid '%s' is a read only tunable%p", bufp, line); + warnx("Tunable values are set in /boot/loader.conf"); + } else + warnx("oid '%s' is read only%s", bufp, line); + return (1); } if ((kind & CTLTYPE) == CTLTYPE_INT || @@ -243,47 +279,59 @@ parse(const char *string) (kind & CTLTYPE) == CTLTYPE_ULONG || (kind & CTLTYPE) == CTLTYPE_S64 || (kind & CTLTYPE) == CTLTYPE_U64) { - if (strlen(newval) == 0) - errx(1, "empty numeric value"); + if (strlen(newval) == 0) { + warnx("empty numeric value"); + return (1); + } } switch (kind & CTLTYPE) { case CTLTYPE_INT: if (strcmp(fmt, "IK") == 0) { - if (!set_IK(newval, &intval)) - errx(1, "invalid value '%s'", - (char *)newval); + if (!set_IK(newval, &intval)) { + warnx("invalid value '%s'%s", + (char *)newval, line); + return (1); + } } else { intval = (int)strtol(newval, &endptr, 0); - if (endptr == newval || *endptr != '\0') - errx(1, "invalid integer '%s'", - (char *)newval); + if (endptr == newval || *endptr != '\0') { + warnx("invalid integer '%s'%s", + (char *)newval, line); + return (1); + } } 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); + if (endptr == newval || *endptr != '\0') { + warnx("invalid unsigned integer '%s'%s", + (char *)newval, line); + return (1); + } 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); + if (endptr == newval || *endptr != '\0') { + warnx("invalid long integer '%s'%s", + (char *)newval, line); + return (1); + } 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); + if (endptr == newval || *endptr != '\0') { + warnx("invalid unsigned long integer" + " '%s'%s", (char *)newval, line); + return (1); + } newval = &ulongval; newsize = sizeof(ulongval); break; @@ -291,26 +339,31 @@ parse(const char *string) break; case CTLTYPE_S64: i64val = strtoimax(newval, &endptr, 0); - if (endptr == newval || *endptr != '\0') - errx(1, "invalid int64_t '%s'", - (char *)newval); + if (endptr == newval || *endptr != '\0') { + warnx("invalid int64_t '%s'%s", + (char *)newval, line); + return (1); + } newval = &i64val; newsize = sizeof(i64val); break; case CTLTYPE_U64: u64val = strtoumax(newval, &endptr, 0); - if (endptr == newval || *endptr != '\0') - errx(1, "invalid uint64_t '%s'", - (char *)newval); + if (endptr == newval || *endptr != '\0') { + warnx("invalid uint64_t '%s'%s", + (char *)newval, line); + return (1); + } newval = &u64val; newsize = sizeof(u64val); break; case CTLTYPE_OPAQUE: /* FALLTHROUGH */ default: - errx(1, "oid '%s' is type %d," - " cannot set that", bufp, - kind & CTLTYPE); + warnx("oid '%s' is type %d," + " cannot set that%s", bufp, + kind & CTLTYPE, line); + return (1); } i = show_var(mib, len); @@ -319,18 +372,20 @@ parse(const char *string) putchar('\n'); switch (errno) { case EOPNOTSUPP: - errx(1, "%s: value is not available", - string); + warnx("%s: value is not available%s", + string, line); + return (1); case ENOTDIR: - errx(1, "%s: specification is incomplete", - string); + warnx("%s: specification is incomplete%s", + string, line); + return (1); case ENOMEM: - errx(1, "%s: type is unknown to this program", - string); + warnx("%s: type is unknown to this program%s", + string, line); + return (1); default: - warn("%s", string); - warncount++; - return; + warn("%s%s", string, line); + return (1); } } if (!bflag) @@ -342,6 +397,58 @@ parse(const char *string) putchar('\n'); nflag = i; } + + return (0); +} + +static int +parsefile(const char *filename) +{ + FILE *file; + char line[BUFSIZ], *p, *pq, *pdq; + int warncount = 0, lineno = 0; + + file = fopen(filename, "r"); + if (file == NULL) + err(EX_NOINPUT, "%s", filename); + while (fgets(line, sizeof(line), file) != NULL) { + lineno++; + p = line; + pq = strchr(line, '\''); + pdq = strchr(line, '\"'); + /* Replace the first # with \0. */ + while((p = strchr(p, '#')) != NULL) { + if (pq != NULL && p > pq) { + if ((p = strchr(pq+1, '\'')) != NULL) + *(++p) = '\0'; + break; + } else if (pdq != NULL && p > pdq) { + if ((p = strchr(pdq+1, '\"')) != NULL) + *(++p) = '\0'; + break; + } else if (p == line || *(p-1) != '\\') { + *p = '\0'; + break; + } + p++; + } + /* Trim spaces */ + p = line + strlen(line) - 1; + while (p >= line && isspace((int)*p)) { + *p = '\0'; + p--; + } + p = line; + while (isspace((int)*p)) + p++; + if (*p == '\0') + continue; + else + warncount += parse(p, lineno); + } + fclose(file); + + return (warncount); } /* These functions will dump out various interesting structures. */ |