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