Start 1.33.0 development cycle
[oweals/busybox.git] / libbb / duration.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Utility routines.
4  *
5  * Copyright (C) 2018 Denys Vlasenko
6  *
7  * Licensed under GPLv2, see file LICENSE in this source tree.
8  */
9 //config:config FLOAT_DURATION
10 //config:       bool "Enable fractional duration arguments"
11 //config:       default y
12 //config:       help
13 //config:       Allow sleep N.NNN, top -d N.NNN etc.
14
15 //kbuild:lib-$(CONFIG_SLEEP)   += duration.o
16 //kbuild:lib-$(CONFIG_TOP)     += duration.o
17 //kbuild:lib-$(CONFIG_TIMEOUT) += duration.o
18 //kbuild:lib-$(CONFIG_PING)    += duration.o
19 //kbuild:lib-$(CONFIG_PING6)   += duration.o
20 //kbuild:lib-$(CONFIG_WATCH)   += duration.o
21
22 #include "libbb.h"
23
24 static const struct suffix_mult duration_suffixes[] = {
25         { "s", 1 },
26         { "m", 60 },
27         { "h", 60*60 },
28         { "d", 24*60*60 },
29         { "", 0 }
30 };
31
32 #if ENABLE_FLOAT_DURATION
33 duration_t FAST_FUNC parse_duration_str(char *str)
34 {
35         duration_t duration;
36
37         if (strchr(str, '.')) {
38                 double d;
39                 char *pp;
40                 int len = strspn(str, "0123456789.");
41                 char sv = str[len];
42                 str[len] = '\0';
43                 errno = 0;
44                 d = strtod(str, &pp);
45                 if (errno || *pp)
46                         bb_show_usage();
47                 str += len;
48                 *str-- = sv;
49                 sv = *str;
50                 *str = '1';
51                 duration = d * xatoul_sfx(str, duration_suffixes);
52                 *str = sv;
53         } else {
54                 duration = xatoul_sfx(str, duration_suffixes);
55         }
56
57         return duration;
58 }
59 void FAST_FUNC sleep_for_duration(duration_t duration)
60 {
61         struct timespec ts;
62
63         ts.tv_sec = MAXINT(typeof(ts.tv_sec));
64         ts.tv_nsec = 0;
65         if (duration >= 0 && duration < ts.tv_sec) {
66                 ts.tv_sec = duration;
67                 ts.tv_nsec = (duration - ts.tv_sec) * 1000000000;
68         }
69         do {
70                 errno = 0;
71                 nanosleep(&ts, &ts);
72         } while (errno == EINTR);
73 }
74 #else
75 duration_t FAST_FUNC parse_duration_str(char *str)
76 {
77         return xatou_range_sfx(str, 0, UINT_MAX, duration_suffixes);
78 }
79 #endif