With the attached, sleep supports the subtraction of amounts, e.g.

  $ sleep -- 1d -10m

as discussed in http://bugs.gnu.org/7877#67.

Please keep a special eye on the new test during the review:
it might be racy, but at least it's a start for discussion.

Thanks & have a nice day,
Berny
>From 724a7699b4b6c9d1d359afc5e4f4945a29b146f7 Mon Sep 17 00:00:00 2001
From: Bernhard Voelker <[email protected]>
Date: Wed, 30 Jul 2014 00:40:19 +0200
Subject: [PATCH] sleep: support subtraction of sleep amounts

* src/sleep.c (main): Check for non-negative sleep amount for the
resulting total only instead of for each individual argument.
* tests/misc/sleep.sh: New file.
* tests/local.mk (all_tests): Add it.
* doc/coreutils.texi (sleep invocation): Add an example.
* NEWS (Improvements): Mention the change.

Discussed in http://bugs.gnu.org/7877#67

Conflicts:
	NEWS
---
 NEWS                |  4 ++++
 doc/coreutils.texi  |  5 ++++
 src/sleep.c         |  8 +++++--
 tests/local.mk      |  1 +
 tests/misc/sleep.sh | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 84 insertions(+), 2 deletions(-)
 create mode 100755 tests/misc/sleep.sh

diff --git a/NEWS b/NEWS
index 511e626..3760b24 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,10 @@ GNU coreutils NEWS                                    -*- outline -*-
 
 * Noteworthy changes in release ?.? (????-??-??) [?]
 
+** Improvements
+
+  sleep now supports subtraction of sleep amounts among arguments.
+
 
 * Noteworthy changes in release 8.23 (2014-07-18) [stable]
 
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index 19a523d..141665c 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -16855,6 +16855,11 @@ Historical implementations of @command{sleep} have required that
 without a suffix.  However, GNU @command{sleep} accepts
 arbitrary floating point numbers.  @xref{Floating point}.
 
+The following example shows how to sleep 10 minutes less than a day:
+@example
+$ sleep -- 1d -10m
+@end example
+
 The only options are @option{--help} and @option{--version}.  @xref{Common
 options}.
 
diff --git a/src/sleep.c b/src/sleep.c
index e24c251..6038fe5 100644
--- a/src/sleep.c
+++ b/src/sleep.c
@@ -125,8 +125,6 @@ main (int argc, char **argv)
       double s;
       const char *p;
       if (! xstrtod (argv[i], &p, &s, c_strtod)
-          /* Nonnegative interval.  */
-          || ! (0 <= s)
           /* No extra chars after the number and an optional s,m,h,d char.  */
           || (*p && *(p+1))
           /* Check any suffix char and update S based on the suffix.  */
@@ -139,6 +137,12 @@ main (int argc, char **argv)
       seconds += s;
     }
 
+  if (seconds < 0)
+    {
+      error (0, 0, _("negative total sleep time %f"), seconds);
+      ok = false;
+    }
+
   if (!ok)
     usage (EXIT_FAILURE);
 
diff --git a/tests/local.mk b/tests/local.mk
index e0f1f84..2d4060c 100644
--- a/tests/local.mk
+++ b/tests/local.mk
@@ -318,6 +318,7 @@ all_tests =					\
   tests/misc/shred-negative.sh			\
   tests/misc/shred-passes.sh			\
   tests/misc/shred-remove.sh			\
+  tests/misc/sleep.sh				\
   tests/misc/shuf.sh				\
   tests/misc/shuf-reservoir.sh			\
   tests/misc/sort.pl				\
diff --git a/tests/misc/sleep.sh b/tests/misc/sleep.sh
new file mode 100755
index 0000000..fb00992
--- /dev/null
+++ b/tests/misc/sleep.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+# Exercise sleep summing up and subtracting arguments.
+
+# Copyright (C) 2014 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ sleep
+
+do_sleep ()
+{
+  t=$1    # timeout
+  exp=$2  # expected exit code
+  shift 2 || framework_failure_
+  timeout $t env sleep -- "$@"
+  test $? = $exp
+}
+
+# Check that sleep sums up the arguments.
+do_sleep .3   0 .01 || fail=1
+do_sleep .3 124 .01 2 || fail=1
+do_sleep .3 124 .09 .01 2 || fail=1
+
+# Check that subtracting works.
+do_sleep .3   0 1m -59.99s || fail=1
+do_sleep .5 124 1m -59s || fail=1
+
+# Check that subtracting works with more arguments.
+do_sleep .3   0 1d -23h -59m -59.99s || fail=1
+do_sleep .5 124 1d -23h -59m -59s || fail=1
+
+# Check that subtracting works starting with a negative number.
+do_sleep .3   0 -1d 24h .01 || fail=1
+
+# Do not allow negative sleep time.
+cat <<\EOF > exp || fail=1
+sleep: negative total sleep time -1.000000
+Try 'sleep --help' for more information.
+EOF
+
+env sleep -- -1 >out 2>err && fail=1
+compare /dev/null out || fail=1
+compare exp err || fail=1
+rm -f out err || framework_failure_
+
+env sleep -- 1m -61s >out 2>err && fail=1
+compare /dev/null out || fail=1
+compare exp err || fail=1
+rm -f out err || framework_failure_
+
+env sleep -- 1d -23h -59m -61s >out 2>err && fail=1
+compare /dev/null out || fail=1
+compare exp err || fail=1
+rm -f out err || framework_failure_
+
+Exit $fail
-- 
1.8.4.5

Reply via email to