]> git.ipfire.org Git - thirdparty/bash.git/blob - examples/loadables/sleep.c
Imported from ../bash-2.04.tar.gz.
[thirdparty/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 };