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 (1.7 kb)" 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 43/* Do not make this applet NOFORK. It breaks ^C-ing of pauses in shells */ 44//applet:IF_SLEEP(APPLET(sleep, BB_DIR_BIN, BB_SUID_DROP)) 45 46//kbuild:lib-$(CONFIG_SLEEP) += sleep.o 47 48/* BB_AUDIT SUSv3 compliant */ 49/* BB_AUDIT GNU issues -- fancy version matches except args must be ints. */ 50/* http://www.opengroup.org/onlinepubs/007904975/utilities/sleep.html */ 51 52//usage:#define sleep_trivial_usage 53//usage: IF_FEATURE_FANCY_SLEEP("[") "N" IF_FEATURE_FANCY_SLEEP("]...") 54//usage:#define sleep_full_usage "\n\n" 55//usage: IF_NOT_FEATURE_FANCY_SLEEP("Pause for N seconds") 56//usage: IF_FEATURE_FANCY_SLEEP( 57//usage: "Pause for a time equal to the total of the args given, where each arg can\n" 58//usage: "have an optional suffix of (s)econds, (m)inutes, (h)ours, or (d)ays") 59//usage: 60//usage:#define sleep_example_usage 61//usage: "$ sleep 2\n" 62//usage: "[2 second delay results]\n" 63//usage: IF_FEATURE_FANCY_SLEEP( 64//usage: "$ sleep 1d 3h 22m 8s\n" 65//usage: "[98528 second delay results]\n") 66 67#include "libbb.h" 68 69#if ENABLE_FEATURE_FANCY_SLEEP || ENABLE_FEATURE_FLOAT_SLEEP 70static const struct suffix_mult sfx[] = { 71 { "s", 1 }, 72 { "m", 60 }, 73 { "h", 60*60 }, 74 { "d", 24*60*60 }, 75 { "", 0 } 76}; 77#endif 78 79int sleep_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 80int sleep_main(int argc UNUSED_PARAM, char **argv) 81{ 82#if ENABLE_FEATURE_FLOAT_SLEEP 83 double duration; 84 struct timespec ts; 85#else 86 unsigned duration; 87#endif 88 89 ++argv; 90 if (!*argv) 91 bb_show_usage(); 92 93#if ENABLE_FEATURE_FLOAT_SLEEP 94 95# if ENABLE_LOCALE_SUPPORT 96 /* undo busybox.c setlocale */ 97 setlocale(LC_NUMERIC, "C"); 98# endif 99 duration = 0; 100 do { 101 char *arg = *argv; 102 if (strchr(arg, '.')) { 103 double d; 104 char *pp; 105 int len = strspn(arg, "0123456789."); 106 char sv = arg[len]; 107 arg[len] = '\0'; 108 errno = 0; 109 d = strtod(arg, &pp); 110 if (errno || *pp) 111 bb_show_usage(); 112 arg += len; 113 *arg-- = sv; 114 sv = *arg; 115 *arg = '1'; 116 duration += d * xatoul_sfx(arg, sfx); 117 *arg = sv; 118 } else { 119 duration += xatoul_sfx(arg, sfx); 120 } 121 } while (*++argv); 122 123 ts.tv_sec = MAXINT(typeof(ts.tv_sec)); 124 ts.tv_nsec = 0; 125 if (duration >= 0 && duration < ts.tv_sec) { 126 ts.tv_sec = duration; 127 ts.tv_nsec = (duration - ts.tv_sec) * 1000000000; 128 } 129 do { 130 errno = 0; 131 nanosleep(&ts, &ts); 132 } while (errno == EINTR); 133 134#elif ENABLE_FEATURE_FANCY_SLEEP 135 136 duration = 0; 137 do { 138 duration += xatou_range_sfx(*argv, 0, UINT_MAX - duration, sfx); 139 } while (*++argv); 140 sleep(duration); 141 142#else /* simple */ 143 144 duration = xatou(*argv); 145 sleep(duration); 146 // Off. If it's really needed, provide example why 147 //if (sleep(duration)) { 148 // bb_perror_nomsg_and_die(); 149 //} 150 151#endif 152 153 return EXIT_SUCCESS; 154} 155