| /* vi: set sw=4 ts=4: */ |
| /* |
| * Utility routines. |
| * |
| * Copyright (C) 2018 Denys Vlasenko |
| * |
| * Licensed under GPLv2, see file LICENSE in this source tree. |
| */ |
| //config:config FLOAT_DURATION |
| //config: bool "Enable fractional duration arguments" |
| //config: default y |
| //config: help |
| //config: Allow sleep N.NNN, top -d N.NNN etc. |
| |
| //kbuild:lib-$(CONFIG_SLEEP) += duration.o |
| //kbuild:lib-$(CONFIG_TOP) += duration.o |
| //kbuild:lib-$(CONFIG_TIMEOUT) += duration.o |
| //kbuild:lib-$(CONFIG_PING) += duration.o |
| //kbuild:lib-$(CONFIG_PING6) += duration.o |
| //kbuild:lib-$(CONFIG_WATCH) += duration.o |
| |
| #include "libbb.h" |
| |
| static const struct suffix_mult duration_suffixes[] ALIGN_SUFFIX = { |
| { "s", 1 }, |
| { "m", 60 }, |
| { "h", 60*60 }, |
| { "d", 24*60*60 }, |
| { "", 0 } |
| }; |
| |
| #if ENABLE_FLOAT_DURATION |
| duration_t FAST_FUNC parse_duration_str(char *str) |
| { |
| duration_t duration; |
| |
| if (strchr(str, '.')) { |
| double d; |
| char *pp; |
| int len = strspn(str, "0123456789."); |
| char sv = str[len]; |
| str[len] = '\0'; |
| errno = 0; |
| d = strtod(str, &pp); |
| if (errno || *pp) |
| bb_show_usage(); |
| str += len; |
| *str-- = sv; |
| sv = *str; |
| *str = '1'; |
| duration = d * xatoul_sfx(str, duration_suffixes); |
| *str = sv; |
| } else { |
| duration = xatoul_sfx(str, duration_suffixes); |
| } |
| |
| return duration; |
| } |
| void FAST_FUNC sleep_for_duration(duration_t duration) |
| { |
| struct timespec ts; |
| |
| 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); |
| } |
| #else |
| duration_t FAST_FUNC parse_duration_str(char *str) |
| { |
| return xatou_range_sfx(str, 0, UINT_MAX, duration_suffixes); |
| } |
| #endif |