diff options
author | imp <imp@FreeBSD.org> | 2015-07-29 02:34:25 +0000 |
---|---|---|
committer | imp <imp@FreeBSD.org> | 2015-07-29 02:34:25 +0000 |
commit | 5f3e1e3c1b0e52c8c7e437b0dc3a55fbd40e24a9 (patch) | |
tree | 88906ba367a495dc54601fa5132ee65b7f4c3d8c /sbin/sysctl | |
parent | 44267026a04d5bba6872796d13bd9f9e83d859fe (diff) | |
download | FreeBSD-src-5f3e1e3c1b0e52c8c7e437b0dc3a55fbd40e24a9.zip FreeBSD-src-5f3e1e3c1b0e52c8c7e437b0dc3a55fbd40e24a9.tar.gz |
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
Diffstat (limited to 'sbin/sysctl')
-rw-r--r-- | sbin/sysctl/sysctl.c | 50 |
1 files changed, 42 insertions, 8 deletions
diff --git a/sbin/sysctl/sysctl.c b/sbin/sysctl/sysctl.c index f321120..d740778c 100644 --- a/sbin/sysctl/sysctl.c +++ b/sbin/sysctl/sysctl.c @@ -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 = " "; |