| /* 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 | |
| #include "libbb.h" | |
| static const struct suffix_mult duration_suffixes[] = { | |
| { "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 |