From d9c4b6b01181b3fcd2d42540cc1737c42708ae29 Mon Sep 17 00:00:00 2001 From: Jan Rybar Date: Sun, 6 Aug 2017 00:00:00 +0200 Subject: [PATCH] top: refresh interval accepts non-locale decimal value For the past 3 years top has fully honored that locale LC_NUMERIC setting which impacts his refresh interval. For the past nearly 5 years top has saved that refresh value in a locale independent form in his config file. With this commit we'll intentionally break top so that a comma or period will be accepted for the radix point regardless of what that LC_NUMERIC may have suggested. The current locale LC_NUMERIC will, however, determine how the delay interval is displayed in the 'd' prompt. [ This position is better than the approach employed ] [ by those coreutils 'sleep' and 'timeout' programs. ] [ Both claim to permit floating point arguments. But ] [ neither one will accept the comma separator should ] [ the locale be a country that in fact uses a comma. ] Reference(s): https://gitlab.com/procps-ng/procps/merge_requests/50 Prototyped by: Jan Rybar Signed-off-by: Jim Warner --- NEWS | 1 + top/top.c | 22 ++++++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index e0be152a..7f3e967a 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,7 @@ procps-ng-NEXT * top: provides more accurate cpu usage at startup * top: display NUMA node under which a thread ran * top: fix argument parsing quirk resulting in SEGV Redhat #1450429 + * top: delay interval accepts non-locale radix point Redhat #1182248 * watch: define HOST_NAME_MAX where not defined Debian #830734 procps-ng-3.3.12 diff --git a/top/top.c b/top/top.c index 4e81e669..385df1d5 100644 --- a/top/top.c +++ b/top/top.c @@ -1241,15 +1241,25 @@ static char *ioline (const char *prompt) { /* - * Make locale aware float (but maybe restrict to whole numbers). */ + * Make locale unaware float (but maybe restrict to whole numbers). */ static int mkfloat (const char *str, float *num, int whole) { - char *ep; + char tmp[SMLBUFSIZ], *ep; - if (whole) + if (whole) { *num = (float)strtol(str, &ep, 0); - else - *num = strtof(str, &ep); - if (ep != str && *ep == '\0' && *num < INT_MAX) + if (ep != str && *ep == '\0' && *num < INT_MAX) + return 1; + return 0; + } + snprintf(tmp, sizeof(tmp), "%s", str); + *num = strtof(tmp, &ep); + if (*ep != '\0') { + // fallback - try to swap the floating point separator + if (*ep == '.') *ep = ','; + else if (*ep == ',') *ep = '.'; + *num = strtof(tmp, &ep); + } + if (ep != tmp && *ep == '\0' && *num < INT_MAX) return 1; return 0; } // end: mkfloat