svn commit: r210749 - head/bin/sleep

Konstantin Belousov kib at FreeBSD.org
Mon Aug 2 10:57:56 UTC 2010


Author: kib
Date: Mon Aug  2 10:57:56 2010
New Revision: 210749
URL: http://svn.freebsd.org/changeset/base/210749

Log:
  Simplify argument parser by using sscanf(); simplify usage() by not
  refusing to use stdio.
  Reduce nesting level in the sleep loop by returning earlier for negative
  timeouts.
  Limit the maximum timeout to INT_MAX seconds.
  
  Submitted by:	bde
  MFC after:	3 weeks

Modified:
  head/bin/sleep/sleep.c

Modified: head/bin/sleep/sleep.c
==============================================================================
--- head/bin/sleep/sleep.c	Mon Aug  2 10:31:39 2010	(r210748)
+++ head/bin/sleep/sleep.c	Mon Aug  2 10:57:56 2010	(r210749)
@@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$");
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
-#include <unistd.h>
 
 static void usage(void);
 
@@ -65,91 +64,39 @@ int
 main(int argc, char *argv[])
 {
 	struct timespec time_to_sleep;
-	long l, original;
-	int neg;
-	char *p;
+	double d;
+	time_t original;
+	char buf[2];
 
 	if (argc != 2)
 		usage();
 
-	p = argv[1];
-
-	/* Skip over leading whitespaces. */
-	while (isspace((unsigned char)*p))
-		++p;
-
-	/* Check for optional `+' or `-' sign. */
-	neg = 0;
-	if (*p == '-') {
-		neg = 1;
-		++p;
-		if (!isdigit((unsigned char)*p) && *p != '.')
-			usage();
-	}
-	else if (*p == '+')
-		++p;
-
-	/* Calculate seconds. */
-	if (isdigit((unsigned char)*p)) {
-		l = strtol(p, &p, 10);
-
-		/*
-		 * Avoid overflow when `seconds' is huge.  This assumes
-		 * that the maximum value for a time_t is <= INT_MAX.
-		 */
-		if (l > INT_MAX)
-			l = INT_MAX;
-	} else
-		l = 0;
-	time_to_sleep.tv_sec = (time_t)l;
-
-	/* Calculate nanoseconds. */
-	time_to_sleep.tv_nsec = 0;
-
-	if (*p == '.') {		/* Decimal point. */
-		l = 100000000L;
-		do {
-			if (isdigit((unsigned char)*++p))
-				time_to_sleep.tv_nsec += (*p - '0') * l;
-			else
-				break;
-			l /= 10;
-		} while (l);
-	}
-
-	/* Skip over the trailing whitespace. */
-	while (isspace((unsigned char)*p))
-		++p;
-	if (*p != '\0')
+	if (sscanf(argv[1], "%lf%1s", &d, buf) != 1)
+		usage();
+	if (d > INT_MAX)
 		usage();
+	if (d <= 0)
+		return (0);
+	original = time_to_sleep.tv_sec = (time_t)d;
+	time_to_sleep.tv_nsec = 1e9 * (d - time_to_sleep.tv_sec);
 
 	signal(SIGINFO, report_request);
-	if (!neg && (time_to_sleep.tv_sec > 0 || time_to_sleep.tv_nsec > 0)) {
-		original = time_to_sleep.tv_sec;
-		while (nanosleep(&time_to_sleep, &time_to_sleep) != 0) {
-			if (report_requested) {
-				/*
-				 * Reporting does not bother with
-				 * fractions of a second...
-				 */
-				warnx("about %jd second(s) left"
-				    " out of the original %jd",
-				    (intmax_t)time_to_sleep.tv_sec,
-				    (intmax_t)original);
-				report_requested = 0;
-			} else
-				break;
-		}
+	while (nanosleep(&time_to_sleep, &time_to_sleep) != 0) {
+		if (report_requested) {
+			/* Reporting does not bother with nanoseconds. */
+			warnx("about %d second(s) left out of the original %d",
+			    (int)time_to_sleep.tv_sec, (int)original);
+			report_requested = 0;
+		} else
+			break;
 	}
-
 	return (0);
 }
 
 static void
 usage(void)
 {
-	static const char msg[] = "usage: sleep seconds\n";
 
-	write(STDERR_FILENO, msg, sizeof(msg) - 1);
+	fprintf(stderr, "usage: sleep seconds\n");
 	exit(1);
 }


More information about the svn-src-all mailing list