busybox/libbb/duration.c
<<
>>
Prefs
   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
  24static const struct suffix_mult duration_suffixes[] ALIGN_SUFFIX = {
  25        { "s", 1 },
  26        { "m", 60 },
  27        { "h", 60*60 },
  28        { "d", 24*60*60 },
  29        { "", 0 }
  30};
  31
  32#if ENABLE_FLOAT_DURATION
  33duration_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;
  41                char sv;
  42
  43# if ENABLE_LOCALE_SUPPORT
  44                /* Undo busybox.c: on input, we want to use dot
  45                 * as fractional separator in strtod(),
  46                 * regardless of current locale
  47                 */
  48                setlocale(LC_NUMERIC, "C");
  49# endif
  50                len = strspn(str, "0123456789.");
  51                sv = str[len];
  52                str[len] = '\0';
  53                errno = 0;
  54                d = strtod(str, &pp);
  55                if (errno || *pp)
  56                        bb_show_usage();
  57                str += len;
  58                *str-- = sv;
  59                sv = *str;
  60                *str = '1';
  61                duration = d * xatoul_sfx(str, duration_suffixes);
  62                *str = sv;
  63        } else {
  64                duration = xatoul_sfx(str, duration_suffixes);
  65        }
  66
  67        return duration;
  68}
  69void FAST_FUNC sleep_for_duration(duration_t duration)
  70{
  71        struct timespec ts;
  72
  73        ts.tv_sec = MAXINT(typeof(ts.tv_sec));
  74        ts.tv_nsec = 0;
  75        if (duration >= 0 && duration < ts.tv_sec) {
  76                ts.tv_sec = duration;
  77                ts.tv_nsec = (duration - ts.tv_sec) * 1000000000;
  78        }
  79        do {
  80                errno = 0;
  81                nanosleep(&ts, &ts);
  82        } while (errno == EINTR);
  83}
  84#else
  85duration_t FAST_FUNC parse_duration_str(char *str)
  86{
  87        return xatou_range_sfx(str, 0, UINT_MAX, duration_suffixes);
  88}
  89#endif
  90