sleep: if FANCY && DESKTOP, support fractional seconds, minutes, hours and so on. It's coreutils compat. bloatcheck is atrocious :(
No binary (build failed)
—
(log yok)
| @@ -36,28 +36,69 @@ static const struct suffix_mult sfx[] = { | |
| int sleep_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |
| int sleep_main(int argc UNUSED_PARAM, char **argv) | |
| { | |
| + | #if ENABLE_FEATURE_FANCY_SLEEP && ENABLE_DESKTOP |
| + | double duration; |
| + | struct timespec ts; |
| + | #else |
| unsigned duration; | |
| + | #endif |
| ++argv; | |
| if (!*argv) | |
| bb_show_usage(); | |
| - | #if ENABLE_FEATURE_FANCY_SLEEP |
| + | #if ENABLE_FEATURE_FANCY_SLEEP && ENABLE_DESKTOP |
| duration = 0; | |
| do { | |
| - | duration += xatoul_range_sfx(*argv, 0, UINT_MAX-duration, sfx); |
| + | char *arg = *argv; |
| + | if (strchr(arg, '.')) { |
| + | double d; |
| + | int len = strspn(arg, "0123456789."); |
| + | char sv = arg[len]; |
| + | arg[len] = '\0'; |
| + | d = bb_strtod(arg, NULL); |
| + | if (errno) |
| + | bb_show_usage(); |
| + | arg[len] = sv; |
| + | len--; |
| + | sv = arg[len]; |
| + | arg[len] = '1'; |
| + | duration += d * xatoul_sfx(&arg[len], sfx); |
| + | arg[len] = sv; |
| + | } else |
| + | duration += xatoul_sfx(arg, sfx); |
| } while (*++argv); | |
| - | #else /* FEATURE_FANCY_SLEEP */ |
| + | 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); |
| - | duration = xatou(*argv); |
| + | #elif ENABLE_FEATURE_FANCY_SLEEP |
| - | #endif /* FEATURE_FANCY_SLEEP */ |
| + | duration = 0; |
| + | do { |
| + | duration += xatou_range_sfx(*argv, 0, UINT_MAX - duration, sfx); |
| + | } while (*++argv); |
| + | sleep(duration); |
| - | if (sleep(duration)) { |
| - | bb_perror_nomsg_and_die(); |
| - | } |
| + | #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; | |
| } | |
| @@ -169,7 +169,7 @@ uint32_t bb_strtou32(const char *arg, char **endp, int base) | |
| /* Floating point */ | |
| - | /* double bb_strtod(const char *arg, char **endp); */ |
| + | double bb_strtod(const char *arg, char **endp) FAST_FUNC; |
| #if __GNUC_PREREQ(4,1) | |
| # pragma GCC visibility pop | |
| @@ -13,6 +13,7 @@ lib-y += bb_basename.o | |
| lib-y += bb_do_delay.o | |
| lib-y += bb_pwd.o | |
| lib-y += bb_qsort.o | |
| + | lib-y += bb_strtod.o |
| lib-y += bb_strtonum.o | |
| lib-y += change_identity.o | |
| lib-y += chomp.o | |
| @@ -0,0 +1,85 @@ | |
| + | /* vi: set sw=4 ts=4: */ |
| + | /* |
| + | * Utility routines. |
| + | * |
| + | * Copyright (C) 1999-2004 by Erik Andersen <[email protected]> |
| + | * |
| + | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
| + | */ |
| + | |
| + | #include "libbb.h" |
| + | #include <math.h> /* just for HUGE_VAL */ |
| + | |
| + | #define NOT_DIGIT(a) (((unsigned char)(a-'0')) > 9) |
| + | |
| + | double FAST_FUNC bb_strtod(const char *arg, char **endp) |
| + | { |
| + | double v; |
| + | char *endptr; |
| + | |
| + | if (arg[0] != '-' && NOT_DIGIT(arg[0])) |
| + | goto err; |
| + | errno = 0; |
| + | v = strtod(arg, &endptr); |
| + | if (endp) |
| + | *endp = endptr; |
| + | if (endptr[0]) { |
| + | /* "1234abcg" or out-of-range? */ |
| + | if (isalnum(endptr[0]) || errno) { |
| + | err: |
| + | errno = ERANGE; |
| + | return HUGE_VAL; |
| + | } |
| + | /* good number, just suspicious terminator */ |
| + | errno = EINVAL; |
| + | } |
| + | return v; |
| + | } |
| + | |
| + | #if 0 |
| + | /* String to timespec: "NNNN[.NNNNN]" -> struct timespec. |
| + | * Can be used for other fixed-point needs. |
| + | * Returns pointer past last converted char, |
| + | * and returns errno similar to bb_strtoXX functions. |
| + | */ |
| + | char* FAST_FUNC bb_str_to_ts(struct timespec *ts, const char *arg) |
| + | { |
| + | if (sizeof(ts->tv_sec) <= sizeof(int)) |
| + | ts->tv_sec = bb_strtou(arg, &arg, 10); |
| + | else if (sizeof(ts->tv_sec) <= sizeof(long)) |
| + | ts->tv_sec = bb_strtoul(arg, &arg, 10); |
| + | else |
| + | ts->tv_sec = bb_strtoull(arg, &arg, 10); |
| + | ts->tv_nsec = 0; |
| + | |
| + | if (*arg != '.') |
| + | return arg; |
| + | |
| + | /* !EINVAL: number is not ok (alphanumeric ending, overflow etc) */ |
| + | if (errno != EINVAL) |
| + | return arg; |
| + | |
| + | if (!*++arg) /* "NNN." */ |
| + | return arg; |
| + | |
| + | { /* "NNN.xxx" - parse xxx */ |
| + | int ndigits; |
| + | char *p; |
| + | char buf[10]; /* we never use more than 9 digits */ |
| + | |
| + | /* Need to make a copy to avoid false overflow */ |
| + | safe_strncpy(buf, arg, 10); |
| + | ts->tv_nsec = bb_strtou(buf, &p, 10); |
| + | ndigits = p - buf; |
| + | arg += ndigits; |
| + | /* normalize to nsec */ |
| + | while (ndigits < 9) { |
| + | ndigits++; |
| + | ts->tv_nsec *= 10; |
| + | } |
| + | while (isdigit(*arg)) /* skip possible 10th plus digits */ |
| + | arg++; |
| + | } |
| + | return arg; |
| + | } |
| + | #endif |
| @@ -124,33 +124,3 @@ int FAST_FUNC bb_strtoi(const char *arg, char **endp, int base) | |
| return handle_errors(v, endp, endptr); | |
| } | |
| #endif | |
| - | |
| - | /* Floating point */ |
| - | |
| - | #if 0 |
| - | |
| - | #include <math.h> /* just for HUGE_VAL */ |
| - | #define NOT_DIGIT(a) (((unsigned char)(a-'0')) > 9) |
| - | double FAST_FUNC bb_strtod(const char *arg, char **endp) |
| - | { |
| - | double v; |
| - | char *endptr; |
| - | |
| - | if (arg[0] != '-' && NOT_DIGIT(arg[0])) goto err; |
| - | errno = 0; |
| - | v = strtod(arg, &endptr); |
| - | if (endp) *endp = endptr; |
| - | if (endptr[0]) { |
| - | /* "1234abcg" or out-of-range? */ |
| - | if (isalnum(endptr[0]) || errno) { |
| - | err: |
| - | errno = ERANGE; |
| - | return HUGE_VAL; |
| - | } |
| - | /* good number, just suspicious terminator */ |
| - | errno = EINVAL; |
| - | } |
| - | return v; |
| - | } |
| - | |
| - | #endif |