mirror of
https://github.com/sheumann/hush.git
synced 2024-08-25 21:28:57 +00:00
hush: add HUSH_BASH_COMPAT, make [[ special handling depend on it
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
1d77db8459
commit
9ca656b149
@ -43,9 +43,6 @@ config ASH
|
|||||||
shell (by Herbert Xu), which was created by porting the 'ash' shell
|
shell (by Herbert Xu), which was created by porting the 'ash' shell
|
||||||
(written by Kenneth Almquist) from NetBSD.
|
(written by Kenneth Almquist) from NetBSD.
|
||||||
|
|
||||||
comment "Ash Shell Options"
|
|
||||||
depends on ASH
|
|
||||||
|
|
||||||
config ASH_BASH_COMPAT
|
config ASH_BASH_COMPAT
|
||||||
bool "bash-compatible extensions"
|
bool "bash-compatible extensions"
|
||||||
default y
|
default y
|
||||||
@ -169,6 +166,13 @@ config HUSH
|
|||||||
It does not handle select, aliases, brace expansion,
|
It does not handle select, aliases, brace expansion,
|
||||||
tilde expansion, &>file and >&file redirection of stdout+stderr.
|
tilde expansion, &>file and >&file redirection of stdout+stderr.
|
||||||
|
|
||||||
|
config HUSH_BASH_COMPAT
|
||||||
|
bool "bash-compatible extensions"
|
||||||
|
default y
|
||||||
|
depends on HUSH
|
||||||
|
help
|
||||||
|
Enable bash-compatible extensions.
|
||||||
|
|
||||||
config HUSH_HELP
|
config HUSH_HELP
|
||||||
bool "help builtin"
|
bool "help builtin"
|
||||||
default n
|
default n
|
||||||
@ -268,9 +272,6 @@ config MSH
|
|||||||
# It uses only vfork, so it can be used on uClinux systems.
|
# It uses only vfork, so it can be used on uClinux systems.
|
||||||
|
|
||||||
|
|
||||||
comment "Bourne Shell Options"
|
|
||||||
depends on MSH || LASH || HUSH || ASH
|
|
||||||
|
|
||||||
config SH_MATH_SUPPORT
|
config SH_MATH_SUPPORT
|
||||||
bool "POSIX math support"
|
bool "POSIX math support"
|
||||||
default y
|
default y
|
||||||
|
56
shell/hush.c
56
shell/hush.c
@ -42,11 +42,18 @@
|
|||||||
* <(list) and >(list) Process Substitution
|
* <(list) and >(list) Process Substitution
|
||||||
* Tilde Expansion
|
* Tilde Expansion
|
||||||
*
|
*
|
||||||
* Bash stuff (maybe optionally enable?):
|
* Bash stuff (optionally enabled):
|
||||||
* &> and >& redirection of stdout+stderr
|
* &> and >& redirection of stdout+stderr
|
||||||
* Brace Expansion
|
* Brace Expansion
|
||||||
* reserved words: [[ ]] function select
|
* reserved words: [[ ]] function select
|
||||||
* substrings ${var:1:5}
|
* substrings ${var:1:5}
|
||||||
|
* let EXPR [EXPR...]
|
||||||
|
* Each EXPR is an arithmetic expression (ARITHMETIC EVALUATION)
|
||||||
|
* If the last arg evaluates to 0, let returns 1; 0 otherwise.
|
||||||
|
* NB: let `echo 'a=a + 1'` - error (IOW: multi-word expansion is used)
|
||||||
|
* ((EXPR))
|
||||||
|
* The EXPR is evaluated according to ARITHMETIC EVALUATION.
|
||||||
|
* This is exactly equivalent to let "expression".
|
||||||
*
|
*
|
||||||
* TODOs:
|
* TODOs:
|
||||||
* grep for "TODO" and fix (some of them are easy)
|
* grep for "TODO" and fix (some of them are easy)
|
||||||
@ -59,7 +66,7 @@
|
|||||||
* $ ls i=`echo 'a b'` # ls has two args: "i=a" and "b"
|
* $ ls i=`echo 'a b'` # ls has two args: "i=a" and "b"
|
||||||
* ls: cannot access i=a: No such file or directory
|
* ls: cannot access i=a: No such file or directory
|
||||||
* ls: cannot access b: No such file or directory
|
* ls: cannot access b: No such file or directory
|
||||||
* Note1: same applies to local builtin when we'll have it.
|
* Note1: same applies to local builtin.
|
||||||
* Note2: bash 3.2.33(1) does this only if export word itself
|
* Note2: bash 3.2.33(1) does this only if export word itself
|
||||||
* is not quoted:
|
* is not quoted:
|
||||||
* $ export i=`echo 'aaa bbb'`; echo "$i"
|
* $ export i=`echo 'aaa bbb'`; echo "$i"
|
||||||
@ -299,28 +306,11 @@ struct command {
|
|||||||
smallint cmd_type; /* CMD_xxx */
|
smallint cmd_type; /* CMD_xxx */
|
||||||
#define CMD_NORMAL 0
|
#define CMD_NORMAL 0
|
||||||
#define CMD_SUBSHELL 1
|
#define CMD_SUBSHELL 1
|
||||||
|
|
||||||
/* used for "[[ EXPR ]]" */
|
/* used for "[[ EXPR ]]" */
|
||||||
#define CMD_SINGLEWORD_NOGLOB 2
|
#if ENABLE_HUSH_BASH_COMPAT
|
||||||
/* used for "export noglob=* glob* a=`echo a b`" */
|
# define CMD_SINGLEWORD_NOGLOB 2
|
||||||
/* #define CMD_SINGLEWORD_NOGLOB_COND 3 */
|
|
||||||
// It is hard to implement correctly, adds significant amounts of tricky code,
|
|
||||||
// and all this only useful for really obscure export statements
|
|
||||||
// almost nobody would use anyway. #ifdef CMD_SINGLEWORD_NOGLOB_COND
|
|
||||||
// guard the code which implement it, but I have doubts it works
|
|
||||||
// in all cases (especially with mixed globbed/non-globbed arguments)
|
|
||||||
#if ENABLE_HUSH_FUNCTIONS
|
|
||||||
# define CMD_FUNCDEF 4
|
|
||||||
#endif
|
#endif
|
||||||
//TODO
|
|
||||||
//#define CMD_ARITH - let EXPR, ((EXPR))
|
|
||||||
//let EXPR [EXPR...]
|
|
||||||
// Each EXPR is an arithmetic expression to be evaluated (ARITHMETIC EVALUATION)
|
|
||||||
// If the last arg evaluates to 0, let returns 1; 0 is returned otherwise.
|
|
||||||
// NB: let `echo 'a=a + 1'` - error (IOW: multi-word expansion is used)
|
|
||||||
//((EXPR))
|
|
||||||
// The EXPR is evaluated according to ARITHMETIC EVALUATION.
|
|
||||||
// This is exactly equivalent to let "expression".
|
|
||||||
//[[ EXPR ]]
|
|
||||||
// Basically, word splitting and pathname expansion should NOT be performed
|
// Basically, word splitting and pathname expansion should NOT be performed
|
||||||
// Examples:
|
// Examples:
|
||||||
// no word splitting: a="a b"; [[ $a = "a b" ]]; echo $? should print "0"
|
// no word splitting: a="a b"; [[ $a = "a b" ]]; echo $? should print "0"
|
||||||
@ -330,6 +320,18 @@ struct command {
|
|||||||
// =~ regexp match
|
// =~ regexp match
|
||||||
// Apart from the above, [[ expr ]] should work as [ expr ]
|
// Apart from the above, [[ expr ]] should work as [ expr ]
|
||||||
|
|
||||||
|
/* used for "export noglob=* glob* a=`echo a b`" */
|
||||||
|
/*#define CMD_SINGLEWORD_NOGLOB_COND 3 */
|
||||||
|
// It is hard to implement correctly, it adds significant amounts of tricky code,
|
||||||
|
// and all this is only useful for really obscure export statements
|
||||||
|
// almost nobody would use anyway. #ifdef CMD_SINGLEWORD_NOGLOB_COND
|
||||||
|
// guards the code which implements it, but I have doubts it works
|
||||||
|
// in all cases (especially with mixed globbed/non-globbed arguments)
|
||||||
|
|
||||||
|
#if ENABLE_HUSH_FUNCTIONS
|
||||||
|
# define CMD_FUNCDEF 3
|
||||||
|
#endif
|
||||||
|
|
||||||
/* if non-NULL, this "command" is { list }, ( list ), or a compound statement */
|
/* if non-NULL, this "command" is { list }, ( list ), or a compound statement */
|
||||||
struct pipe *group;
|
struct pipe *group;
|
||||||
#if !BB_MMU
|
#if !BB_MMU
|
||||||
@ -2484,10 +2486,12 @@ static char **expand_strvec_to_strvec(char **argv)
|
|||||||
return expand_variables(argv, 0x100);
|
return expand_variables(argv, 0x100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_HUSH_BASH_COMPAT
|
||||||
static char **expand_strvec_to_strvec_singleword_noglob(char **argv)
|
static char **expand_strvec_to_strvec_singleword_noglob(char **argv)
|
||||||
{
|
{
|
||||||
return expand_variables(argv, 0x80);
|
return expand_variables(argv, 0x80);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CMD_SINGLEWORD_NOGLOB_COND
|
#ifdef CMD_SINGLEWORD_NOGLOB_COND
|
||||||
static char **expand_strvec_to_strvec_singleword_noglob_cond(char **argv)
|
static char **expand_strvec_to_strvec_singleword_noglob_cond(char **argv)
|
||||||
@ -3838,9 +3842,12 @@ static int run_pipe(struct pipe *pi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Expand the rest into (possibly) many strings each */
|
/* Expand the rest into (possibly) many strings each */
|
||||||
if (command->cmd_type == CMD_SINGLEWORD_NOGLOB) {
|
if (0) {}
|
||||||
|
#if ENABLE_HUSH_BASH_COMPAT
|
||||||
|
else if (command->cmd_type == CMD_SINGLEWORD_NOGLOB) {
|
||||||
argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt);
|
argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#ifdef CMD_SINGLEWORD_NOGLOB_COND
|
#ifdef CMD_SINGLEWORD_NOGLOB_COND
|
||||||
else if (command->cmd_type == CMD_SINGLEWORD_NOGLOB_COND) {
|
else if (command->cmd_type == CMD_SINGLEWORD_NOGLOB_COND) {
|
||||||
argv_expanded = expand_strvec_to_strvec_singleword_noglob_cond(argv + command->assignment_cnt);
|
argv_expanded = expand_strvec_to_strvec_singleword_noglob_cond(argv + command->assignment_cnt);
|
||||||
@ -4094,6 +4101,7 @@ static void debug_print_tree(struct pipe *pi, int lvl)
|
|||||||
static const char *const CMDTYPE[] = {
|
static const char *const CMDTYPE[] = {
|
||||||
"{}",
|
"{}",
|
||||||
"()",
|
"()",
|
||||||
|
"[noglob]",
|
||||||
#if ENABLE_HUSH_FUNCTIONS
|
#if ENABLE_HUSH_FUNCTIONS
|
||||||
"func()",
|
"func()",
|
||||||
#endif
|
#endif
|
||||||
@ -4833,10 +4841,12 @@ static int done_word(o_string *word, struct parse_context *ctx)
|
|||||||
command->cmd_type = CMD_SINGLEWORD_NOGLOB_COND;
|
command->cmd_type = CMD_SINGLEWORD_NOGLOB_COND;
|
||||||
} else
|
} else
|
||||||
# endif
|
# endif
|
||||||
|
# if ENABLE_HUSH_BASH_COMPAT
|
||||||
if (strcmp(word->data, "[[") == 0) {
|
if (strcmp(word->data, "[[") == 0) {
|
||||||
command->cmd_type = CMD_SINGLEWORD_NOGLOB;
|
command->cmd_type = CMD_SINGLEWORD_NOGLOB;
|
||||||
}
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (command->group) {
|
if (command->group) {
|
||||||
|
Loading…
Reference in New Issue
Block a user