Imported from ../bash-2.05a.tar.gz.
[platform/upstream/bash.git] / examples / loadables / sleep.c
1 /*
2  * sleep -- sleep for fractions of a second
3  *
4  * usage: sleep seconds[.fraction]
5  */
6 #include "config.h"
7
8 #include "bashtypes.h"
9
10 #if defined (TIME_WITH_SYS_TIME)
11 #  include <sys/time.h>
12 #  include <time.h>
13 #else
14 #  if defined (HAVE_SYS_TIME_H)
15 #    include <sys/time.h>
16 #  else
17 #    include <time.h>
18 #  endif
19 #endif
20
21 #if defined (HAVE_UNISTD_H)
22 #include <unistd.h>
23 #endif
24
25 #include <stdio.h>
26 #include "chartypes.h"
27
28 #include "shell.h"
29 #include "builtins.h"
30
31 #define RETURN(x) \
32         do { \
33                 if (sp) *sp = sec; \
34                 if (usp) *usp = usec; \
35                 return (x); \
36         } while (0)
37
38 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
39 static int
40 fsleep(sec, usec)
41 long    sec, usec;
42 {
43         struct timeval tv;
44
45         tv.tv_sec = sec;
46         tv.tv_usec = usec;
47
48         return select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv);
49 }
50 #else /* !HAVE_TIMEVAL || !HAVE_SELECT */
51 static int
52 fsleep(sec, usec)
53 long    sec, usec;
54 {
55         if (usec >= 500000)     /* round */
56                 sec++;
57         return (sleep(sec));
58 }
59 #endif /* !HAVE_TIMEVAL || !HAVE_SELECT */
60
61 /*
62  * An incredibly simplistic floating point converter.
63  */
64 static int multiplier[7] = { 1, 100000, 10000, 1000, 100, 10, 1 };
65
66 static int
67 convert(s, sp, usp)
68 char    *s;
69 long    *sp, *usp;
70 {
71         int n;
72         long sec, usec;
73         char    *p;
74
75         sec = usec = 0;
76
77 #define DECIMAL '.'
78
79         for (p = s; p && *p; p++) {
80                 if (*p == DECIMAL)              /* decimal point */
81                         break;
82                 if (DIGIT(*p) == 0)
83                         RETURN(0);
84                 sec = (sec * 10) + (*p - '0');
85         }
86
87         if (*p == 0)
88                 RETURN(1);
89
90         if (*p == DECIMAL)
91                 p++;
92
93         /* Look for up to six digits past a decimal point. */
94         for (n = 0; n < 6 && p[n]; n++) {
95                 if (DIGIT(p[n]) == 0)
96                         RETURN(0);
97                 usec = (usec * 10) + (p[n] - '0');
98         }
99
100         /* Now convert to millionths */
101         usec *= multiplier[n];
102
103         if (n == 6 && p[6] >= '5' && p[6] <= '9')
104                 usec++;                 /* round up 1 */
105
106         RETURN(1);
107 }
108
109 int
110 sleep_builtin (list)
111 WORD_LIST       *list;
112 {
113         long    sec, usec;
114
115         if (list == 0) {
116                 builtin_usage();
117                 return(EX_USAGE);
118         }
119
120         if (*list->word->word == '-' || list->next) {
121                 builtin_usage ();
122                 return (EX_USAGE);
123         }
124
125         if (convert(list->word->word, &sec, &usec)) {
126                 fsleep(sec, usec);
127                 return(EXECUTION_SUCCESS);
128         }
129
130         builtin_error("%s: bad sleep interval", list->word->word);
131         return (EXECUTION_FAILURE);
132 }
133
134 static char *sleep_doc[] = {
135         "sleep suspends execution for a minimum of SECONDS[.FRACTION] seconds.",
136         (char *)NULL
137 };
138
139 struct builtin sleep_struct = {
140         "sleep",
141         sleep_builtin,
142         BUILTIN_ENABLED,
143         sleep_doc,
144         "sleep seconds[.fraction]",
145         0
146 };