duration.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  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. //kbuild:lib-$(CONFIG_SLEEP) += duration.o
  15. //kbuild:lib-$(CONFIG_TOP) += duration.o
  16. //kbuild:lib-$(CONFIG_TIMEOUT) += duration.o
  17. //kbuild:lib-$(CONFIG_PING) += duration.o
  18. //kbuild:lib-$(CONFIG_PING6) += duration.o
  19. //kbuild:lib-$(CONFIG_WATCH) += duration.o
  20. #include "libbb.h"
  21. static const struct suffix_mult duration_suffixes[] ALIGN_SUFFIX = {
  22. { "s", 1 },
  23. { "m", 60 },
  24. { "h", 60*60 },
  25. { "d", 24*60*60 },
  26. { "", 0 }
  27. };
  28. #if ENABLE_FLOAT_DURATION
  29. duration_t FAST_FUNC parse_duration_str(char *str)
  30. {
  31. duration_t duration;
  32. if (strchr(str, '.')) {
  33. double d;
  34. char *pp;
  35. int len;
  36. char sv;
  37. # if ENABLE_LOCALE_SUPPORT
  38. /* Undo busybox.c: on input, we want to use dot
  39. * as fractional separator in strtod(),
  40. * regardless of current locale
  41. */
  42. setlocale(LC_NUMERIC, "C");
  43. # endif
  44. len = strspn(str, "0123456789.");
  45. sv = str[len];
  46. str[len] = '\0';
  47. errno = 0;
  48. d = strtod(str, &pp);
  49. if (errno || *pp)
  50. bb_show_usage();
  51. str += len;
  52. *str-- = sv;
  53. sv = *str;
  54. *str = '1';
  55. duration = d * xatoul_sfx(str, duration_suffixes);
  56. *str = sv;
  57. } else {
  58. duration = xatoul_sfx(str, duration_suffixes);
  59. }
  60. return duration;
  61. }
  62. void FAST_FUNC sleep_for_duration(duration_t duration)
  63. {
  64. struct timespec ts;
  65. ts.tv_sec = MAXINT(typeof(ts.tv_sec));
  66. ts.tv_nsec = 0;
  67. if (duration >= 0 && duration < ts.tv_sec) {
  68. ts.tv_sec = duration;
  69. ts.tv_nsec = (duration - ts.tv_sec) * 1000000000;
  70. }
  71. /* NB: ENABLE_ASH_SLEEP requires that we do NOT loop on EINTR here:
  72. * otherwise, traps won't execute until we finish looping.
  73. */
  74. //do {
  75. // errno = 0;
  76. // nanosleep(&ts, &ts);
  77. //} while (errno == EINTR);
  78. nanosleep(&ts, &ts);
  79. }
  80. #else
  81. duration_t FAST_FUNC parse_duration_str(char *str)
  82. {
  83. return xatou_range_sfx(str, 0, UINT_MAX, duration_suffixes);
  84. }
  85. #endif