From owner-svn-src-head@freebsd.org Fri Mar 9 23:37:20 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 869D6F3087C; Fri, 9 Mar 2018 23:37:20 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 350ED739FF; Fri, 9 Mar 2018 23:37:20 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 2E38D25B39; Fri, 9 Mar 2018 23:37:20 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w29NbKOH093828; Fri, 9 Mar 2018 23:37:20 GMT (envelope-from jhb@FreeBSD.org) Received: (from jhb@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w29NbJSX093826; Fri, 9 Mar 2018 23:37:19 GMT (envelope-from jhb@FreeBSD.org) Message-Id: <201803092337.w29NbJSX093826@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jhb set sender to jhb@FreeBSD.org using -f From: John Baldwin Date: Fri, 9 Mar 2018 23:37:19 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r330711 - head/sbin/sysctl X-SVN-Group: head X-SVN-Commit-Author: jhb X-SVN-Commit-Paths: head/sbin/sysctl X-SVN-Commit-Revision: 330711 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 09 Mar 2018 23:37:20 -0000 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 #include #include +#include #include #include #include @@ -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;