From edwin@mavetju.org  Wed Apr 24 22:48:33 2002
Return-Path: <edwin@mavetju.org>
Received: from topaz.mdcc.cx (topaz.mdcc.cx [212.204.230.141])
	by hub.freebsd.org (Postfix) with ESMTP id 7981037B404
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 24 Apr 2002 22:48:32 -0700 (PDT)
Received: from k7.mavetju.org (topaz.mdcc.cx [212.204.230.141])
	by topaz.mdcc.cx (Postfix) with ESMTP id 4A89C2B6CB
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 25 Apr 2002 07:48:26 +0200 (CEST)
Received: by k7.mavetju.org (Postfix, from userid 1001)
	id A8057397; Thu, 25 Apr 2002 15:49:24 +1000 (EST)
Message-Id: <20020425054924.A8057397@k7.mavetju.org>
Date: Thu, 25 Apr 2002 15:49:24 +1000 (EST)
From: Edwin Groothuis <edwin@mavetju.org>
Reply-To: Edwin Groothuis <edwin@mavetju.org>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [PATCH] sleep.c to support time multipliers
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         37442
>Category:       bin
>Synopsis:       [patch] sleep(1) 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:  Wed May 21 21:39:23 UTC 2008
>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:

From: Peter Pentchev <roam@ringlet.net>
To: Edwin Groothuis <edwin@mavetju.org>
Cc: bug-followup@FreeBSD.org
Subject: Re: bin/37442: [PATCH] sleep.c to support time multipliers
Date: Thu, 25 Apr 2002 14:07:17 +0300

 On Thu, Apr 25, 2002 at 03:49:24PM +1000, Edwin Groothuis wrote:
 > 
 > >Number:         37442
 > >Category:       bin
 > >Synopsis:       [PATCH] sleep.c to support time multipliers
 > >Originator:     Edwin Groothuis
 > >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.
 
 Mmm... not to knock your patch down, but.. you do realize that
 this can be done with expr(1) and/or shell built-in arithmetic
 functions (ksh and bash have $((5 * 1800)), don't know about
 other shells), right?
 
 G'luck,
 Peter
 
 -- 
 Peter Pentchev	roam@ringlet.net	roam@FreeBSD.org
 PGP key:	http://people.FreeBSD.org/~roam/roam.key.asc
 Key fingerprint	FDBA FD79 C26F 3C51 C95E  DF9E ED18 B68D 1619 4553
 No language can express every thought unambiguously, least of all this one.

From: Edwin Groothuis <edwin@mavetju.org>
To: Peter Pentchev <roam@ringlet.net>
Cc: bug-followup@FreeBSD.org
Subject: Re: bin/37442: [PATCH] sleep.c to support time multipliers
Date: Thu, 25 Apr 2002 21:46:13 +1000

 On Thu, Apr 25, 2002 at 02:07:17PM +0300, Peter Pentchev wrote:
 > On Thu, Apr 25, 2002 at 03:49:24PM +1000, Edwin Groothuis wrote:
 > > 
 > > >Number:         37442
 > > >Category:       bin
 > > >Synopsis:       [PATCH] sleep.c to support time multipliers
 > > >Originator:     Edwin Groothuis
 > > >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.
 > 
 > Mmm... not to knock your patch down, but.. you do realize that
 > this can be done with expr(1) and/or shell built-in arithmetic
 > functions (ksh and bash have $((5 * 1800)), don't know about
 > other shells), right?
 
 Yes I know, that's what I did in the beginning. But I also know
 that its easier to write (and make sure it's correct) '2.5h' than
 '9000' (or echo ((5 * 1800)), which puts you in the situation that
 you're thinking in 5 half hours instead of 2.5 hours (which is the
 same in timespan but not how an average person thinks)).
 
 Edwin
 
 -- 
 Edwin Groothuis      |           Personal website: http://www.MavEtJu.org
 edwin@mavetju.org    |        Interested in MUDs? Visit Fatal Dimensions:
 bash$ :(){ :|:&};:   |                    http://www.FatalDimensions.org/

From: Andrew <andrew@ugh.net.au>
To: freebsd-gnats-submit@FreeBSD.org, edwin@mavetju.org
Cc:  
Subject: Re: bin/37442: [PATCH] sleep.c to support time multipliers
Date: Wed, 12 Jun 2002 23:58:56 +1000

  > Mmm... not to knock your patch down, but.. you do realize > that this 
 can be done with expr(1) and/or shell built-in
  > arithmetic functions (ksh and bash have $((5 * 1800)),
  > don't know about other shells), right?
 
 That shouldn't be enough to stop the patch though (IMHO anyway). After 
 all df supports -h and I'm sure with a bit of awk and/or sh you could 
 get similar behavior without this rather nice switch.
 
 It just makes sleep that bit more convenient without breaking any 
 historical behavior.
 
 Andrew
 

From: Ruslan Ermilov <ru@FreeBSD.org>
To: Edwin Groothuis <edwin@mavetju.org>
Cc: bug-followup@FreeBSD.org
Subject: Re: bin/37442 - patch for /bin/sleep
Date: Mon, 12 Aug 2002 20:38:29 +0300

 On Mon, Aug 12, 2002 at 09:04:20PM +1000, Edwin Groothuis wrote:
 > Greetings,
 > 
 > "Why me" is what you ask yourself now probably. Mostly because you
 > are the one who made the last changes to sleep.c... nearly three
 > years ago :-/
 > 
 > Could you have please a look at PR bin/37442?
 >     (http://www.freebsd.org/cgi/query-pr.cgi?pr=bin/37442)
 > 
 > The PR is about a small change in sleep which allows the usage of
 > multipliers: So that 10m is 10 minutes, 3h is three hours and 4d
 > is four days.
 > 
 > It doesn't break any current script-usages, it only adds extra
 > flexibility for people who want to use it.
 > 
 POSIX.1-2001 clearly documents the sleep(1)'s SYNOPSIS:
 
 : SYNOPSIS
 :             sleep time
 
 And requires that:
 
 : DESCRIPTION
 :             The sleep utility shall suspend execution for at least
 :             the integral number of seconds specified by the time
 :             operand.
 
 We are currently "compatible" with POSIX in that we don't violate it
 (POSIX allows the implementation to support more fine-grained sleep,
 just does not require it to).
 
 If we make the change you propose, we will become incompatible with
 POSIX, as the latter requires ``sleep 10m'' to sleep for "at least
 10 seconds".
 
 I will close the PR if you don't mind, pending your confirmation.
 
 
 Cheers,
 -- 
 Ruslan Ermilov		Sysadmin and DBA,
 ru@sunbay.com		Sunbay Software AG,
 ru@FreeBSD.org		FreeBSD committer,
 +380.652.512.251	Simferopol, Ukraine
 
 http://www.FreeBSD.org	The Power To Serve
 http://www.oracle.com	Enabling The Information Age

From: Ruslan Ermilov <ru@FreeBSD.org>
To: "."@babolo.ru
Cc: bug-followup@FreeBSD.org
Subject: Re: bin/37442 - patch for /bin/sleep
Date: Tue, 13 Aug 2002 11:34:51 +0300

 --qcHopEYAB45HaUaB
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 Content-Transfer-Encoding: quoted-printable
 
 On Tue, Aug 13, 2002 at 01:52:41AM +0400, "."@babolo.ru wrote:
 > Ruslan Ermilov writes:
 > > The following reply was made to PR bin/37442; it has been noted by GNAT=
 S.
 > >=20
 > > From: Ruslan Ermilov <ru@FreeBSD.org>
 > > To: Edwin Groothuis <edwin@mavetju.org>
 > > Cc: bug-followup@FreeBSD.org
 > > Subject: Re: bin/37442 - patch for /bin/sleep
 > > Date: Mon, 12 Aug 2002 20:38:29 +0300
 > >=20
 > >  On Mon, Aug 12, 2002 at 09:04:20PM +1000, Edwin Groothuis wrote:
 > >  > Greetings,
 > >  >=20
 > >  > "Why me" is what you ask yourself now probably. Mostly because you
 > >  > are the one who made the last changes to sleep.c... nearly three
 > >  > years ago :-/
 > >  >=20
 > >  > Could you have please a look at PR bin/37442?
 > >  >     (http://www.freebsd.org/cgi/query-pr.cgi?pr=3Dbin/37442)
 > >  >=20
 > >  > The PR is about a small change in sleep which allows the usage of
 > >  > multipliers: So that 10m is 10 minutes, 3h is three hours and 4d
 > >  > is four days.
 > >  >=20
 > >  > It doesn't break any current script-usages, it only adds extra
 > >  > flexibility for people who want to use it.
 > >  >=20
 > >  POSIX.1-2001 clearly documents the sleep(1)'s SYNOPSIS:
 > > =20
 > >  : SYNOPSIS
 > >  :             sleep time
 > > =20
 > >  And requires that:
 > > =20
 > >  : DESCRIPTION
 > >  :             The sleep utility shall suspend execution for at least
 > >  :             the integral number of seconds specified by the time
 > >  :             operand.
 > > =20
 > >  We are currently "compatible" with POSIX in that we don't violate it
 > >  (POSIX allows the implementation to support more fine-grained sleep,
 > >  just does not require it to).
 > > =20
 > >  If we make the change you propose, we will become incompatible with
 > >  POSIX, as the latter requires ``sleep 10m'' to sleep for "at least
 > >  10 seconds".
 > As far as I understand any value bigger then 10s is "at least 10 seconds".
 > So 10m is "at least 10 seconds".
 > :-)
 > So, this IS compatible with POSIX
 >=20
 Nope.  "at least the integral number of seconds" is not the same as "at
 least the X seconds".  The point is to say that the implementation may
 choose to support non-integral intervals, as we do.
 
 
 Cheers,
 --=20
 Ruslan Ermilov		Sysadmin and DBA,
 ru@sunbay.com		Sunbay Software AG,
 ru@FreeBSD.org		FreeBSD committer,
 +380.652.512.251	Simferopol, Ukraine
 
 http://www.FreeBSD.org	The Power To Serve
 http://www.oracle.com	Enabling The Information Age
 
 --qcHopEYAB45HaUaB
 Content-Type: application/pgp-signature
 Content-Disposition: inline
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.0.7 (FreeBSD)
 
 iD8DBQE9WMSrUkv4P6juNwoRArgPAJ46iVsMCBq7n3BHEKCW6VZuqdacDgCfSbLT
 TIXZkOuwxezcSjRVeLr0ftg=
 =UYQu
 -----END PGP SIGNATURE-----
 
 --qcHopEYAB45HaUaB--
>Unformatted:
