[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openbsd-tech
Subject:    Re: systat(1): improve parsing of delay value
From:       Alexander Bluhm <alexander.bluhm () gmx ! net>
Date:       2021-01-28 21:51:01
Message-ID: YBMxxc2VunM+ghxZ () t430s ! bluhm ! invalid
[Download RAW message or body]

On Thu, Jan 28, 2021 at 09:06:51PM +0100, Martijn van Duren wrote:
> Thanks for checking. Should be fixed below.

OK bluhm@

> 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);
> 

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic