diff options
| author | Konstantin Belousov <kib@FreeBSD.org> | 2010-08-21 08:49:53 +0000 |
|---|---|---|
| committer | Konstantin Belousov <kib@FreeBSD.org> | 2010-08-21 08:49:53 +0000 |
| commit | ac86626fa5a1023b9e6a0532f56f2bc4da008aea (patch) | |
| tree | 78be88fe298091434b070d930684b80f4af01992 /bin | |
| parent | 74d5adc0cde72a69feeea13fa7171a35f90f2849 (diff) | |
Notes
Diffstat (limited to 'bin')
| -rw-r--r-- | bin/sleep/sleep.1 | 13 | ||||
| -rw-r--r-- | bin/sleep/sleep.c | 97 |
2 files changed, 44 insertions, 66 deletions
diff --git a/bin/sleep/sleep.1 b/bin/sleep/sleep.1 index bc56dbf6471b..5dad81ad9ee7 100644 --- a/bin/sleep/sleep.1 +++ b/bin/sleep/sleep.1 @@ -51,6 +51,10 @@ suspends execution for a minimum of If the .Nm command receives a signal, it takes the standard action. +When the +.Dv SIGINFO +signal is received, the estimate of the amount of seconds left to +sleep is printed on the standard output. .Sh IMPLEMENTATION NOTES The .Dv SIGALRM @@ -58,14 +62,11 @@ signal is not handled specially by this implementation. .Pp The .Nm -command will accept and honor a non-integer number of specified seconds -(with a -.Ql .\& -character as a decimal point). -.Bf Sy +command allows and honors a non-integer number of seconds to sleep +in any form acceptable by +.Xr strtod 3 . This is a non-portable extension, and its use will nearly guarantee that a shell script will not execute properly on another system. -.Ef .Sh EXIT STATUS .Ex -std .Sh EXAMPLES diff --git a/bin/sleep/sleep.c b/bin/sleep/sleep.c index f38b183cb2bf..fa7deb2f5ca5 100644 --- a/bin/sleep/sleep.c +++ b/bin/sleep/sleep.c @@ -42,84 +42,61 @@ static char sccsid[] = "@(#)sleep.c 8.3 (Berkeley) 4/2/94"; __FBSDID("$FreeBSD$"); #include <ctype.h> +#include <err.h> #include <limits.h> +#include <signal.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <time.h> -#include <unistd.h> -void usage(void); +static void usage(void); + +static volatile sig_atomic_t report_requested; +static void +report_request(int signo __unused) +{ + + report_requested = 1; +} int main(int argc, char *argv[]) { struct timespec time_to_sleep; - long l; - int neg; - char *p; + double d; + time_t original; + char buf[2]; - if (argc != 2) { + if (argc != 2) usage(); - return(1); - } - - p = argv[1]; - - /* Skip over leading whitespaces. */ - while (isspace((unsigned char)*p)) - ++p; - /* Check for optional `+' or `-' sign. */ - neg = 0; - if (*p == '-') { - neg = 1; - ++p; - if (!isdigit((unsigned char)*p) && *p != '.') { - usage(); - return(1); - } - } - 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 (sscanf(argv[1], "%lf%1s", &d, buf) != 1) + usage(); + if (d > INT_MAX) + usage(); + if (d <= 0) + return (0); + original = time_to_sleep.tv_sec = (time_t)d; + time_to_sleep.tv_nsec = 1e9 * (d - time_to_sleep.tv_sec); - if (*p == '.') { /* Decimal point. */ - l = 100000000L; - do { - if (isdigit((unsigned char)*++p)) - time_to_sleep.tv_nsec += (*p - '0') * l; - else - break; - l /= 10; - } while (l); + signal(SIGINFO, report_request); + while (nanosleep(&time_to_sleep, &time_to_sleep) != 0) { + if (report_requested) { + /* Reporting does not bother with nanoseconds. */ + warnx("about %d second(s) left out of the original %d", + (int)time_to_sleep.tv_sec, (int)original); + report_requested = 0; + } else + break; } - - if (!neg && (time_to_sleep.tv_sec > 0 || time_to_sleep.tv_nsec > 0)) - (void)nanosleep(&time_to_sleep, (struct timespec *)NULL); - - return(0); + return (0); } -void +static void usage(void) { - const char msg[] = "usage: sleep seconds\n"; - write(STDERR_FILENO, msg, sizeof(msg) - 1); + fprintf(stderr, "usage: sleep seconds\n"); + exit(1); } |
