sleep.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * sleep implementation for busybox
  4. *
  5. * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
  6. *
  7. * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  8. */
  9. /* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
  10. *
  11. * Rewritten to do proper arg and error checking.
  12. * Also, added a 'fancy' configuration to accept multiple args with
  13. * time suffixes for seconds, minutes, hours, and days.
  14. */
  15. //config:config SLEEP
  16. //config: bool "sleep"
  17. //config: default y
  18. //config: help
  19. //config: sleep is used to pause for a specified number of seconds.
  20. //config: It comes in 3 versions:
  21. //config: - small: takes one integer parameter
  22. //config: - fancy: takes multiple integer arguments with suffixes:
  23. //config: sleep 1d 2h 3m 15s
  24. //config: - fancy with fractional numbers:
  25. //config: sleep 2.3s 4.5h sleeps for 16202.3 seconds
  26. //config: Last one is "the most compatible" with coreutils sleep,
  27. //config: but it adds around 1k of code.
  28. //config:
  29. //config:config FEATURE_FANCY_SLEEP
  30. //config: bool "Enable multiple arguments and s/m/h/d suffixes"
  31. //config: default y
  32. //config: depends on SLEEP
  33. //config: help
  34. //config: Allow sleep to pause for specified minutes, hours, and days.
  35. //config:
  36. //config:config FEATURE_FLOAT_SLEEP
  37. //config: bool "Enable fractional arguments"
  38. //config: default y
  39. //config: depends on FEATURE_FANCY_SLEEP
  40. //config: help
  41. //config: Allow for fractional numeric parameters.
  42. /* Do not make this applet NOFORK. It breaks ^C-ing of pauses in shells */
  43. //applet:IF_SLEEP(APPLET(sleep, BB_DIR_BIN, BB_SUID_DROP))
  44. //kbuild:lib-$(CONFIG_SLEEP) += sleep.o
  45. /* BB_AUDIT SUSv3 compliant */
  46. /* BB_AUDIT GNU issues -- fancy version matches except args must be ints. */
  47. /* http://www.opengroup.org/onlinepubs/007904975/utilities/sleep.html */
  48. //usage:#define sleep_trivial_usage
  49. //usage: IF_FEATURE_FANCY_SLEEP("[") "N" IF_FEATURE_FANCY_SLEEP("]...")
  50. //usage:#define sleep_full_usage "\n\n"
  51. //usage: IF_NOT_FEATURE_FANCY_SLEEP("Pause for N seconds")
  52. //usage: IF_FEATURE_FANCY_SLEEP(
  53. //usage: "Pause for a time equal to the total of the args given, where each arg can\n"
  54. //usage: "have an optional suffix of (s)econds, (m)inutes, (h)ours, or (d)ays")
  55. //usage:
  56. //usage:#define sleep_example_usage
  57. //usage: "$ sleep 2\n"
  58. //usage: "[2 second delay results]\n"
  59. //usage: IF_FEATURE_FANCY_SLEEP(
  60. //usage: "$ sleep 1d 3h 22m 8s\n"
  61. //usage: "[98528 second delay results]\n")
  62. #include "libbb.h"
  63. #if ENABLE_FEATURE_FANCY_SLEEP || ENABLE_FEATURE_FLOAT_SLEEP
  64. static const struct suffix_mult sfx[] = {
  65. { "s", 1 },
  66. { "m", 60 },
  67. { "h", 60*60 },
  68. { "d", 24*60*60 },
  69. { "", 0 }
  70. };
  71. #endif
  72. int sleep_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  73. int sleep_main(int argc UNUSED_PARAM, char **argv)
  74. {
  75. #if ENABLE_FEATURE_FLOAT_SLEEP
  76. double duration;
  77. struct timespec ts;
  78. #else
  79. unsigned duration;
  80. #endif
  81. ++argv;
  82. if (!*argv)
  83. bb_show_usage();
  84. #if ENABLE_FEATURE_FLOAT_SLEEP
  85. # if ENABLE_LOCALE_SUPPORT
  86. /* undo busybox.c setlocale */
  87. setlocale(LC_NUMERIC, "C");
  88. # endif
  89. duration = 0;
  90. do {
  91. char *arg = *argv;
  92. if (strchr(arg, '.')) {
  93. double d;
  94. char *pp;
  95. int len = strspn(arg, "0123456789.");
  96. char sv = arg[len];
  97. arg[len] = '\0';
  98. errno = 0;
  99. d = strtod(arg, &pp);
  100. if (errno || *pp)
  101. bb_show_usage();
  102. arg += len;
  103. *arg-- = sv;
  104. sv = *arg;
  105. *arg = '1';
  106. duration += d * xatoul_sfx(arg, sfx);
  107. *arg = sv;
  108. } else {
  109. duration += xatoul_sfx(arg, sfx);
  110. }
  111. } while (*++argv);
  112. ts.tv_sec = MAXINT(typeof(ts.tv_sec));
  113. ts.tv_nsec = 0;
  114. if (duration >= 0 && duration < ts.tv_sec) {
  115. ts.tv_sec = duration;
  116. ts.tv_nsec = (duration - ts.tv_sec) * 1000000000;
  117. }
  118. do {
  119. errno = 0;
  120. nanosleep(&ts, &ts);
  121. } while (errno == EINTR);
  122. #elif ENABLE_FEATURE_FANCY_SLEEP
  123. duration = 0;
  124. do {
  125. duration += xatou_range_sfx(*argv, 0, UINT_MAX - duration, sfx);
  126. } while (*++argv);
  127. sleep(duration);
  128. #else /* simple */
  129. duration = xatou(*argv);
  130. sleep(duration);
  131. // Off. If it's really needed, provide example why
  132. //if (sleep(duration)) {
  133. // bb_perror_nomsg_and_die();
  134. //}
  135. #endif
  136. return EXIT_SUCCESS;
  137. }