add a sleep builtin that can deal with fractions too
This commit is contained in:
parent
4e626ecc30
commit
cc8caf2cf9
57
funcs.c
57
funcs.c
@ -26,7 +26,19 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.168 2011/01/30 01:35:58 tg Exp $");
|
||||
#if HAVE_SELECT
|
||||
#if HAVE_SYS_BSDTYPES_H
|
||||
#include <sys/bsdtypes.h>
|
||||
#endif
|
||||
#if HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
#if HAVE_BSTRING_H
|
||||
#include <bstring.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.169 2011/02/11 00:41:34 tg Exp $");
|
||||
|
||||
#if HAVE_KILLPG
|
||||
/*
|
||||
@ -112,6 +124,9 @@ const struct builtin mkshbuiltins[] = {
|
||||
#endif
|
||||
{"realpath", c_realpath},
|
||||
{"rename", c_rename},
|
||||
#if HAVE_SELECT
|
||||
{"sleep", c_sleep},
|
||||
#endif
|
||||
{NULL, (int (*)(const char **))NULL}
|
||||
};
|
||||
|
||||
@ -3647,3 +3662,43 @@ c_cat(const char **wp)
|
||||
free(buf);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
#if HAVE_SELECT
|
||||
int
|
||||
c_sleep(const char **wp)
|
||||
{
|
||||
struct timeval tv;
|
||||
int rv = 1;
|
||||
|
||||
/* skip argv[0] */
|
||||
++wp;
|
||||
if (wp[0] && !strcmp(wp[0], "--"))
|
||||
/* skip "--" (options separator) */
|
||||
++wp;
|
||||
|
||||
if (!wp[0] || wp[1])
|
||||
bi_errorf(T_synerr);
|
||||
else if (parse_usec(wp[0], &tv))
|
||||
bi_errorf("%s: %s '%s'", T_synerr, strerror(errno), wp[0]);
|
||||
else {
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigset_t omask;
|
||||
|
||||
/* block SIGCHLD from interrupting us, though */
|
||||
sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
|
||||
#endif
|
||||
if (select(0, NULL, NULL, NULL, &tv) == 0 || errno == EINTR)
|
||||
/*
|
||||
* strictly speaking only for SIGALRM, but the
|
||||
* execution may be interrupted by other signals
|
||||
*/
|
||||
rv = 0;
|
||||
else
|
||||
bi_errorf("%s: %s", T_select, strerror(errno));
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigprocmask(SIG_BLOCK, &omask, NULL);
|
||||
#endif
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
#endif
|
||||
|
11
mksh.1
11
mksh.1
@ -1,4 +1,4 @@
|
||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.248 2011/02/09 13:08:18 tg Exp $
|
||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.249 2011/02/11 00:41:35 tg Exp $
|
||||
.\" $OpenBSD: ksh.1,v 1.138 2010/09/20 07:41:17 jmc Exp $
|
||||
.\"-
|
||||
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
|
||||
@ -72,7 +72,7 @@
|
||||
.\" with -mandoc, it might implement .Mx itself, but we want to
|
||||
.\" use our own definition. And .Dd must come *first*, always.
|
||||
.\"
|
||||
.Dd $Mdocdate: February 9 2011 $
|
||||
.Dd $Mdocdate: February 11 2011 $
|
||||
.\"
|
||||
.\" Check which macro package we use
|
||||
.\"
|
||||
@ -2805,7 +2805,7 @@ regular commands
|
||||
.Ic \&[ , chdir , bind , cat ,
|
||||
.Ic echo , let , mknod , print ,
|
||||
.Ic printf , pwd , realpath , rename ,
|
||||
.Ic test , ulimit , whence
|
||||
.Ic sleep , test , ulimit , whence
|
||||
.Pp
|
||||
In the future, the additional
|
||||
.Nm
|
||||
@ -4047,6 +4047,11 @@ etc.
|
||||
.Ar number
|
||||
defaults to 1.
|
||||
.Pp
|
||||
.It Ic sleep Ar seconds
|
||||
Suspends execution for a minimum of the
|
||||
.Ar seconds
|
||||
specified as positive decimal value with an optional fractional part.
|
||||
Signal delivery may continue execution earlier.
|
||||
.It Ic source Ar file Op Ar arg ...
|
||||
Like
|
||||
.Ic \&. Po Do dot Dc Pc ,
|
||||
|
7
sh.h
7
sh.h
@ -154,7 +154,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef EXTERN
|
||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.428 2011/02/09 13:08:27 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.429 2011/02/11 00:41:37 tg Exp $");
|
||||
#endif
|
||||
#define MKSH_VERSION "R39 2011/02/09"
|
||||
|
||||
@ -626,6 +626,7 @@ EXTERN const char T_oomem[] I__("can't allocate %lu data bytes");
|
||||
#else
|
||||
EXTERN const char T_synerr[] I__("syntax error");
|
||||
#endif
|
||||
EXTERN const char T_select[] I__("select");
|
||||
EXTERN const char T_r_fc_e_[] I__("r=fc -e -");
|
||||
#define T_fc_e_ (T_r_fc_e_ + 2) /* "fc -e -" */
|
||||
#define Tn_fc_e_ 7 /* strlen(T_fc_e_) */
|
||||
@ -794,7 +795,7 @@ struct coproc {
|
||||
EXTERN struct coproc coproc;
|
||||
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
/* Used in jobs.c and by coprocess stuff in exec.c */
|
||||
/* used in jobs.c and by coprocess stuff in exec.c and select() calls */
|
||||
EXTERN sigset_t sm_default, sm_sigchld;
|
||||
#endif
|
||||
|
||||
@ -1526,6 +1527,7 @@ int c_mknod(const char **);
|
||||
int c_realpath(const char **);
|
||||
int c_rename(const char **);
|
||||
int c_cat(const char **);
|
||||
int c_sleep(const char **);
|
||||
/* histrap.c */
|
||||
void init_histvec(void);
|
||||
void hist_init(Source *);
|
||||
@ -1703,6 +1705,7 @@ int shf_vfprintf(struct shf *, const char *, va_list)
|
||||
/* syn.c */
|
||||
void initkeywords(void);
|
||||
struct op *compile(Source *);
|
||||
bool parse_usec(const char *, struct timeval *);
|
||||
/* tree.c */
|
||||
int fptreef(struct shf *, int, const char *, ...);
|
||||
char *snptreef(char *, int, const char *, ...);
|
||||
|
66
syn.c
66
syn.c
@ -1,7 +1,7 @@
|
||||
/* $OpenBSD: syn.c,v 1.28 2008/07/23 16:34:38 jaredy Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011
|
||||
* Thorsten Glaser <tg@mirbsd.org>
|
||||
*
|
||||
* Provided that these terms and disclaimer and all copyright notices
|
||||
@ -22,7 +22,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.52 2010/09/14 21:26:18 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.53 2011/02/11 00:41:38 tg Exp $");
|
||||
|
||||
struct nesting_state {
|
||||
int start_token; /* token than began nesting (eg, FOR) */
|
||||
@ -405,7 +405,7 @@ get_command(int cf)
|
||||
t = newtp((c == FOR) ? TFOR : TSELECT);
|
||||
musthave(LWORD, ARRAYVAR);
|
||||
if (!is_wdvarname(yylval.cp, true))
|
||||
yyerror("%s: %s\n", c == FOR ? "for" : "select",
|
||||
yyerror("%s: %s\n", c == FOR ? "for" : T_select,
|
||||
"bad identifier");
|
||||
strdupx(t->str, ident, ATEMP);
|
||||
nesting_push(&old_nesting, c);
|
||||
@ -736,7 +736,7 @@ const struct tokeninfo {
|
||||
{ "case", CASE, true },
|
||||
{ "esac", ESAC, true },
|
||||
{ "for", FOR, true },
|
||||
{ "select", SELECT, true },
|
||||
{ T_select, SELECT, true },
|
||||
{ "while", WHILE, true },
|
||||
{ "until", UNTIL, true },
|
||||
{ "do", DO, true },
|
||||
@ -1005,3 +1005,61 @@ dbtestp_error(Test_env *te, int offset, const char *msg)
|
||||
}
|
||||
syntaxerr(msg);
|
||||
}
|
||||
|
||||
#if HAVE_SELECT
|
||||
|
||||
#ifndef EOVERFLOW
|
||||
#ifdef ERANGE
|
||||
#define EOVERFLOW ERANGE
|
||||
#else
|
||||
#define EOVERFLOW EINVAL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bool
|
||||
parse_usec(const char *s, struct timeval *tv)
|
||||
{
|
||||
struct timeval tt;
|
||||
int i;
|
||||
|
||||
tv->tv_sec = 0;
|
||||
/* parse integral part */
|
||||
while (ksh_isdigit(*s)) {
|
||||
tt.tv_sec = tv->tv_sec * 10 + (*s++ - '0');
|
||||
if (tt.tv_sec / 10 != tv->tv_sec) {
|
||||
errno = EOVERFLOW;
|
||||
return (true);
|
||||
}
|
||||
tv->tv_sec = tt.tv_sec;
|
||||
}
|
||||
|
||||
tv->tv_usec = 0;
|
||||
if (!*s)
|
||||
/* no decimal fraction */
|
||||
return (false);
|
||||
else if (*s++ != '.') {
|
||||
/* junk after integral part */
|
||||
errno = EINVAL;
|
||||
return (true);
|
||||
}
|
||||
|
||||
/* parse decimal fraction */
|
||||
i = 100000;
|
||||
while (ksh_isdigit(*s)) {
|
||||
tv->tv_usec += i * (*s++ - '0');
|
||||
if (i == 1)
|
||||
break;
|
||||
i /= 10;
|
||||
}
|
||||
/* check for junk after fractional part */
|
||||
while (ksh_isdigit(*s))
|
||||
++s;
|
||||
if (*s) {
|
||||
errno = EINVAL;
|
||||
return (true);
|
||||
}
|
||||
|
||||
/* end of input string reached, no errors */
|
||||
return (false);
|
||||
}
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user