Date: Fri, 9 Mar 2018 23:37:19 +0000 (UTC) From: John Baldwin <jhb@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r330711 - head/sbin/sysctl Message-ID: <201803092337.w29NbJSX093826@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jhb Date: Fri Mar 9 23:37:19 2018 New Revision: 330711 URL: https://svnweb.freebsd.org/changeset/base/330711 Log: Permit sysctl(8) to set an array of numeric values for a single node. Most sysctl nodes only return a single value, but some nodes return an array of values (e.g. kern.cp_time). sysctl(8) understand how to display the values of a node that returns multiple values (it prints out each numeric value separated by spaces). However, until now sysctl(8) has only been able to set sysctl nodes to a single value. This change allows sysctl to accept a new value for a numeric sysctl node that contains multiple values separated by either spaces or commas. sysctl(8) parses this list into an array of values and passes the array as the "new" value to sysctl(2). Reviewed by: rpokala MFC after: 1 week Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D14569 Modified: head/sbin/sysctl/sysctl.8 head/sbin/sysctl/sysctl.c Modified: head/sbin/sysctl/sysctl.8 ============================================================================== --- head/sbin/sysctl/sysctl.8 Fri Mar 9 23:25:18 2018 (r330710) +++ head/sbin/sysctl/sysctl.8 Fri Mar 9 23:37:19 2018 (r330711) @@ -28,7 +28,7 @@ .\" From: @(#)sysctl.8 8.1 (Berkeley) 6/6/93 .\" $FreeBSD$ .\" -.Dd December 10, 2015 +.Dd March 9, 2018 .Dt SYSCTL 8 .Os .Sh NAME @@ -39,7 +39,7 @@ .Op Fl bdehiNnoRTtqx .Op Fl B Ar bufsize .Op Fl f Ar filename -.Ar name Ns Op = Ns Ar value +.Ar name Ns Op = Ns Ar value Ns Op , Ns Ar value .Ar ... .Nm .Op Fl bdehNnoRTtqx Modified: head/sbin/sysctl/sysctl.c ============================================================================== --- head/sbin/sysctl/sysctl.c Fri Mar 9 23:25:18 2018 (r330710) +++ head/sbin/sysctl/sysctl.c Fri Mar 9 23:37:19 2018 (r330711) @@ -65,6 +65,7 @@ static const char rcsid[] = #include <errno.h> #include <inttypes.h> #include <locale.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -234,16 +235,17 @@ main(int argc, char **argv) } /* - * Parse a name into a MIB entry. - * Lookup and print out the MIB entry if it exists. - * Set a new value if requested. + * Parse a single numeric value, append it to 'newbuf', and update + * 'newsize'. Returns true if the value was parsed and false if the + * value was invalid. Non-numeric types (strings) are handled + * directly in parse(). */ -static int -parse(const char *string, int lineno) +static bool +parse_numeric(const char *newvalstr, const char *fmt, u_int kind, + void **newbufp, size_t *newsizep) { - int len, i, j; + void *newbuf; const void *newval; - const char *newvalstr = NULL; int8_t i8val; uint8_t u8val; int16_t i16val; @@ -254,11 +256,111 @@ parse(const char *string, int lineno) unsigned int uintval; long longval; unsigned long ulongval; - size_t newsize = Bflag; int64_t i64val; uint64_t u64val; + size_t valsize; + char *endptr = NULL; + + errno = 0; + + switch (kind & CTLTYPE) { + case CTLTYPE_INT: + if (strncmp(fmt, "IK", 2) == 0) + intval = strIKtoi(newvalstr, &endptr, fmt); + else + intval = (int)strtol(newvalstr, &endptr, 0); + newval = &intval; + valsize = sizeof(intval); + break; + case CTLTYPE_UINT: + uintval = (int) strtoul(newvalstr, &endptr, 0); + newval = &uintval; + valsize = sizeof(uintval); + break; + case CTLTYPE_LONG: + longval = strtol(newvalstr, &endptr, 0); + newval = &longval; + valsize = sizeof(longval); + break; + case CTLTYPE_ULONG: + ulongval = strtoul(newvalstr, &endptr, 0); + newval = &ulongval; + valsize = sizeof(ulongval); + break; + case CTLTYPE_S8: + i8val = (int8_t)strtol(newvalstr, &endptr, 0); + newval = &i8val; + valsize = sizeof(i8val); + break; + case CTLTYPE_S16: + i16val = (int16_t)strtol(newvalstr, &endptr, 0); + newval = &i16val; + valsize = sizeof(i16val); + break; + case CTLTYPE_S32: + i32val = (int32_t)strtol(newvalstr, &endptr, 0); + newval = &i32val; + valsize = sizeof(i32val); + break; + case CTLTYPE_S64: + i64val = strtoimax(newvalstr, &endptr, 0); + newval = &i64val; + valsize = sizeof(i64val); + break; + case CTLTYPE_U8: + u8val = (uint8_t)strtoul(newvalstr, &endptr, 0); + newval = &u8val; + valsize = sizeof(u8val); + break; + case CTLTYPE_U16: + u16val = (uint16_t)strtoul(newvalstr, &endptr, 0); + newval = &u16val; + valsize = sizeof(u16val); + break; + case CTLTYPE_U32: + u32val = (uint32_t)strtoul(newvalstr, &endptr, 0); + newval = &u32val; + valsize = sizeof(u32val); + break; + case CTLTYPE_U64: + u64val = strtoumax(newvalstr, &endptr, 0); + newval = &u64val; + valsize = sizeof(u64val); + break; + default: + /* NOTREACHED */ + abort(); + } + + if (errno != 0 || endptr == newvalstr || + (endptr != NULL && *endptr != '\0')) + return (false); + + newbuf = realloc(*newbufp, *newsizep + valsize); + if (newbuf == NULL) + err(1, "out of memory"); + memcpy((char *)newbuf + *newsizep, newval, valsize); + *newbufp = newbuf; + *newsizep += valsize; + + return (true); +} + +/* + * Parse a name into a MIB entry. + * Lookup and print out the MIB entry if it exists. + * Set a new value if requested. + */ +static int +parse(const char *string, int lineno) +{ + int len, i, j; + const void *newval; + char *newvalstr = NULL; + void *newbuf; + size_t newsize = Bflag; int mib[CTL_MAXNAME]; - char *cp, *bufp, buf[BUFSIZ], *endptr = NULL, fmt[BUFSIZ], line[BUFSIZ]; + char *cp, *bufp, buf[BUFSIZ], fmt[BUFSIZ], line[BUFSIZ]; u_int kind; if (lineno) @@ -377,94 +479,33 @@ parse(const char *string, int lineno) return (1); } - errno = 0; + newbuf = NULL; switch (kind & CTLTYPE) { - case CTLTYPE_INT: - if (strncmp(fmt, "IK", 2) == 0) - intval = strIKtoi(newvalstr, &endptr, fmt); - else - intval = (int)strtol(newvalstr, &endptr, - 0); - newval = &intval; - newsize = sizeof(intval); - break; - case CTLTYPE_UINT: - uintval = (int) strtoul(newvalstr, &endptr, 0); - newval = &uintval; - newsize = sizeof(uintval); - break; - case CTLTYPE_LONG: - longval = strtol(newvalstr, &endptr, 0); - newval = &longval; - newsize = sizeof(longval); - break; - case CTLTYPE_ULONG: - ulongval = strtoul(newvalstr, &endptr, 0); - newval = &ulongval; - newsize = sizeof(ulongval); - break; - case CTLTYPE_STRING: - newval = newvalstr; - break; - case CTLTYPE_S8: - i8val = (int8_t)strtol(newvalstr, &endptr, 0); - newval = &i8val; - newsize = sizeof(i8val); - break; - case CTLTYPE_S16: - i16val = (int16_t)strtol(newvalstr, &endptr, - 0); - newval = &i16val; - newsize = sizeof(i16val); - break; - case CTLTYPE_S32: - i32val = (int32_t)strtol(newvalstr, &endptr, - 0); - newval = &i32val; - newsize = sizeof(i32val); - break; - case CTLTYPE_S64: - i64val = strtoimax(newvalstr, &endptr, 0); - newval = &i64val; - newsize = sizeof(i64val); - break; - case CTLTYPE_U8: - u8val = (uint8_t)strtoul(newvalstr, &endptr, 0); - newval = &u8val; - newsize = sizeof(u8val); - break; - case CTLTYPE_U16: - u16val = (uint16_t)strtoul(newvalstr, &endptr, - 0); - newval = &u16val; - newsize = sizeof(u16val); - break; - case CTLTYPE_U32: - u32val = (uint32_t)strtoul(newvalstr, &endptr, - 0); - newval = &u32val; - newsize = sizeof(u32val); - break; - case CTLTYPE_U64: - u64val = strtoumax(newvalstr, &endptr, 0); - newval = &u64val; - newsize = sizeof(u64val); - break; - default: - /* NOTREACHED */ - abort(); + case CTLTYPE_STRING: + newval = newvalstr; + break; + default: + newsize = 0; + while ((cp = strsep(&newvalstr, " ,")) != NULL) { + if (*cp == '\0') + continue; + if (!parse_numeric(cp, fmt, kind, &newbuf, + &newsize)) { + warnx("invalid %s '%s'%s", + ctl_typename[kind & CTLTYPE], + cp, line); + free(newbuf); + return (1); + } + } + newval = newbuf; + break; } - if (errno != 0 || endptr == newvalstr || - (endptr != NULL && *endptr != '\0')) { - warnx("invalid %s '%s'%s", ctl_typename[kind & CTLTYPE], - newvalstr, line); - return (1); - } - i = show_var(mib, len); if (sysctl(mib, len, 0, 0, newval, newsize) == -1) { + free(newbuf); if (!i && !bflag) putchar('\n'); switch (errno) { @@ -485,6 +526,7 @@ parse(const char *string, int lineno) return (1); } } + free(newbuf); if (!bflag) printf(" -> "); i = nflag;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201803092337.w29NbJSX093826>