diff options
author | kib <kib@FreeBSD.org> | 2010-07-31 14:30:11 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2010-07-31 14:30:11 +0000 |
commit | 5895145874af81575fdde667d6d7d91dd3a66521 (patch) | |
tree | 46feeb8a6095d7ca3ec9d141ca969c46b69e528c /bin/sleep/sleep.c | |
parent | 27277244cd333006d5d010f8047d83a3a8a402c1 (diff) | |
download | FreeBSD-src-5895145874af81575fdde667d6d7d91dd3a66521.zip FreeBSD-src-5895145874af81575fdde667d6d7d91dd3a66521.tar.gz |
Report the time left for the sleep on SIGINFO.
Be stricter in the checking of interval specification.
PR: bin/139345
MFC after: 3 weeks
Diffstat (limited to 'bin/sleep/sleep.c')
-rw-r--r-- | bin/sleep/sleep.c | 66 |
1 files changed, 47 insertions, 19 deletions
diff --git a/bin/sleep/sleep.c b/bin/sleep/sleep.c index f38b183..a573cb5 100644 --- a/bin/sleep/sleep.c +++ b/bin/sleep/sleep.c @@ -42,26 +42,34 @@ 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 <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; + long l, original; int neg; char *p; - if (argc != 2) { + if (argc != 2) usage(); - return(1); - } p = argv[1]; @@ -74,10 +82,8 @@ main(int argc, char *argv[]) if (*p == '-') { neg = 1; ++p; - if (!isdigit((unsigned char)*p) && *p != '.') { + if (!isdigit((unsigned char)*p) && *p != '.') usage(); - return(1); - } } else if (*p == '+') ++p; @@ -85,13 +91,13 @@ main(int argc, char *argv[]) /* 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. - */ + + /* + * Avoid overflow when `seconds' is huge. This assumes + * that the maximum value for a time_t is <= INT_MAX. + */ + if (l > INT_MAX) l = INT_MAX; - } } else l = 0; time_to_sleep.tv_sec = (time_t)l; @@ -110,16 +116,38 @@ main(int argc, char *argv[]) } while (l); } - if (!neg && (time_to_sleep.tv_sec > 0 || time_to_sleep.tv_nsec > 0)) - (void)nanosleep(&time_to_sleep, (struct timespec *)NULL); + /* Skip over the trailing whitespace. */ + while (isspace((unsigned char)*p)) + ++p; + if (*p != '\0') + usage(); + + signal(SIGINFO, report_request); + if (!neg && (time_to_sleep.tv_sec > 0 || time_to_sleep.tv_nsec > 0)) { + original = time_to_sleep.tv_sec; + while (nanosleep(&time_to_sleep, &time_to_sleep) != 0) { + if (report_requested) { + /* + * Reporting does not bother with + * fractions of a second... + */ + warnx("about %ld second(s) left" + " out of the original %ld", + time_to_sleep.tv_sec, original); + report_requested = 0; + } else + break; + } + } - return(0); + return (0); } -void +static void usage(void) { - const char msg[] = "usage: sleep seconds\n"; + static const char msg[] = "usage: sleep seconds\n"; write(STDERR_FILENO, msg, sizeof(msg) - 1); + exit(1); } |