- Add support for floating pointer numbers,
  which you will find in other implementations.

- Add support for suffixes [s|m|h|d], as
  found in GNU sleep, which is very useful.

- Add support for multiple arguments. Not
  really necessary, but brings compatibility
  at barely any cost.

Signed-off-by: Mattias Andrée <[email protected]>
---
 sleep.1 | 27 +++++++++++++++++-----
 sleep.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 92 insertions(+), 14 deletions(-)

diff --git a/sleep.1 b/sleep.1
index 2b78bfb..66c71c0 100644
--- a/sleep.1
+++ b/sleep.1
@@ -1,22 +1,37 @@
-.Dd 2015-10-08
+.Dd 2016-03-26
 .Dt SLEEP 1
 .Os sbase
 .Sh NAME
 .Nm sleep
-.Nd wait for a number of seconds
+.Nd wait for a specified amount of time
 .Sh SYNOPSIS
 .Nm
-.Ar num
+.Ar num[suffix] ...
 .Sh DESCRIPTION
 .Nm
-waits for
+waits for the sum of all
+.Ar num[suffix]
+to elapse.
+.Pp
+.Ar suffix
+may be either
+\fBs\fP for seconds (default),
+\fBm\fP for minutes,
+\fBh\fP for hours, or
+\fBd\fP for days.
+.Pp
 .Ar num
-seconds to elapse.
+may be a floating point number.
 .Sh SEE ALSO
-.Xr sleep 3
+.Xr sleep 3 ,
+.Xr nanosleep 3
 .Sh STANDARDS
 The
 .Nm
 utility is compliant with the
 .St -p1003.1-2013
 specification.
+.Ar suffix ,
+multiple arguments, and
+floatomg point number support
+are extension to that standard.
diff --git a/sleep.c b/sleep.c
index b1028ed..693ce88 100644
--- a/sleep.c
+++ b/sleep.c
@@ -1,27 +1,90 @@
 /* See LICENSE file for copyright and license details. */
-#include <unistd.h>
+#include <ctype.h>
+#include <string.h>
+#include <time.h>
 
 #include "util.h"
 
+#ifndef TIME_MAX
+# define TIME_MAX ((time_t)~0 ^ ((time_t)1 << (8 * sizeof(time_t) - 1)))
+#endif
+
 static void
 usage(void)
 {
-       eprintf("usage: %s num\n", argv0);
+       eprintf("usage: %s num[s|m|h|d] ...\n", argv0);
+}
+
+static char *
+strtotime(char *str, struct timespec *ts)
+{
+       char *p = str, *suf, c;
+       char buf[10];
+       size_t n;
+
+       while (isdigit(*p))
+               p++;
+       suf = p + (*p == '.');
+       while (isdigit(*suf))
+               suf++;
+
+       c = *suf;
+       *suf = *p = '\0';
+
+       ts->tv_sec = estrtonum(str, 0, TIME_MAX);
+
+       if (p++ != suf) {
+               n = strlen(p);
+               n = n < 9 ? n : 9;
+               memcpy(buf, p, n);
+               memset(buf + n, '0', 9 - n);
+               buf[9] = '\0';
+               ts->tv_nsec = estrtonum(buf, 0, 999999999L);
+       } else {
+               ts->tv_nsec = 0;
+       }
+
+       *suf = c;
+       return suf;
+       
+}
+
+static int
+parsesuffix(char *suf)
+{
+       int n = 1;
+       if (!strcmp(suf, "m"))
+               n = 60;
+       else if (!strcmp(suf, "h"))
+               n = 60 * 60;
+       else if (!strcmp(suf, "d"))
+               n = 60 * 60 * 24;
+       else if (*suf && strcmp(suf, "s"))
+               eprintf("%s: invalid suffix\n");
+       return n;
 }
 
 int
 main(int argc, char *argv[])
 {
-       unsigned seconds;
+       struct timespec dur, rem;
+       int n;
 
-       argv0 = argv[0], argc--, argv++;
+       ARGBEGIN {
+       default:
+               usage();
+       } ARGEND
 
-       if (argc != 1)
+       if (!argc)
                usage();
 
-       seconds = estrtonum(argv[0], 0, UINT_MAX);
-       while ((seconds = sleep(seconds)) > 0)
-               ;
+       for (; argc; argc--, argv++) {
+               n = parsesuffix(strtotime(*argv, &dur));
+               while (n--) {
+                       rem = dur;
+                       while (nanosleep(&rem, &rem) < 0);
+               }
+       }
 
        return 0;
 }
-- 
2.7.3


Reply via email to