150 lines
2.4 KiB
C
150 lines
2.4 KiB
C
/*
|
|
* sleep -- sleep for fractions of a second
|
|
*
|
|
* usage: sleep seconds[.fraction]
|
|
*/
|
|
#include "config.h"
|
|
|
|
#include "bashtypes.h"
|
|
|
|
#if defined (TIME_WITH_SYS_TIME)
|
|
# include <sys/time.h>
|
|
# include <time.h>
|
|
#else
|
|
# if defined (HAVE_SYS_TIME_H)
|
|
# include <sys/time.h>
|
|
# else
|
|
# include <time.h>
|
|
# endif
|
|
#endif
|
|
|
|
#if defined (HAVE_UNISTD_H)
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "shell.h"
|
|
#include "builtins.h"
|
|
|
|
#define RETURN(x) \
|
|
do { \
|
|
if (sp) *sp = sec; \
|
|
if (usp) *usp = usec; \
|
|
return (x); \
|
|
} while (0)
|
|
|
|
#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
|
|
static int
|
|
fsleep(sec, usec)
|
|
long sec, usec;
|
|
{
|
|
struct timeval tv;
|
|
|
|
tv.tv_sec = sec;
|
|
tv.tv_usec = usec;
|
|
|
|
return select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv);
|
|
}
|
|
#else /* !HAVE_TIMEVAL || !HAVE_SELECT */
|
|
static int
|
|
fsleep(sec, usec)
|
|
long sec, usec;
|
|
{
|
|
if (usec >= 500000) /* round */
|
|
sec++;
|
|
return (sleep(sec));
|
|
}
|
|
#endif /* !HAVE_TIMEVAL || !HAVE_SELECT */
|
|
|
|
/*
|
|
* An incredibly simplistic floating point converter.
|
|
*/
|
|
static int
|
|
convert(s, sp, usp)
|
|
char *s;
|
|
long *sp, *usp;
|
|
{
|
|
int n;
|
|
long sec, usec;
|
|
char *p;
|
|
|
|
sec = usec = 0;
|
|
|
|
#define DECIMAL '.'
|
|
|
|
for (p = s; p && *p; p++) {
|
|
if (*p == DECIMAL) /* decimal point */
|
|
break;
|
|
if (isdigit(*p) == 0)
|
|
RETURN(0);
|
|
sec = (sec * 10) + (*p - '0');
|
|
}
|
|
|
|
if (*p == 0)
|
|
RETURN(1);
|
|
|
|
if (*p == DECIMAL)
|
|
p++;
|
|
|
|
/* Look for up to six digits past a decimal point. */
|
|
for (n = 0; n < 6 && p[n]; n++) {
|
|
if (isdigit(p[n]) == 0)
|
|
RETURN(0);
|
|
usec = (usec * 10) + (p[n] - '0');
|
|
}
|
|
|
|
/* Now convert to millionths */
|
|
if (n == 1)
|
|
usec *= 100000;
|
|
else if (n == 2)
|
|
usec *= 10000;
|
|
else if (n == 3)
|
|
usec *= 1000;
|
|
else if (n == 4)
|
|
usec *= 100;
|
|
else if (n == 5)
|
|
usec *= 10;
|
|
else if (n == 6 && p[6] && isdigit(p[6]) && p[6] >= '5')
|
|
usec++; /* round up 1 */
|
|
RETURN(1);
|
|
}
|
|
|
|
int
|
|
sleep_builtin (list)
|
|
WORD_LIST *list;
|
|
{
|
|
long sec, usec;
|
|
|
|
if (list == 0) {
|
|
builtin_usage();
|
|
return(EX_USAGE);
|
|
}
|
|
|
|
if (*list->word->word == '-' || list->next) {
|
|
builtin_usage ();
|
|
return (EX_USAGE);
|
|
}
|
|
|
|
if (convert(list->word->word, &sec, &usec)) {
|
|
fsleep(sec, usec);
|
|
return(EXECUTION_SUCCESS);
|
|
}
|
|
|
|
builtin_error("%s: bad sleep interval", list->word->word);
|
|
return (EXECUTION_FAILURE);
|
|
}
|
|
|
|
static char *sleep_doc[] = {
|
|
"sleep suspends execution for a minimum of SECONDS[.FRACTION] seconds.",
|
|
(char *)NULL
|
|
};
|
|
|
|
struct builtin sleep_struct = {
|
|
"sleep",
|
|
sleep_builtin,
|
|
BUILTIN_ENABLED,
|
|
sleep_doc,
|
|
"sleep seconds[.fraction]",
|
|
0
|
|
};
|