Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 29 Jul 2015 02:34:26 +0000 (UTC)
From:      Warner Losh <imp@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r285994 - in head: sbin/sysctl share/man/man9
Message-ID:  <201507290234.t6T2YQu4076316@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: imp
Date: Wed Jul 29 02:34:25 2015
New Revision: 285994
URL: https://svnweb.freebsd.org/changeset/base/285994

Log:
  Teach sysctl about the new optional suffix after IK to specify
  precision. Update input as well. Add IK to the manual (it was missing
  completely).
  
  Differential Revision: https://reviews.freebsd.org/D3181

Modified:
  head/sbin/sysctl/sysctl.c
  head/share/man/man9/sysctl.9

Modified: head/sbin/sysctl/sysctl.c
==============================================================================
--- head/sbin/sysctl/sysctl.c	Wed Jul 29 02:26:57 2015	(r285993)
+++ head/sbin/sysctl/sysctl.c	Wed Jul 29 02:34:25 2015	(r285994)
@@ -81,7 +81,7 @@ static int	show_var(int *, int);
 static int	sysctl_all(int *oid, int len);
 static int	name2oid(const char *, int *);
 
-static int	strIKtoi(const char *, char **);
+static int	strIKtoi(const char *, char **, const char *);
 
 static int ctl_sign[CTLTYPE+1] = {
 	[CTLTYPE_INT] = 1,
@@ -336,8 +336,8 @@ parse(const char *string, int lineno)
 
 		switch (kind & CTLTYPE) {
 			case CTLTYPE_INT:
-				if (strcmp(fmt, "IK") == 0)
-					intval = strIKtoi(newvalstr, &endptr);
+				if (strncmp(fmt, "IK", 2) == 0)
+					intval = strIKtoi(newvalstr, &endptr, fmt);
 				else
 					intval = (int)strtol(newvalstr, &endptr,
 					    0);
@@ -666,12 +666,13 @@ S_bios_smap_xattr(size_t l2, void *p)
 #endif
 
 static int
-strIKtoi(const char *str, char **endptrp)
+strIKtoi(const char *str, char **endptrp, const char *fmt)
 {
 	int kelv;
 	float temp;
 	size_t len;
 	const char *p;
+	int prec, i;
 
 	assert(errno == 0);
 
@@ -679,16 +680,36 @@ strIKtoi(const char *str, char **endptrp
 	/* caller already checked this */
 	assert(len > 0);
 
+	/*
+	 * A format of "IK" is in deciKelvin. A format of "IK3" is in
+	 * milliKelvin. The single digit following IK is log10 of the
+	 * multiplying factor to convert Kelvin into the untis of this sysctl,
+	 * or the dividing factor to convert the sysctl value to Kelvin. Numbers
+	 * larger than 6 will run into precision issues with 32-bit integers.
+	 * Characters that aren't ASCII digits after the 'K' are ignored. No
+	 * localization is present because this is an interface from the kernel
+	 * to this program (eg not an end-user interface), so isdigit() isn't
+	 * used here.
+	 */
+	if (fmt[2] != '\0' && fmt[2] >= '0' && fmt[2] <= '9')
+		prec = fmt[2] - '0';
+	else
+		prec = 1;
 	p = &str[len - 1];
-	if (*p == 'C' || *p == 'F') {
+	if (*p == 'C' || *p == 'F' || *p == 'K') {
 		temp = strtof(str, endptrp);
 		if (*endptrp != str && *endptrp == p && errno == 0) {
 			if (*p == 'F')
 				temp = (temp - 32) * 5 / 9;
 			*endptrp = NULL;
-			return (temp * 10 + 2732);
+			if (*p != 'K')
+				temp += 273.15;
+			for (i = 0; i < prec; i++)
+				temp *= 10.0;
+			return ((int)(temp + 0.5));
 		}
 	} else {
+		/* No unit specified -> treat it as a raw number */
 		kelv = (int)strtol(str, endptrp, 10);
 		if (*endptrp != str && *endptrp == p && errno == 0) {
 			*endptrp = NULL;
@@ -772,7 +793,9 @@ show_var(int *oid, int nlen)
 	size_t intlen;
 	size_t j, len;
 	u_int kind;
+	float base;
 	int (*func)(size_t, void *);
+	int prec;
 
 	/* Silence GCC. */
 	umv = mv = intlen = 0;
@@ -893,8 +916,19 @@ show_var(int *oid, int nlen)
 			else if (fmt[1] == 'K') {
 				if (mv < 0)
 					printf("%jd", mv);
-				else
-					printf("%.1fC", (mv - 2732.0) / 10);
+				else {
+					/*
+					 * See strIKtoi for details on fmt.
+					 */
+					prec = 1;
+					if (fmt[2] != '\0')
+						prec = fmt[2] - '0';
+					base = 1.0;
+					for (int i = 0; i < prec; i++)
+						base *= 10.0;
+					printf("%.*fC", prec,
+					    (float)mv / base - 273.15);
+				}
 			} else
 				printf(hflag ? "%'jd" : "%jd", mv);
 			sep1 = " ";

Modified: head/share/man/man9/sysctl.9
==============================================================================
--- head/share/man/man9/sysctl.9	Wed Jul 29 02:26:57 2015	(r285993)
+++ head/share/man/man9/sysctl.9	Wed Jul 29 02:34:25 2015	(r285994)
@@ -318,35 +318,33 @@ which specifies the format of the OID in
 This format is used as a hint by
 .Xr sysctl 8
 to apply proper data formatting for display purposes.
-Currently used format names are:
-.Dq N
-for node,
-.Dq A
-for
-.Li "char *" ,
-.Dq I
-for
-.Li "int" ,
-.Dq IU
-for
-.Li "unsigned int" ,
-.Dq L
-for
-.Li "long" ,
-.Dq LU
-for
-.Li "unsigned long" ,
-.Dq Q
-for
-.Li "quad_t" ,
-.Dq QU
-for
+.Pp
+Current formats:
+.Bl -tag -width "S,TYPE" -compact -offset indent
+.It Cm N
+node
+.It Cm A
+.Li "char *"
+.It Cm I
+.Li "int"
+.It Cm IK Ns Op Ar n
+temperature in Kelvin, multiplied by an optional single digit
+power of ten scaling factor: 1 (default) gives deciKelvin, 0 gives Kelvin, 3
+gives milliKelvin
+.It Cm IU
+.Li "unsigned int"
+.It Cm L
+.Li "long"
+.It Cm LU
+.Li "unsigned long"
+.It Cm Q
+.Li "quad_t"
+.It Cm QU
 .Li "u_quad_t"
-and
-.Dq S,TYPE
-for
+.It Cm "S,TYPE"
 .Li "struct TYPE"
-structures.
+structures
+.El
 .It Fa descr
 A pointer to a textual description of the OID.
 .El



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201507290234.t6T2YQu4076316>