1 /* sleep - delay for a specified amount of time.
2 Copyright (C) 84, 1991-1997, 1999-2000 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 #include <sys/types.h>
25 #define USE_CLOCK_GETTIME (defined CLOCK_REALTIME && HAVE_CLOCK_GETTIME)
26 #if ! USE_CLOCK_GETTIME
27 # include <sys/time.h>
31 # define TIME_T_MAX TYPE_MAXIMUM (time_t)
36 #include "long-options.h"
37 #include "nanosleep.h"
45 /* Tell the compiler that non-default rounding modes are used. */
46 #if 199901 <= __STDC_VERSION__
47 #pragma STDC FENV_ACCESS ON
50 /* The official name of this program (e.g., no `g' prefix). */
51 #define PROGRAM_NAME "sleep"
53 #define AUTHORS "Jim Meyering and Paul Eggert"
55 /* The name by which this program was run. */
58 static struct option
const long_options
[] =
67 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
72 Usage: %s NUMBER[SUFFIX]...\n\
74 Pause for NUMBER seconds. SUFFIX may be `s' for seconds (the default),\n\
75 `m' for minutes, `h' for hours or `d' for days. Unlike most implementations\n\
76 that require NUMBER be an integer, here NUMBER may be an arbitrary floating\n\
79 --help display this help and exit\n\
80 --version output version information and exit\n\
82 program_name
, program_name
);
83 puts (_("\nReport bugs to <bug-sh-utils@gnu.org>."));
88 /* Given a floating point value *X, and a suffix character, SUFFIX_CHAR,
89 scale *X by the multiplier implied by SUFFIX_CHAR. SUFFIX_CHAR may
90 be the NUL byte or `s' to denote seconds, `m' for minutes, `h' for
91 hours, or `d' for days. If SUFFIX_CHAR is invalid, don't modify *X
92 and return nonzero. Otherwise return zero. */
95 apply_suffix (double *x
, char suffix_char
)
97 unsigned int multiplier
;
109 multiplier
= 60 * 60;
112 multiplier
= 60 * 60 * 24;
126 /* Subtract the `struct timespec' values X and Y,
127 storing the difference in DIFF.
128 Return 1 if the difference is positive, otherwise 0.
129 Derived from code in the GNU libc manual. */
132 timespec_subtract (struct timespec
*diff
,
133 const struct timespec
*x
, struct timespec
*y
)
135 /* Perform the carry for the later subtraction by updating Y. */
136 if (x
->tv_nsec
< y
->tv_nsec
)
138 int nsec
= (y
->tv_nsec
- x
->tv_nsec
) / 1000000000 + 1;
139 y
->tv_nsec
-= 1000000000 * nsec
;
143 if (1000000000 < x
->tv_nsec
- y
->tv_nsec
)
145 int nsec
= (y
->tv_nsec
- x
->tv_nsec
) / 1000000000;
146 y
->tv_nsec
+= 1000000000 * nsec
;
150 /* Compute the time remaining to wait.
151 `tv_nsec' is certainly positive. */
152 diff
->tv_sec
= x
->tv_sec
- y
->tv_sec
;
153 diff
->tv_nsec
= x
->tv_nsec
- y
->tv_nsec
;
155 /* Return 1 if result is positive. */
156 return y
->tv_sec
< x
->tv_sec
;
159 static struct timespec
*
160 clock_get_realtime (struct timespec
*ts
)
163 #if USE_CLOCK_GETTIME
164 fail
= clock_gettime (CLOCK_REALTIME
, ts
);
167 fail
= gettimeofday (&tv
, NULL
);
170 ts
->tv_sec
= tv
.tv_sec
;
171 ts
->tv_nsec
= 1000 * tv
.tv_usec
;
176 error (1, errno
, _("cannot read realtime clock"));
182 main (int argc
, char **argv
)
185 double seconds
= 0.0;
190 struct timespec ts_start
;
191 struct timespec ts_stop
;
192 struct timespec ts_sleep
;
194 /* Record start time. */
195 clock_get_realtime (&ts_start
);
197 program_name
= argv
[0];
198 setlocale (LC_ALL
, "");
199 bindtextdomain (PACKAGE
, LOCALEDIR
);
200 textdomain (PACKAGE
);
202 atexit (close_stdout
);
204 parse_long_options (argc
, argv
, PROGRAM_NAME
, GNU_PACKAGE
, VERSION
,
207 while ((c
= getopt_long (argc
, argv
, "", long_options
, NULL
)) != -1)
221 error (0, 0, _("too few arguments"));
226 /* Always round up, since we must sleep for at least the specified
228 fesetround (FE_UPWARD
);
231 for (i
= optind
; i
< argc
; i
++)
235 if (xstrtod (argv
[i
], &p
, &s
)
236 /* Nonnegative interval. */
238 /* No extra chars after the number and an optional s,m,h,d char. */
240 /* Check any suffix char and update S based on the suffix. */
241 || apply_suffix (&s
, *p
))
243 error (0, 0, _("invalid time interval `%s'"), argv
[i
]);
253 /* Separate whole seconds from nanoseconds.
254 Be careful to detect any overflow. */
255 ts_sleep
.tv_sec
= seconds
;
256 ns
= 1e9
* (seconds
- ts_sleep
.tv_sec
);
257 forever
= ! (ts_sleep
.tv_sec
<= seconds
&& 0 <= ns
&& ns
<= 1e9
);
258 ts_sleep
.tv_nsec
= ns
;
260 /* Round up to the next whole number, if necessary, so that we
261 always sleep for at least the requested amount of time. */
262 ts_sleep
.tv_nsec
+= (ts_sleep
.tv_nsec
< ns
);
264 /* Normalize the interval length. nanosleep requires this. */
265 if (1000000000 <= ts_sleep
.tv_nsec
)
267 time_t t
= ts_sleep
.tv_sec
+ 1;
269 /* Detect integer overflow. */
270 forever
|= (t
< ts_sleep
.tv_sec
);
273 ts_sleep
.tv_nsec
-= 1000000000;
276 ts_stop
.tv_sec
= ts_start
.tv_sec
+ ts_sleep
.tv_sec
;
277 ts_stop
.tv_nsec
= ts_start
.tv_nsec
+ ts_sleep
.tv_nsec
;
278 if (1000000000 <= ts_stop
.tv_nsec
)
281 ts_stop
.tv_nsec
-= 1000000000;
284 /* Detect integer overflow. */
285 forever
|= (ts_stop
.tv_sec
< ts_start
.tv_sec
286 || (ts_stop
.tv_sec
== ts_start
.tv_sec
287 && ts_stop
.tv_nsec
< ts_start
.tv_nsec
));
291 /* Fix ts_sleep and ts_stop, which may be garbage due to overflow. */
292 ts_sleep
.tv_sec
= ts_stop
.tv_sec
= TIME_T_MAX
;
293 ts_sleep
.tv_nsec
= ts_stop
.tv_nsec
= 999999999;
296 while (nanosleep (&ts_sleep
, NULL
) != 0
297 && timespec_subtract (&ts_sleep
, &ts_stop
,
298 clock_get_realtime (&ts_start
)))