Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 13 Nov 2002 10:07:22 -0800 (PST)
From:      Nate Lawson <nate@root.org>
To:        Sheldon Hearn <sheldonh@starjuice.net>
Cc:        current@freebsd.org
Subject:   Re: sleep(1) behavior
Message-ID:  <Pine.BSF.4.21.0211131003010.39871-200000@root.org>
In-Reply-To: <20021113080425.GO1278@starjuice.net>

next in thread | previous in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
On Wed, 13 Nov 2002, Sheldon Hearn wrote:
> On (2002/11/12 16:37), Nate Lawson wrote:
> 
> > I've found an interesting contradiction and was wondering what behavior
> > sleep should have.  It checks for a command line flag with getopt(3) and
> > exits with usage() if it finds one.  However, it then checks for a '-' or
> > '+' sign.  If negative, it behaves like "sleep 0" and exits
> > immediately.  This case can almost never be triggered since the
> > getopt(3) will catch the minus sign, even if a digit follows it.
> > 
> > Current behavior:
> > sleep 0 = exits immediately
> > sleep -1 = exits with usage()
> > sleep -f = exits with usage()
> > sleep "   -1" = exits immediately and is the only way I know to trigger
> > the negative case.
> > 
> > What is the standard, desired behavior?
> 
> IEEE Std 1003.2-1992 says:
> 
> 	time	A nonnegative decimal integer specifying the number of
> 		seconds for which to suspend execution.
> 
> I think it's pretty clear that negative time arguments to sleep(1) are
> not portable.

Thanks, that's what I was expecting.  The attached patch provides the
following behavior:

sleep 0 = exit 0 immediately
sleep [ \t]*1AAAA = sleep 1 second
sleep [ \t]*\.2zzz = sleep .2 seconds
sleep [ \t]*-.* = usage()

Please let me know if there are any problems with this patch.

-Nate

[-- Attachment #2 --]
Index: sleep.c
===================================================================
RCS file: /home/ncvs/src/bin/sleep/sleep.c,v
retrieving revision 1.12
diff -u -r1.12 sleep.c
--- sleep.c	30 Jun 2002 05:15:04 -0000	1.12
+++ sleep.c	13 Nov 2002 18:00:31 -0000
@@ -47,10 +47,10 @@
 
 #include <ctype.h>
 #include <limits.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
 #include <unistd.h>
+#include <string.h>
 
 void usage(void);
 
@@ -59,51 +59,43 @@
 {
 	struct timespec time_to_sleep;
 	long l;
-	int ch, neg;
 	char *p;
 
-	while ((ch = getopt(argc, argv, "")) != -1)
-		switch(ch) {
-		case '?':
-		default:
-			usage();
-			/* NOTREACHED */
-		}
-	argc -= optind;
-	argv += optind;
-
-	if (argc != 1) {
+	if (argc != 2) {
 		usage();
 		/* NOTREACHED */
 	}
 
-	p = argv[0];
+	p = argv[1];
 
 	/* Skip over leading whitespaces. */
 	while (isspace((unsigned char)*p))
 		++p;
 
-	/* Check for optional `+' or `-' sign. */
-	neg = 0;
+	/* No arguments or negative values are allowed */
 	if (*p == '-') {
-		neg = 1;
-		++p;
+		usage();
+		/* NOTREACHED */
 	}
-	else if (*p == '+')
+
+	/* Check for optional `+' sign. */
+	if (*p == '+')
 		++p;
 
 	/* Calculate seconds. */
-	if (isdigit((unsigned char)*p)) {
-		l = strtol(p, &p, 10);
-		if (l > INT_MAX) {
+	l = 0;
+	while (isdigit((unsigned char)*p)) {
+		l = (l * 10) + (*p - '0');
+		if (l > INT_MAX || l < 0) {
 			/*
 			 * Avoid overflow when `seconds' is huge.  This assumes
 			 * that the maximum value for a time_t is >= INT_MAX.
 			 */
 			l = INT_MAX;
+			break;
 		}
-	} else
-		l = 0;
+		++p;
+	}
 	time_to_sleep.tv_sec = (time_t)l;
 
 	/* Calculate nanoseconds. */
@@ -119,7 +111,7 @@
 		} while (l /= 10);
 	}
 
-	if (!neg && (time_to_sleep.tv_sec > 0 || time_to_sleep.tv_nsec > 0))
+	if (time_to_sleep.tv_sec > 0 || time_to_sleep.tv_nsec > 0)
 		(void)nanosleep(&time_to_sleep, (struct timespec *)NULL);
 
 	exit(0);
@@ -128,7 +120,8 @@
 void
 usage(void)
 {
+	const char *msg = "usage: sleep seconds\n";
 
-	(void)fprintf(stderr, "usage: sleep seconds\n");
+	write(STDOUT_FILENO, msg, strlen(msg));
 	exit(1);
 }

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.21.0211131003010.39871-200000>