summaryrefslogtreecommitdiffstats
path: root/bin/sleep/sleep.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2010-07-31 14:30:11 +0000
committerkib <kib@FreeBSD.org>2010-07-31 14:30:11 +0000
commit5895145874af81575fdde667d6d7d91dd3a66521 (patch)
tree46feeb8a6095d7ca3ec9d141ca969c46b69e528c /bin/sleep/sleep.c
parent27277244cd333006d5d010f8047d83a3a8a402c1 (diff)
downloadFreeBSD-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.c66
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);
}
OpenPOWER on IntegriCloud