aboutsummaryrefslogtreecommitdiff
path: root/libbb/duration.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbb/duration.c')
-rw-r--r--libbb/duration.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/libbb/duration.c b/libbb/duration.c
new file mode 100644
index 000000000..765a1e9fe
--- /dev/null
+++ b/libbb/duration.c
@@ -0,0 +1,76 @@
+/* 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
+
+#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(*argv, 0, UINT_MAX, duration_suffixes);
+}
+#endif