summaryrefslogtreecommitdiffstats
path: root/bin/sleep/sleep.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/sleep/sleep.c')
-rw-r--r--bin/sleep/sleep.c60
1 files changed, 56 insertions, 4 deletions
diff --git a/bin/sleep/sleep.c b/bin/sleep/sleep.c
index 74242c9..0083987 100644
--- a/bin/sleep/sleep.c
+++ b/bin/sleep/sleep.c
@@ -45,8 +45,11 @@ static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
+#include <ctype.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
+#include <time.h>
#include <unistd.h>
void usage __P((void));
@@ -56,22 +59,71 @@ main(argc, argv)
int argc;
char *argv[];
{
- int ch, secs;
+ struct timespec time_to_sleep;
+ long l;
+ int ch, neg;
+ char *p;
while ((ch = getopt(argc, argv, "")) != -1)
switch(ch) {
case '?':
default:
usage();
+ /* NOTREACHED */
}
argc -= optind;
argv += optind;
- if (argc != 1)
+ if (argc != 1) {
usage();
+ /* NOTREACHED */
+ }
+
+ p = argv[0];
+
+ /* Skip over leading whitespaces. */
+ while (isspace((unsigned char)*p))
+ ++p;
+
+ /* Check for optional `+' or `-' sign. */
+ neg = 0;
+ if (*p == '-') {
+ neg = 1;
+ ++p;
+ }
+ 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 (*p == '.') { /* Decimal point. */
+ l = 100000000L;
+ do {
+ if (isdigit((unsigned char)*++p))
+ time_to_sleep.tv_nsec += (*p - '0') * l;
+ else
+ break;
+ } while (l /= 10);
+ }
+
+ if (!neg && (time_to_sleep.tv_sec > 0 || time_to_sleep.tv_nsec > 0))
+ (void)nanosleep(&time_to_sleep, (struct timespec *)NULL);
- if ((secs = atoi(*argv)) > 0)
- (void)sleep(secs);
exit(0);
}
OpenPOWER on IntegriCloud