svn commit: r331603 - stable/11/sbin/sysctl

John Baldwin jhb at FreeBSD.org
Tue Mar 27 00:35:36 UTC 2018


Author: jhb
Date: Tue Mar 27 00:35:35 2018
New Revision: 331603
URL: https://svnweb.freebsd.org/changeset/base/331603

Log:
  MFC 330711:
  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).
  
  Sponsored by:	Chelsio Communications

Modified:
  stable/11/sbin/sysctl/sysctl.8
  stable/11/sbin/sysctl/sysctl.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sbin/sysctl/sysctl.8
==============================================================================
--- stable/11/sbin/sysctl/sysctl.8	Mon Mar 26 23:54:59 2018	(r331602)
+++ stable/11/sbin/sysctl/sysctl.8	Tue Mar 27 00:35:35 2018	(r331603)
@@ -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: stable/11/sbin/sysctl/sysctl.c
==============================================================================
--- stable/11/sbin/sysctl/sysctl.c	Mon Mar 26 23:54:59 2018	(r331602)
+++ stable/11/sbin/sysctl/sysctl.c	Tue Mar 27 00:35:35 2018	(r331603)
@@ -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;


More information about the svn-src-all mailing list