Changeset View
Changeset View
Standalone View
Standalone View
sbin/sysctl/sysctl.c
Show First 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | ||||||||||
#include <string.h> | #include <string.h> | |||||||||
#include <sysexits.h> | #include <sysexits.h> | |||||||||
#include <unistd.h> | #include <unistd.h> | |||||||||
static const char *conffile; | static const char *conffile; | |||||||||
static int aflag, bflag, Bflag, dflag, eflag, hflag, iflag; | static int aflag, bflag, Bflag, dflag, eflag, hflag, iflag; | |||||||||
static int Nflag, nflag, oflag, qflag, tflag, Tflag, Wflag, xflag; | static int Nflag, nflag, oflag, qflag, tflag, Tflag, Wflag, xflag; | |||||||||
static bool Fflag, lflag; | ||||||||||
static int oidfmt(int *, int, char *, u_int *); | static int oidfmt(int *, int, char *, u_int *); | |||||||||
static int parsefile(const char *); | static int parsefile(const char *); | |||||||||
static int parse(const char *, int); | static int parse(const char *, int); | |||||||||
static int show_var(int *, int, bool); | static int show_var(int *, int, bool); | |||||||||
static int sysctl_all(int *, int); | static int sysctl_all(int *, int); | |||||||||
static int name2oid(const char *, int *); | static int name2oid(const char *, int *); | |||||||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | static const char *ctl_typename[CTLTYPE+1] = { | |||||||||
[CTLTYPE_OPAQUE] = "opaque", | [CTLTYPE_OPAQUE] = "opaque", | |||||||||
}; | }; | |||||||||
static void | static void | |||||||||
usage(void) | usage(void) | |||||||||
{ | { | |||||||||
(void)fprintf(stderr, "%s\n%s\n", | (void)fprintf(stderr, "%s\n%s\n", | |||||||||
"usage: sysctl [-bdehiNnoqTtWx] [ -B <bufsize> ] [-f filename] name[=value] ...", | "usage: sysctl [-bdeFhilNnoqTtWx] [ -B <bufsize> ] [-f filename] name[=value] ...", | |||||||||
" sysctl [-bdehNnoqTtWx] [ -B <bufsize> ] -a"); | " sysctl [-bdeFhlNnoqTtWx] [ -B <bufsize> ] -a"); | |||||||||
exit(1); | exit(1); | |||||||||
} | } | |||||||||
int | int | |||||||||
main(int argc, char **argv) | main(int argc, char **argv) | |||||||||
{ | { | |||||||||
int ch; | int ch; | |||||||||
int warncount = 0; | int warncount = 0; | |||||||||
setlocale(LC_NUMERIC, ""); | setlocale(LC_NUMERIC, ""); | |||||||||
setbuf(stdout,0); | setbuf(stdout,0); | |||||||||
setbuf(stderr,0); | setbuf(stderr,0); | |||||||||
while ((ch = getopt(argc, argv, "AabB:def:hiNnoqtTwWxX")) != -1) { | while ((ch = getopt(argc, argv, "AabB:def:FhilNnoqtTwWxX")) != -1) { | |||||||||
switch (ch) { | switch (ch) { | |||||||||
case 'A': | case 'A': | |||||||||
/* compatibility */ | /* compatibility */ | |||||||||
aflag = oflag = 1; | aflag = oflag = 1; | |||||||||
break; | break; | |||||||||
case 'a': | case 'a': | |||||||||
aflag = 1; | aflag = 1; | |||||||||
break; | break; | |||||||||
case 'b': | case 'b': | |||||||||
bflag = 1; | bflag = 1; | |||||||||
break; | break; | |||||||||
case 'B': | case 'B': | |||||||||
Bflag = strtol(optarg, NULL, 0); | Bflag = strtol(optarg, NULL, 0); | |||||||||
break; | break; | |||||||||
case 'd': | case 'd': | |||||||||
dflag = 1; | dflag = 1; | |||||||||
break; | break; | |||||||||
case 'e': | case 'e': | |||||||||
eflag = 1; | eflag = 1; | |||||||||
break; | break; | |||||||||
case 'f': | case 'f': | |||||||||
conffile = optarg; | conffile = optarg; | |||||||||
break; | break; | |||||||||
case 'F': | ||||||||||
Fflag = true; | ||||||||||
break; | ||||||||||
case 'h': | case 'h': | |||||||||
hflag = 1; | hflag = 1; | |||||||||
break; | break; | |||||||||
case 'i': | case 'i': | |||||||||
iflag = 1; | iflag = 1; | |||||||||
break; | break; | |||||||||
case 'l': | ||||||||||
lflag = true; | ||||||||||
break; | ||||||||||
case 'N': | case 'N': | |||||||||
Nflag = 1; | Nflag = 1; | |||||||||
break; | break; | |||||||||
case 'n': | case 'n': | |||||||||
nflag = 1; | nflag = 1; | |||||||||
break; | break; | |||||||||
case 'o': | case 'o': | |||||||||
oflag = 1; | oflag = 1; | |||||||||
Show All 23 Lines | case 'x': | |||||||||
break; | break; | |||||||||
default: | default: | |||||||||
usage(); | usage(); | |||||||||
} | } | |||||||||
} | } | |||||||||
argc -= optind; | argc -= optind; | |||||||||
argv += optind; | argv += optind; | |||||||||
if (Nflag && nflag) | /* Nflag is name only and doesn't make sense to combind with these */ | |||||||||
/* TODO: few other combinations do not make sense but come back later */ | ||||||||||
if (Nflag && (lflag || nflag)) | ||||||||||
usage(); | usage(); | |||||||||
if (aflag && argc == 0) | if (aflag && argc == 0) | |||||||||
exit(sysctl_all(NULL, 0)); | exit(sysctl_all(NULL, 0)); | |||||||||
if (argc == 0 && conffile == NULL) | if (argc == 0 && conffile == NULL) | |||||||||
usage(); | usage(); | |||||||||
warncount = 0; | ||||||||||
if (conffile != NULL) | if (conffile != NULL) | |||||||||
warncount += parsefile(conffile); | warncount += parsefile(conffile); | |||||||||
while (argc-- > 0) | while (argc-- > 0) | |||||||||
warncount += parse(*argv++, 0); | warncount += parse(*argv++, 0); | |||||||||
return (warncount); | return (warncount); | |||||||||
} | } | |||||||||
▲ Show 20 Lines • Show All 719 Lines • ▼ Show 20 Lines | if (kind) | |||||||||
*kind = *(u_int *)buf; | *kind = *(u_int *)buf; | |||||||||
if (fmt) | if (fmt) | |||||||||
strcpy(fmt, (char *)(buf + sizeof(u_int))); | strcpy(fmt, (char *)(buf + sizeof(u_int))); | |||||||||
return (0); | return (0); | |||||||||
} | } | |||||||||
/* | /* | |||||||||
* This displays a combination of name, type, format, and/or description. | ||||||||||
* | ||||||||||
* Returns zero if anything was actually output. | ||||||||||
* Returns one if there is an error. | ||||||||||
*/ | ||||||||||
static int | ||||||||||
show_info(char *name, const char *sep, int ctltype, char *fmt, int *qoid, int nlen) | ||||||||||
{ | ||||||||||
u_char buf[BUFSIZ]; | ||||||||||
const char *prntype; | ||||||||||
int error = 0, i; | ||||||||||
size_t j; | ||||||||||
if (!nflag) | ||||||||||
printf("%s%s", name, sep); | ||||||||||
if (tflag) { | ||||||||||
if (ctl_typename[ctltype] != NULL) | ||||||||||
prntype = ctl_typename[ctltype]; | ||||||||||
else { | ||||||||||
prntype = "unknown"; | ||||||||||
error++; | ||||||||||
} | ||||||||||
if (Fflag || dflag) | ||||||||||
printf("%s%s", prntype, sep); | ||||||||||
else | ||||||||||
fputs(prntype, stdout); | ||||||||||
} | ||||||||||
if (Fflag) { | ||||||||||
if (!isprint(fmt[0])) /* Few codes doesn't have formats */ | ||||||||||
fmt = ""; | ||||||||||
if (dflag) | ||||||||||
delphij: `i` is assigned but not used. I think it's quite likely that this `sysctl` call would always… | ||||||||||
printf("%s%s", fmt, sep); | ||||||||||
else | ||||||||||
fputs(fmt, stdout); | ||||||||||
} | ||||||||||
if (!dflag) | ||||||||||
return (error); | ||||||||||
qoid[1] = CTL_SYSCTL_OIDDESCR; | ||||||||||
bzero(buf, BUFSIZ); | ||||||||||
j = sizeof(buf); | ||||||||||
i = sysctl(qoid, nlen + 2, buf, &j, 0, 0); | ||||||||||
if (i < 0) | ||||||||||
return (1); | ||||||||||
fputs(buf, stdout); | ||||||||||
return (error); | ||||||||||
Not Done Inline Actionserror is always 0, can we get rid of either error or i? markj: `error` is always 0, can we get rid of either `error` or `i`? | ||||||||||
} | ||||||||||
/* | ||||||||||
* This formats and outputs the value of one variable | * This formats and outputs the value of one variable | |||||||||
* | * | |||||||||
* Returns zero if anything was actually output. | * Returns zero if anything was actually output. | |||||||||
* Returns one if didn't know what to do with this. | * Returns one if didn't know what to do with this. | |||||||||
* Return minus one if we had errors. | * Return minus one if we had errors. | |||||||||
*/ | */ | |||||||||
static int | static int | |||||||||
show_var(int *oid, int nlen, bool honor_skip) | show_var(int *oid, int nlen, bool honor_skip) | |||||||||
{ | { | |||||||||
static int skip_len = 0, skip_oid[CTL_MAXNAME]; | static int skip_len = 0, skip_oid[CTL_MAXNAME]; | |||||||||
u_char buf[BUFSIZ], *val, *oval, *p; | u_char *val, *oval, *p; | |||||||||
char name[BUFSIZ], fmt[BUFSIZ]; | char name[BUFSIZ], fmt[BUFSIZ]; | |||||||||
const char *sep, *sep1, *prntype; | const char *sep, *sep1; | |||||||||
int qoid[CTL_MAXNAME+2]; | int qoid[CTL_MAXNAME+2]; | |||||||||
uintmax_t umv; | uintmax_t umv; | |||||||||
intmax_t mv; | intmax_t mv; | |||||||||
int i, hexlen, sign, ctltype; | int i, hexlen, sign, ctltype; | |||||||||
size_t intlen; | size_t intlen; | |||||||||
size_t j, len; | size_t j, len; | |||||||||
u_int kind; | u_int kind; | |||||||||
float base; | float base; | |||||||||
int (*func)(size_t, void *); | int (*func)(size_t, void *); | |||||||||
int prec; | int prec; | |||||||||
/* Silence GCC. */ | /* Silence GCC. */ | |||||||||
umv = mv = intlen = 0; | umv = mv = intlen = 0; | |||||||||
bzero(buf, BUFSIZ); | ||||||||||
bzero(fmt, BUFSIZ); | bzero(fmt, BUFSIZ); | |||||||||
bzero(name, BUFSIZ); | bzero(name, BUFSIZ); | |||||||||
qoid[0] = CTL_SYSCTL; | qoid[0] = CTL_SYSCTL; | |||||||||
qoid[1] = CTL_SYSCTL_NAME; | qoid[1] = CTL_SYSCTL_NAME; | |||||||||
memcpy(qoid + 2, oid, nlen * sizeof(int)); | memcpy(qoid + 2, oid, nlen * sizeof(int)); | |||||||||
j = sizeof(name); | j = sizeof(name); | |||||||||
i = sysctl(qoid, nlen + 2, name, &j, 0, 0); | i = sysctl(qoid, nlen + 2, name, &j, 0, 0); | |||||||||
if (i || !j) | if (i || !j) | |||||||||
Show All 14 Lines | show_var(int *oid, int nlen, bool honor_skip) | |||||||||
} | } | |||||||||
if (eflag) | if (eflag) | |||||||||
sep = "="; | sep = "="; | |||||||||
else | else | |||||||||
sep = ": "; | sep = ": "; | |||||||||
ctltype = (kind & CTLTYPE); | ctltype = (kind & CTLTYPE); | |||||||||
if (tflag || dflag) { | if (tflag || Fflag || dflag) | |||||||||
if (!nflag) | return show_info(name, sep, ctltype, fmt, qoid, nlen); | |||||||||
Not Done Inline Actions
markj: | ||||||||||
printf("%s%s", name, sep); | ||||||||||
if (ctl_typename[ctltype] != NULL) | ||||||||||
prntype = ctl_typename[ctltype]; | ||||||||||
else | ||||||||||
prntype = "unknown"; | ||||||||||
if (tflag && dflag) | ||||||||||
printf("%s%s", prntype, sep); | ||||||||||
else if (tflag) { | ||||||||||
printf("%s", prntype); | ||||||||||
return (0); | ||||||||||
} | ||||||||||
qoid[1] = CTL_SYSCTL_OIDDESCR; | ||||||||||
j = sizeof(buf); | ||||||||||
i = sysctl(qoid, nlen + 2, buf, &j, 0, 0); | ||||||||||
printf("%s", buf); | ||||||||||
return (0); | ||||||||||
} | ||||||||||
/* keep track of encountered skip nodes, ignoring descendants */ | /* keep track of encountered skip nodes, ignoring descendants */ | |||||||||
if ((skip_len == 0 || skip_len >= nlen * (int)sizeof(int)) && | if ((skip_len == 0 || skip_len >= nlen * (int)sizeof(int)) && | |||||||||
(kind & CTLFLAG_SKIP) != 0) { | (kind & CTLFLAG_SKIP) != 0) { | |||||||||
/* Save this oid so we can skip descendants. */ | /* Save this oid so we can skip descendants. */ | |||||||||
skip_len = nlen * sizeof(int); | skip_len = nlen * sizeof(int); | |||||||||
memcpy(skip_oid, oid, skip_len); | memcpy(skip_oid, oid, skip_len); | |||||||||
} | } | |||||||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | #endif | |||||||||
val = oval = malloc(j + 1); | val = oval = malloc(j + 1); | |||||||||
if (val == NULL) { | if (val == NULL) { | |||||||||
warnx("malloc failed"); | warnx("malloc failed"); | |||||||||
return (1); | return (1); | |||||||||
} | } | |||||||||
len = j; | len = j; | |||||||||
i = sysctl(oid, nlen, val, &len, 0, 0); | i = sysctl(oid, nlen, val, &len, 0, 0); | |||||||||
if (i != 0 || (len == 0 && ctltype != CTLTYPE_STRING)) { | if (i != 0 || (len == 0 && ctltype != CTLTYPE_STRING)) { | |||||||||
free(oval); | free(oval); | |||||||||
Done Inline ActionsLooking at how another sysctl failure is handled, it silently skips printing. I suppose this is for -a, all option. I will follow the same error handling. ota_j.email.ne.jp: Looking at how another sysctl failure is handled, it silently skips printing. I suppose this… | ||||||||||
return (1); | return (1); | |||||||||
} | } | |||||||||
if (bflag) { | if (bflag) { | |||||||||
fwrite(val, 1, len, stdout); | fwrite(val, 1, len, stdout); | |||||||||
free(oval); | free(oval); | |||||||||
return (0); | return (0); | |||||||||
} | } | |||||||||
val[len] = '\0'; | val[len] = '\0'; | |||||||||
p = val; | p = val; | |||||||||
sign = ctl_sign[ctltype]; | sign = ctl_sign[ctltype]; | |||||||||
intlen = ctl_size[ctltype]; | intlen = ctl_size[ctltype]; | |||||||||
switch (ctltype) { | switch (ctltype) { | |||||||||
case CTLTYPE_STRING: | case CTLTYPE_STRING: | |||||||||
if (!nflag) | if (!nflag) | |||||||||
printf("%s%s", name, sep); | printf("%s%s", name, sep); | |||||||||
if (lflag) | ||||||||||
printf("%zd%s", len, sep); | ||||||||||
printf("%.*s", (int)len, p); | printf("%.*s", (int)len, p); | |||||||||
free(oval); | free(oval); | |||||||||
return (0); | return (0); | |||||||||
case CTLTYPE_INT: | case CTLTYPE_INT: | |||||||||
case CTLTYPE_UINT: | case CTLTYPE_UINT: | |||||||||
case CTLTYPE_LONG: | case CTLTYPE_LONG: | |||||||||
case CTLTYPE_ULONG: | case CTLTYPE_ULONG: | |||||||||
case CTLTYPE_S8: | case CTLTYPE_S8: | |||||||||
case CTLTYPE_S16: | case CTLTYPE_S16: | |||||||||
case CTLTYPE_S32: | case CTLTYPE_S32: | |||||||||
case CTLTYPE_S64: | case CTLTYPE_S64: | |||||||||
case CTLTYPE_U8: | case CTLTYPE_U8: | |||||||||
case CTLTYPE_U16: | case CTLTYPE_U16: | |||||||||
case CTLTYPE_U32: | case CTLTYPE_U32: | |||||||||
case CTLTYPE_U64: | case CTLTYPE_U64: | |||||||||
if (!nflag) | if (!nflag) | |||||||||
printf("%s%s", name, sep); | printf("%s%s", name, sep); | |||||||||
if (lflag) | ||||||||||
printf("%zd%s", len, sep); | ||||||||||
hexlen = 2 + (intlen * CHAR_BIT + 3) / 4; | hexlen = 2 + (intlen * CHAR_BIT + 3) / 4; | |||||||||
sep1 = ""; | sep1 = ""; | |||||||||
while (len >= intlen) { | while (len >= intlen) { | |||||||||
switch (kind & CTLTYPE) { | switch (kind & CTLTYPE) { | |||||||||
case CTLTYPE_INT: | case CTLTYPE_INT: | |||||||||
case CTLTYPE_UINT: | case CTLTYPE_UINT: | |||||||||
umv = *(u_int *)p; | umv = *(u_int *)p; | |||||||||
mv = *(int *)p; | mv = *(int *)p; | |||||||||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | case CTLTYPE_U64: | |||||||||
free(oval); | free(oval); | |||||||||
return (0); | return (0); | |||||||||
case CTLTYPE_OPAQUE: | case CTLTYPE_OPAQUE: | |||||||||
i = 0; | i = 0; | |||||||||
if (func) { | if (func) { | |||||||||
if (!nflag) | if (!nflag) | |||||||||
printf("%s%s", name, sep); | printf("%s%s", name, sep); | |||||||||
if (lflag) | ||||||||||
printf("%zd%s", len, sep); | ||||||||||
i = (*func)(len, p); | i = (*func)(len, p); | |||||||||
free(oval); | free(oval); | |||||||||
return (i); | return (i); | |||||||||
} | } | |||||||||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | |||||||||
default: | default: | |||||||||
if (!oflag && !xflag) { | if (!oflag && !xflag) { | |||||||||
free(oval); | free(oval); | |||||||||
return (1); | return (1); | |||||||||
} | } | |||||||||
if (!nflag) | if (!nflag) | |||||||||
printf("%s%s", name, sep); | printf("%s%s", name, sep); | |||||||||
if (lflag) | ||||||||||
printf("%zd%s", len, sep); | ||||||||||
printf("Format:%s Length:%zu Dump:0x", fmt, len); | printf("Format:%s Length:%zu Dump:0x", fmt, len); | |||||||||
while (len-- && (xflag || p < val + 16)) | while (len-- && (xflag || p < val + 16)) | |||||||||
printf("%02x", *p++); | printf("%02x", *p++); | |||||||||
if (!xflag && len > 16) | if (!xflag && len > 16) | |||||||||
printf("..."); | printf("..."); | |||||||||
free(oval); | free(oval); | |||||||||
return (0); | return (0); | |||||||||
} | } | |||||||||
▲ Show 20 Lines • Show All 48 Lines • Show Last 20 Lines |
i is assigned but not used. I think it's quite likely that this sysctl call would always succeed as buf is sufficiently large, so if I was you I'd check the return value or maybe convert it to an assertion here.