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) 39static int 40fsleep(sec, usec) 41long 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 */ 51static int 52fsleep(sec, usec) 53long 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 */ 64static int multiplier[7] = { 1, 100000, 10000, 1000, 100, 10, 1 }; 65 66static int 67convert(s, sp, usp) 68char *s; 69long *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 109int 110sleep_builtin (list) 111WORD_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 134static char *sleep_doc[] = { 135 "sleep suspends execution for a minimum of SECONDS[.FRACTION] seconds.", 136 (char *)NULL 137}; 138 139struct builtin sleep_struct = { 140 "sleep", 141 sleep_builtin, 142 BUILTIN_ENABLED, 143 sleep_doc, 144 "sleep seconds[.fraction]", 145 0 146}; 147