| /* vi: set sw=4 ts=4: */ |
| /* |
| * sleep implementation for busybox |
| * |
| * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> |
| * |
| * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
| */ |
| /* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) |
| * |
| * Rewritten to do proper arg and error checking. |
| * Also, added a 'fancy' configuration to accept multiple args with |
| * time suffixes for seconds, minutes, hours, and days. |
| */ |
| //config:config SLEEP |
| //config: bool "sleep" |
| //config: default y |
| //config: help |
| //config: sleep is used to pause for a specified number of seconds. |
| //config: It comes in 3 versions: |
| //config: - small: takes one integer parameter |
| //config: - fancy: takes multiple integer arguments with suffixes: |
| //config: sleep 1d 2h 3m 15s |
| //config: - fancy with fractional numbers: |
| //config: sleep 2.3s 4.5h sleeps for 16202.3 seconds |
| //config: Last one is "the most compatible" with coreutils sleep, |
| //config: but it adds around 1k of code. |
| //config: |
| //config:config FEATURE_FANCY_SLEEP |
| //config: bool "Enable multiple arguments and s/m/h/d suffixes" |
| //config: default y |
| //config: depends on SLEEP |
| //config: help |
| //config: Allow sleep to pause for specified minutes, hours, and days. |
| //config: |
| //config:config FEATURE_FLOAT_SLEEP |
| //config: bool "Enable fractional arguments" |
| //config: default y |
| //config: depends on FEATURE_FANCY_SLEEP |
| //config: help |
| //config: Allow for fractional numeric parameters. |
| |
| /* Do not make this applet NOFORK. It breaks ^C-ing of pauses in shells */ |
| //applet:IF_SLEEP(APPLET(sleep, BB_DIR_BIN, BB_SUID_DROP)) |
| |
| //kbuild:lib-$(CONFIG_SLEEP) += sleep.o |
| |
| /* BB_AUDIT SUSv3 compliant */ |
| /* BB_AUDIT GNU issues -- fancy version matches except args must be ints. */ |
| /* http://www.opengroup.org/onlinepubs/007904975/utilities/sleep.html */ |
| |
| //usage:#define sleep_trivial_usage |
| //usage: IF_FEATURE_FANCY_SLEEP("[") "N" IF_FEATURE_FANCY_SLEEP("]...") |
| //usage:#define sleep_full_usage "\n\n" |
| //usage: IF_NOT_FEATURE_FANCY_SLEEP("Pause for N seconds") |
| //usage: IF_FEATURE_FANCY_SLEEP( |
| //usage: "Pause for a time equal to the total of the args given, where each arg can\n" |
| //usage: "have an optional suffix of (s)econds, (m)inutes, (h)ours, or (d)ays") |
| //usage: |
| //usage:#define sleep_example_usage |
| //usage: "$ sleep 2\n" |
| //usage: "[2 second delay results]\n" |
| //usage: IF_FEATURE_FANCY_SLEEP( |
| //usage: "$ sleep 1d 3h 22m 8s\n" |
| //usage: "[98528 second delay results]\n") |
| |
| #include "libbb.h" |
| |
| #if ENABLE_FEATURE_FANCY_SLEEP || ENABLE_FEATURE_FLOAT_SLEEP |
| static const struct suffix_mult sfx[] = { |
| { "s", 1 }, |
| { "m", 60 }, |
| { "h", 60*60 }, |
| { "d", 24*60*60 }, |
| { "", 0 } |
| }; |
| #endif |
| |
| int sleep_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| int sleep_main(int argc UNUSED_PARAM, char **argv) |
| { |
| #if ENABLE_FEATURE_FLOAT_SLEEP |
| double duration; |
| struct timespec ts; |
| #else |
| unsigned duration; |
| #endif |
| |
| ++argv; |
| if (!*argv) |
| bb_show_usage(); |
| |
| #if ENABLE_FEATURE_FLOAT_SLEEP |
| |
| # if ENABLE_LOCALE_SUPPORT |
| /* undo busybox.c setlocale */ |
| setlocale(LC_NUMERIC, "C"); |
| # endif |
| duration = 0; |
| do { |
| char *arg = *argv; |
| if (strchr(arg, '.')) { |
| double d; |
| char *pp; |
| int len = strspn(arg, "0123456789."); |
| char sv = arg[len]; |
| arg[len] = '\0'; |
| errno = 0; |
| d = strtod(arg, &pp); |
| if (errno || *pp) |
| bb_show_usage(); |
| arg += len; |
| *arg-- = sv; |
| sv = *arg; |
| *arg = '1'; |
| duration += d * xatoul_sfx(arg, sfx); |
| *arg = sv; |
| } else { |
| duration += xatoul_sfx(arg, sfx); |
| } |
| } while (*++argv); |
| |
| ts.tv_sec = MAXINT(typeof(ts.tv_sec)); |
| ts.tv_nsec = 0; |
| if (duration >= 0 && duration < ts.tv_sec) { |
| ts.tv_sec = duration; |
| ts.tv_nsec = (duration - ts.tv_sec) * 1000000000; |
| } |
| do { |
| errno = 0; |
| nanosleep(&ts, &ts); |
| } while (errno == EINTR); |
| |
| #elif ENABLE_FEATURE_FANCY_SLEEP |
| |
| duration = 0; |
| do { |
| duration += xatou_range_sfx(*argv, 0, UINT_MAX - duration, sfx); |
| } while (*++argv); |
| sleep(duration); |
| |
| #else /* simple */ |
| |
| duration = xatou(*argv); |
| sleep(duration); |
| // Off. If it's really needed, provide example why |
| //if (sleep(duration)) { |
| // bb_perror_nomsg_and_die(); |
| //} |
| |
| #endif |
| |
| return EXIT_SUCCESS; |
| } |