Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 25 Apr 2002 15:49:24 +1000 (EST)
From:      Edwin Groothuis <edwin@mavetju.org>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   bin/37442: [PATCH] sleep.c to support time multipliers
Message-ID:  <20020425054924.A8057397@k7.mavetju.org>

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

>Number:         37442
>Category:       bin
>Synopsis:       [PATCH] sleep.c to support time multipliers
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Wed Apr 24 22:50:00 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     Edwin Groothuis
>Release:        FreeBSD 4.5-RELEASE i386
>Organization:
-
>Environment:
System: FreeBSD k7.mavetju.org 4.5-RELEASE FreeBSD 4.5-RELEASE #3: Mon Mar 11 13:32:05 EST 2002 edwin@k7.mavetju.org:/usr/src/sys/compile/k7 i386

Makefile:	1.8	1.5.2.1
sleep.c:	1.11	1.9.2.1
sleep.1:	1.17	1.5.2.2

>Description:

I want to run my nightly downloads run in an xterm, so I can check
if they've run properly. Often I have to delay them for hours and
am now pretty good skilled in the multiplication table of 1800, but
now and then things are one hour off. To solve this, I've modified
sleep(1) to support multipliers: sleep 1h will sleep for one hour,
sleep 2.5m will sleep for two and a half minute.

>How-To-Repeat:

>Fix:

Two patches, one against the 4.5 code, one against the -current of today.

This is patch against the 4.5 code:

--- Makefile-4.5	Thu Apr 25 15:25:49 2002
+++ Makefile	Thu Apr 25 15:09:25 2002
@@ -3,6 +3,8 @@
 
 PROG=	sleep
 
+LDADD= -lm
+
 WARNS?=	2
 
 .include <bsd.prog.mk>
--- sleep.1-4.5	Thu Apr 25 15:25:41 2002
+++ sleep.1	Thu Apr 25 15:18:15 2002
@@ -44,12 +44,18 @@
 .Sh SYNOPSIS
 .Nm
 .Ar seconds
+.Nm
+.Ar number[multiplier]
 .Sh DESCRIPTION
 The
 .Nm
 command
 suspends execution for a minimum of
-.Ar seconds .
+.Ar seconds
+or for the time specified by
+.Ar number[multiplier] .
+The multiplier can be `s' for seconds, `m' for minutes, `h' for
+hours and `d' for days.
 .Pp
 If the
 .Nm
@@ -85,6 +91,10 @@
 number seconds later:
 .Pp
 .Dl (sleep 1800; sh command_file >& errors)&
+.Pp
+or
+.Pp
+.Dl (sleep .5h; sh command_file >& errors)&
 .Pp
 This incantation would wait a half hour before
 running the script command_file.
--- sleep.c-4.5	Thu Apr 25 15:25:38 2002
+++ sleep.c	Thu Apr 25 15:12:59 2002
@@ -51,6 +51,7 @@
 #include <stdlib.h>
 #include <time.h>
 #include <unistd.h>
+#include <math.h>
 
 int main __P((int, char *[]));
 void usage __P((void));
@@ -61,7 +62,7 @@
 	char *argv[];
 {
 	struct timespec time_to_sleep;
-	long l;
+	double d;
 	int ch, neg;
 	char *p;
 
@@ -95,33 +96,43 @@
 	else if (*p == '+')
 		++p;
 
-	/* Calculate seconds. */
-	if (isdigit((unsigned char)*p)) {
-		l = strtol(p, &p, 10);
-		if (l > INT_MAX) {
-			/*
-			 * Avoid overflow when `seconds' is huge.  This assumes
-			 * that the maximum value for a time_t is >= 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;
-		} while (l /= 10);
+	d = atof(p);
+	while (*p != 0) {
+		if (!isdigit(*p) && *p != '.')
+			break;
+		p++;
 	}
 
+	/* Do multiplier trick. */
+	switch (*p) {
+	case 0:
+	case 's':
+		break;
+	case 'm':
+		d *= 60;
+		break;
+	case 'h':
+		d *= 60 * 60;
+		break;
+	case 'd':
+		d *= 24 * 60 * 60;
+		break;
+	default:
+		usage();
+		/* NOTREACHED */
+	}
+
+	if (d > INT_MAX)
+		d = INT_MAX;
+
+	/*
+	 * Split up the double into an integer (seconds) and
+	 * fractional (nanoseconds) part.
+	 */
+	time_to_sleep.tv_sec = (time_t)floor(d);
+	time_to_sleep.tv_nsec =
+			(time_t)1000000000L * (d - time_to_sleep.tv_sec);
+
 	if (!neg && (time_to_sleep.tv_sec > 0 || time_to_sleep.tv_nsec > 0))
 		(void)nanosleep(&time_to_sleep, (struct timespec *)NULL);
 
@@ -132,6 +144,6 @@
 usage()
 {
 
	(void)fprintf(stderr, "usage: sleep seconds\n");
+	(void)fprintf(stderr, "   or: sleep number[multiplier]\n");
 	exit(1);
 }


This is the patch against -current

--- Makefile-1.8	Thu Apr 25 15:24:31 2002
+++ Makefile	Thu Apr 25 15:09:25 2002
@@ -1,6 +1,8 @@
 #	@(#)Makefile	8.1 (Berkeley) 5/31/93
-# $FreeBSD: src/bin/sleep/Makefile,v 1.8 2001/12/04 01:57:46 obrien Exp $
+# $FreeBSD: src/bin/sleep/Makefile,v 1.5.2.1 2001/08/01 05:23:25 obrien Exp $
 
 PROG=	sleep
+
+LDADD= -lm
 
 .include <bsd.prog.mk>
--- sleep.1-1.17	Thu Apr 25 15:25:03 2002
+++ sleep.1	Thu Apr 25 15:18:15 2002
@@ -33,7 +33,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"	@(#)sleep.1	8.3 (Berkeley) 4/18/94
-.\" $FreeBSD: src/bin/sleep/sleep.1,v 1.17 2001/08/07 15:48:27 ru Exp $
+.\" $FreeBSD: src/bin/sleep/sleep.1,v 1.15.2.2 2001/08/16 10:01:09 ru Exp $
 .\"
 .Dd April 18, 1994
 .Dt SLEEP 1
@@ -44,12 +44,18 @@
 .Sh SYNOPSIS
 .Nm
 .Ar seconds
+.Nm
+.Ar number[multiplier]
 .Sh DESCRIPTION
 The
 .Nm
 command
 suspends execution for a minimum of
-.Ar seconds .
+.Ar seconds
+or for the time specified by
+.Ar number[multiplier] .
+The multiplier can be `s' for seconds, `m' for minutes, `h' for
+hours and `d' for days.
 .Pp
 If the
 .Nm
@@ -85,6 +91,10 @@
 number seconds later:
 .Pp
 .Dl (sleep 1800; sh command_file >& errors)&
+.Pp
+or
+.Pp
+.Dl (sleep .5h; sh command_file >& errors)&
 .Pp
 This incantation would wait a half hour before
 running the script command_file.
--- sleep.c-1.11	Thu Apr 25 15:23:38 2002
+++ sleep.c	Thu Apr 25 15:38:19 2002
@@ -42,7 +42,7 @@
 static char sccsid[] = "@(#)sleep.c	8.3 (Berkeley) 4/2/94";
 #endif
 static const char rcsid[] =
-  "$FreeBSD: src/bin/sleep/sleep.c,v 1.11 2002/02/02 06:50:56 imp Exp $";
+  "$FreeBSD: src/bin/sleep/sleep.c,v 1.9.2.1 2001/08/01 05:23:25 obrien Exp $";
 #endif /* not lint */
 
 #include <ctype.h>
@@ -51,6 +51,7 @@
 #include <stdlib.h>
 #include <time.h>
 #include <unistd.h>
+#include <math.h>
 
 void usage(void);
 
@@ -58,7 +59,7 @@
 main(int argc, char *argv[])
 {
 	struct timespec time_to_sleep;
-	long l;
+	double d;
 	int ch, neg;
 	char *p;
 
@@ -92,33 +93,43 @@
 	else if (*p == '+')
 		++p;
 
-	/* Calculate seconds. */
-	if (isdigit((unsigned char)*p)) {
-		l = strtol(p, &p, 10);
-		if (l > INT_MAX) {
-			/*
-			 * Avoid overflow when `seconds' is huge.  This assumes
-			 * that the maximum value for a time_t is >= 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;
-		} while (l /= 10);
+	d = atof(p);
+	while (*p != 0) {
+		if (!isdigit(*p) && *p != '.')
+			break;
+		p++;
 	}
 
+	/* Do multiplier trick. */
+	switch (*p) {
+	case 0:
+	case 's':
+		break;
+	case 'm':
+		d *= 60;
+		break;
+	case 'h':
+		d *= 60 * 60;
+		break;
+	case 'd':
+		d *= 24 * 60 * 60;
+		break;
+	default:
+		usage();
+		/* NOTREACHED */
+	}
+
+	if (d > INT_MAX)
+		d = INT_MAX;
+
+	/*
+	 * Split up the double into an integer (seconds) and
+	 * fractional (nanoseconds) part.
+	 */
+	time_to_sleep.tv_sec = (time_t)floor(d);
+	time_to_sleep.tv_nsec =
+			(time_t)1000000000L * (d - time_to_sleep.tv_sec);
+
 	if (!neg && (time_to_sleep.tv_sec > 0 || time_to_sleep.tv_nsec > 0))
 		(void)nanosleep(&time_to_sleep, (struct timespec *)NULL);
 
@@ -130,5 +141,6 @@
 {
 
 	(void)fprintf(stderr, "usage: sleep seconds\n");
+	(void)fprintf(stderr, "   or: sleep number[multiplier]\n");
 	exit(1);
 }
>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020425054924.A8057397>