On Tue, 2021-01-26 at 16:40 +0100, Alexander Bluhm wrote: > On Mon, Jan 25, 2021 at 11:17:04AM +0100, Martijn van Duren wrote: > > if (argc == 1) { > > - double del = atof(argv[0]); > > - if (del == 0) > > + delay = strtodnum(argv[0], 0, UINT32_MAX / 1000000, > > &errstr); > > + if (errstr != NULL) > > viewstr = argv[0]; > > - else > > - delay = del; > > You need the else. delay should only be changed if parsing was successful. > > > } else if (argc == 2) { > > viewstr = argv[0]; > > - delay = atof(argv[1]); > > - if (delay <= 0) > > - delay = 5; > > + delay = strtodnum(optarg, 0, UINT32_MAX / 1000000, &errstr); > > This should be argv[1] instead of optarg. > > > + if (errstr != NULL) > > + errx(1, "-s \"%s\": delay value is %s", optarg, > > errstr); > > } > > The -s in the error message is wrong. Here delay was passed as argument. > > bluhm > Thanks for checking. Should be fixed below.
Index: main.c =================================================================== RCS file: /cvs/src/usr.bin/systat/main.c,v retrieving revision 1.72 diff -u -p -r1.72 main.c --- main.c 12 Jan 2020 20:51:08 -0000 1.72 +++ main.c 28 Jan 2021 20:05:30 -0000 @@ -40,9 +40,11 @@ #include <errno.h> #include <fcntl.h> #include <limits.h> +#include <math.h> #include <netdb.h> #include <signal.h> #include <stdio.h> +#include <stdint.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> @@ -73,6 +75,7 @@ char uloadbuf[TIMEPOS]; int ucount(void); void usage(void); +double strtodnum(const char *, double, double, const char **); /* command prompt */ @@ -323,9 +326,14 @@ void cmd_delay(const char *buf) { double del; - del = atof(buf); + const char *errstr; - if (del > 0) { + if (buf[0] == '\0') + return; + del = strtodnum(buf, 0, UINT32_MAX / 1000000, &errstr); + if (errstr != NULL) + error("s: \"%s\": delay value is %s", buf, errstr); + else { udelay = (useconds_t)(del * 1000000); gotsig_alarm = 1; naptime = del; @@ -414,6 +422,48 @@ gethz(void) hz = cinf.hz; } +#define INVALID 1 +#define TOOSMALL 2 +#define TOOLARGE 3 + +double +strtodnum(const char *nptr, double minval, double maxval, const char **errstrp) +{ + double d = 0; + int error = 0; + char *ep; + struct errval { + const char *errstr; + int err; + } ev[4] = { + { NULL, 0 }, + { "invalid", EINVAL }, + { "too small", ERANGE }, + { "too large", ERANGE }, + }; + + ev[0].err = errno; + errno = 0; + if (minval > maxval) { + error = INVALID; + } else { + d = strtod(nptr, &ep); + if (nptr == ep || *ep != '\0') + error = INVALID; + else if ((d == -HUGE_VAL && errno == ERANGE) || d < minval) + error = TOOSMALL; + else if ((d == HUGE_VAL && errno == ERANGE) || d > maxval) + error = TOOLARGE; + } + if (errstrp != NULL) + *errstrp = ev[error].errstr; + errno = ev[error].err; + if (error) + d = 0; + + return (d); +} + int main(int argc, char *argv[]) { @@ -421,7 +471,7 @@ main(int argc, char *argv[]) const char *errstr; extern char *optarg; extern int optind; - double delay = 5; + double delay = 5, del; char *viewstr = NULL; @@ -475,9 +525,11 @@ main(int argc, char *argv[]) nflag = 1; break; case 's': - delay = atof(optarg); - if (delay <= 0) - delay = 5; + delay = strtodnum(optarg, 0, UINT32_MAX / 1000000, + &errstr); + if (errstr != NULL) + errx(1, "-s \"%s\": delay value is %s", optarg, + errstr); break; case 'w': rawwidth = strtonum(optarg, 1, MAX_LINE_BUF-1, &errstr); @@ -497,16 +549,16 @@ main(int argc, char *argv[]) argv += optind; if (argc == 1) { - double del = atof(argv[0]); - if (del == 0) + del = strtodnum(argv[0], 0, UINT32_MAX / 1000000, &errstr); + if (errstr != NULL) viewstr = argv[0]; else delay = del; } else if (argc == 2) { viewstr = argv[0]; - delay = atof(argv[1]); - if (delay <= 0) - delay = 5; + delay = strtodnum(argv[1], 0, UINT32_MAX / 1000000, &errstr); + if (errstr != NULL) + errx(1, "\"%s\": delay value is %s", argv[1], errstr); } udelay = (useconds_t)(delay * 1000000.0);