]> git.ipfire.org Git - thirdparty/bash.git/blob - examples/loadables/sleep.c
Imported from ../bash-2.0.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
64 convert(s, sp, usp)
65 char *s;
66 long *sp, *usp;
67 {
68 int n;
69 long sec, usec;
70 char *p;
71
72 sec = usec = 0;
73
74 #define DECIMAL '.'
75
76 for (p = s; p && *p; p++) {
77 if (*p == DECIMAL) /* decimal point */
78 break;
79 if (isdigit(*p) == 0)
80 RETURN(0);
81 sec = (sec * 10) + (*p - '0');
82 }
83
84 if (*p == 0)
85 RETURN(1);
86
87 if (*p == DECIMAL)
88 p++;
89
90 /* Look for up to six digits past a decimal point. */
91 for (n = 0; n < 6 && p[n]; n++) {
92 if (isdigit(p[n]) == 0)
93 RETURN(0);
94 usec = (usec * 10) + (p[n] - '0');
95 }
96
97 /* Now convert to millionths */
98 if (n == 1)
99 usec *= 100000;
100 else if (n == 2)
101 usec *= 10000;
102 else if (n == 3)
103 usec *= 1000;
104 else if (n == 4)
105 usec *= 100;
106 else if (n == 5)
107 usec *= 10;
108 else if (n == 6 && p[6] && isdigit(p[6]) && p[6] >= '5')
109 usec++; /* round up 1 */
110 RETURN(1);
111 }
112
113 int
114 sleep_builtin (list)
115 WORD_LIST *list;
116 {
117 long sec, usec;
118
119 if (list == 0) {
120 builtin_usage();
121 return(EX_USAGE);
122 }
123
124 if (*list->word->word == '-' || list->next) {
125 builtin_usage ();
126 return (EX_USAGE);
127 }
128
129 if (convert(list->word->word, &sec, &usec)) {
130 fsleep(sec, usec);
131 return(EXECUTION_SUCCESS);
132 }
133
134 builtin_error("%s: bad sleep interval", list->word->word);
135 return (EXECUTION_FAILURE);
136 }
137
138 static char *sleep_doc[] = {
139 "sleep suspends execution for a minimum of SECONDS[.FRACTION] seconds.",
140 (char *)NULL
141 };
142
143 struct builtin sleep_struct = {
144 "sleep",
145 sleep_builtin,
146 BUILTIN_ENABLED,
147 sleep_doc,
148 "sleep seconds[.fraction]",
149 0
150 };