vi: fixes to string search in colon commands, closes 10321
[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
21 #include "libbb.h"
22
23 static const struct suffix_mult duration_suffixes[] = {
24         { "s", 1 },
25         { "m", 60 },
26         { "h", 60*60 },
27         { "d", 24*60*60 },
28         { "", 0 }
29 };
30
31 #if ENABLE_FLOAT_DURATION
32 duration_t FAST_FUNC parse_duration_str(char *str)
33 {
34         duration_t duration;
35
36         if (strchr(str, '.')) {
37                 double d;
38                 char *pp;
39                 int len = strspn(str, "0123456789.");
40                 char sv = str[len];
41                 str[len] = '\0';
42                 errno = 0;
43                 d = strtod(str, &pp);
44                 if (errno || *pp)
45                         bb_show_usage();
46                 str += len;
47                 *str-- = sv;
48                 sv = *str;
49                 *str = '1';
50                 duration = d * xatoul_sfx(str, duration_suffixes);
51                 *str = sv;
52         } else {
53                 duration = xatoul_sfx(str, duration_suffixes);
54         }
55
56         return duration;
57 }
58 void FAST_FUNC sleep_for_duration(duration_t duration)
59 {
60         struct timespec ts;
61
62         ts.tv_sec = MAXINT(typeof(ts.tv_sec));
63         ts.tv_nsec = 0;
64         if (duration >= 0 && duration < ts.tv_sec) {
65                 ts.tv_sec = duration;
66                 ts.tv_nsec = (duration - ts.tv_sec) * 1000000000;
67         }
68         do {
69                 errno = 0;
70                 nanosleep(&ts, &ts);
71         } while (errno == EINTR);
72 }
73 #else
74 duration_t FAST_FUNC parse_duration_str(char *str)
75 {
76         return xatou_range_sfx(str, 0, UINT_MAX, duration_suffixes);
77 }
78 #endif