hush: split bash compatible extensions into separate defines. No code changes
Splitting these options makes it self-documenting about what bash-compatible features we have. Signed-off-by: Kang-Che Sung <explorer09@gmail.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
7d4aec0c3e
commit
027d3ab57d
73
shell/hush.c
73
shell/hush.c
@ -326,6 +326,15 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* So far, all bash compat is controlled by one config option */
|
||||||
|
/* Separate defines document which part of code implements what */
|
||||||
|
#define BASH_PATTERN_SUBST ENABLE_HUSH_BASH_COMPAT
|
||||||
|
#define BASH_SUBSTR ENABLE_HUSH_BASH_COMPAT
|
||||||
|
#define BASH_TEST2 ENABLE_HUSH_BASH_COMPAT
|
||||||
|
#define BASH_SOURCE ENABLE_HUSH_BASH_COMPAT
|
||||||
|
#define BASH_HOSTNAME_VAR ENABLE_HUSH_BASH_COMPAT
|
||||||
|
|
||||||
|
|
||||||
/* Build knobs */
|
/* Build knobs */
|
||||||
#define LEAK_HUNTING 0
|
#define LEAK_HUNTING 0
|
||||||
#define BUILD_AS_NOMMU 0
|
#define BUILD_AS_NOMMU 0
|
||||||
@ -411,7 +420,7 @@
|
|||||||
#define _SPECIAL_VARS_STR "_*@$!?#"
|
#define _SPECIAL_VARS_STR "_*@$!?#"
|
||||||
#define SPECIAL_VARS_STR ("_*@$!?#" + 1)
|
#define SPECIAL_VARS_STR ("_*@$!?#" + 1)
|
||||||
#define NUMERIC_SPECVARS_STR ("_*@$!?#" + 3)
|
#define NUMERIC_SPECVARS_STR ("_*@$!?#" + 3)
|
||||||
#if ENABLE_HUSH_BASH_COMPAT
|
#if BASH_PATTERN_SUBST
|
||||||
/* Support / and // replace ops */
|
/* Support / and // replace ops */
|
||||||
/* Note that // is stored as \ in "encoded" string representation */
|
/* Note that // is stored as \ in "encoded" string representation */
|
||||||
# define VAR_ENCODED_SUBST_OPS "\\/%#:-=+?"
|
# define VAR_ENCODED_SUBST_OPS "\\/%#:-=+?"
|
||||||
@ -572,7 +581,7 @@ 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
|
||||||
#if ENABLE_HUSH_BASH_COMPAT
|
#if BASH_TEST2
|
||||||
/* used for "[[ EXPR ]]" */
|
/* used for "[[ EXPR ]]" */
|
||||||
# define CMD_SINGLEWORD_NOGLOB 2
|
# define CMD_SINGLEWORD_NOGLOB 2
|
||||||
#endif
|
#endif
|
||||||
@ -947,7 +956,7 @@ static int builtin_set(char **argv) FAST_FUNC;
|
|||||||
#endif
|
#endif
|
||||||
static int builtin_shift(char **argv) FAST_FUNC;
|
static int builtin_shift(char **argv) FAST_FUNC;
|
||||||
static int builtin_source(char **argv) FAST_FUNC;
|
static int builtin_source(char **argv) FAST_FUNC;
|
||||||
#if ENABLE_HUSH_TEST
|
#if ENABLE_HUSH_TEST || BASH_TEST2
|
||||||
static int builtin_test(char **argv) FAST_FUNC;
|
static int builtin_test(char **argv) FAST_FUNC;
|
||||||
#endif
|
#endif
|
||||||
#if ENABLE_HUSH_TRAP
|
#if ENABLE_HUSH_TRAP
|
||||||
@ -1044,7 +1053,7 @@ static const struct built_in_command bltins1[] = {
|
|||||||
BLTIN("set" , builtin_set , "Set positional parameters"),
|
BLTIN("set" , builtin_set , "Set positional parameters"),
|
||||||
#endif
|
#endif
|
||||||
BLTIN("shift" , builtin_shift , "Shift positional parameters"),
|
BLTIN("shift" , builtin_shift , "Shift positional parameters"),
|
||||||
#if ENABLE_HUSH_BASH_COMPAT
|
#if BASH_SOURCE
|
||||||
BLTIN("source" , builtin_source , NULL),
|
BLTIN("source" , builtin_source , NULL),
|
||||||
#endif
|
#endif
|
||||||
#if ENABLE_HUSH_TRAP
|
#if ENABLE_HUSH_TRAP
|
||||||
@ -2174,7 +2183,7 @@ static void unset_vars(char **strings)
|
|||||||
free(strings);
|
free(strings);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_BASH_COMPAT || ENABLE_HUSH_READ
|
#if BASH_HOSTNAME_VAR || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_READ
|
||||||
static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val)
|
static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val)
|
||||||
{
|
{
|
||||||
char *var = xasprintf("%s=%s", name, val);
|
char *var = xasprintf("%s=%s", name, val);
|
||||||
@ -3633,7 +3642,7 @@ static int done_word(o_string *word, struct parse_context *ctx)
|
|||||||
(ctx->ctx_res_w == RES_SNTX));
|
(ctx->ctx_res_w == RES_SNTX));
|
||||||
return (ctx->ctx_res_w == RES_SNTX);
|
return (ctx->ctx_res_w == RES_SNTX);
|
||||||
}
|
}
|
||||||
# if ENABLE_HUSH_BASH_COMPAT
|
# if BASH_TEST2
|
||||||
if (strcmp(word->data, "[[") == 0) {
|
if (strcmp(word->data, "[[") == 0) {
|
||||||
command->cmd_type = CMD_SINGLEWORD_NOGLOB;
|
command->cmd_type = CMD_SINGLEWORD_NOGLOB;
|
||||||
}
|
}
|
||||||
@ -4231,7 +4240,7 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign
|
|||||||
{
|
{
|
||||||
int ch;
|
int ch;
|
||||||
char dbl = end_ch & DOUBLE_CLOSE_CHAR_FLAG;
|
char dbl = end_ch & DOUBLE_CLOSE_CHAR_FLAG;
|
||||||
# if ENABLE_HUSH_BASH_COMPAT
|
# if BASH_SUBSTR || BASH_PATTERN_SUBST
|
||||||
char end_char2 = end_ch >> 8;
|
char end_char2 = end_ch >> 8;
|
||||||
# endif
|
# endif
|
||||||
end_ch &= (DOUBLE_CLOSE_CHAR_FLAG - 1);
|
end_ch &= (DOUBLE_CLOSE_CHAR_FLAG - 1);
|
||||||
@ -4242,7 +4251,11 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign
|
|||||||
syntax_error_unterm_ch(end_ch);
|
syntax_error_unterm_ch(end_ch);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (ch == end_ch IF_HUSH_BASH_COMPAT( || ch == end_char2)) {
|
if (ch == end_ch
|
||||||
|
# if BASH_SUBSTR || BASH_PATTERN_SUBST
|
||||||
|
|| ch == end_char2
|
||||||
|
# endif
|
||||||
|
) {
|
||||||
if (!dbl)
|
if (!dbl)
|
||||||
break;
|
break;
|
||||||
/* we look for closing )) of $((EXPR)) */
|
/* we look for closing )) of $((EXPR)) */
|
||||||
@ -4395,14 +4408,14 @@ static int parse_dollar(o_string *as_string,
|
|||||||
|
|
||||||
/* Eat everything until closing '}' (or ':') */
|
/* Eat everything until closing '}' (or ':') */
|
||||||
end_ch = '}';
|
end_ch = '}';
|
||||||
if (ENABLE_HUSH_BASH_COMPAT
|
if (BASH_SUBSTR
|
||||||
&& ch == ':'
|
&& ch == ':'
|
||||||
&& !strchr(MINUS_PLUS_EQUAL_QUESTION, i_peek(input))
|
&& !strchr(MINUS_PLUS_EQUAL_QUESTION, i_peek(input))
|
||||||
) {
|
) {
|
||||||
/* It's ${var:N[:M]} thing */
|
/* It's ${var:N[:M]} thing */
|
||||||
end_ch = '}' * 0x100 + ':';
|
end_ch = '}' * 0x100 + ':';
|
||||||
}
|
}
|
||||||
if (ENABLE_HUSH_BASH_COMPAT
|
if (BASH_PATTERN_SUBST
|
||||||
&& ch == '/'
|
&& ch == '/'
|
||||||
) {
|
) {
|
||||||
/* It's ${var/[/]pattern[/repl]} thing */
|
/* It's ${var/[/]pattern[/repl]} thing */
|
||||||
@ -4429,7 +4442,9 @@ static int parse_dollar(o_string *as_string,
|
|||||||
o_addchr(as_string, last_ch);
|
o_addchr(as_string, last_ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ENABLE_HUSH_BASH_COMPAT && (end_ch & 0xff00)) {
|
if ((BASH_SUBSTR || BASH_PATTERN_SUBST)
|
||||||
|
&& (end_ch & 0xff00)
|
||||||
|
) {
|
||||||
/* close the first block: */
|
/* close the first block: */
|
||||||
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
o_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||||
/* while parsing N from ${var:N[:M]}
|
/* while parsing N from ${var:N[:M]}
|
||||||
@ -4440,7 +4455,7 @@ static int parse_dollar(o_string *as_string,
|
|||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
/* got '}' */
|
/* got '}' */
|
||||||
if (end_ch == '}' * 0x100 + ':') {
|
if (BASH_SUBSTR && end_ch == '}' * 0x100 + ':') {
|
||||||
/* it's ${var:N} - emulate :999999999 */
|
/* it's ${var:N} - emulate :999999999 */
|
||||||
o_addstr(dest, "999999999");
|
o_addstr(dest, "999999999");
|
||||||
} /* else: it's ${var/[/]pattern} */
|
} /* else: it's ${var/[/]pattern} */
|
||||||
@ -4515,7 +4530,7 @@ static int parse_dollar(o_string *as_string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if BB_MMU
|
#if BB_MMU
|
||||||
# if ENABLE_HUSH_BASH_COMPAT
|
# if BASH_PATTERN_SUBST
|
||||||
#define encode_string(as_string, dest, input, dquote_end, process_bkslash) \
|
#define encode_string(as_string, dest, input, dquote_end, process_bkslash) \
|
||||||
encode_string(dest, input, dquote_end, process_bkslash)
|
encode_string(dest, input, dquote_end, process_bkslash)
|
||||||
# else
|
# else
|
||||||
@ -4527,7 +4542,7 @@ static int parse_dollar(o_string *as_string,
|
|||||||
|
|
||||||
#else /* !MMU */
|
#else /* !MMU */
|
||||||
|
|
||||||
# if ENABLE_HUSH_BASH_COMPAT
|
# if BASH_PATTERN_SUBST
|
||||||
/* all parameters are needed, no macro tricks */
|
/* all parameters are needed, no macro tricks */
|
||||||
# else
|
# else
|
||||||
#define encode_string(as_string, dest, input, dquote_end, process_bkslash) \
|
#define encode_string(as_string, dest, input, dquote_end, process_bkslash) \
|
||||||
@ -4540,7 +4555,7 @@ static int encode_string(o_string *as_string,
|
|||||||
int dquote_end,
|
int dquote_end,
|
||||||
int process_bkslash)
|
int process_bkslash)
|
||||||
{
|
{
|
||||||
#if !ENABLE_HUSH_BASH_COMPAT
|
#if !BASH_PATTERN_SUBST
|
||||||
const int process_bkslash = 1;
|
const int process_bkslash = 1;
|
||||||
#endif
|
#endif
|
||||||
int ch;
|
int ch;
|
||||||
@ -5183,7 +5198,7 @@ static struct pipe *parse_stream(char **pstring,
|
|||||||
/*** Execution routines ***/
|
/*** Execution routines ***/
|
||||||
|
|
||||||
/* Expansion can recurse, need forward decls: */
|
/* Expansion can recurse, need forward decls: */
|
||||||
#if !ENABLE_HUSH_BASH_COMPAT
|
#if !BASH_PATTERN_SUBST
|
||||||
/* only ${var/pattern/repl} (its pattern part) needs additional mode */
|
/* only ${var/pattern/repl} (its pattern part) needs additional mode */
|
||||||
#define expand_string_to_string(str, do_unbackslash) \
|
#define expand_string_to_string(str, do_unbackslash) \
|
||||||
expand_string_to_string(str)
|
expand_string_to_string(str)
|
||||||
@ -5304,7 +5319,7 @@ static int expand_on_ifs(int *ended_with_ifs, o_string *output, int n, const cha
|
|||||||
* Returns malloced string.
|
* Returns malloced string.
|
||||||
* As an optimization, we return NULL if expansion is not needed.
|
* As an optimization, we return NULL if expansion is not needed.
|
||||||
*/
|
*/
|
||||||
#if !ENABLE_HUSH_BASH_COMPAT
|
#if !BASH_PATTERN_SUBST
|
||||||
/* only ${var/pattern/repl} (its pattern part) needs additional mode */
|
/* only ${var/pattern/repl} (its pattern part) needs additional mode */
|
||||||
#define encode_then_expand_string(str, process_bkslash, do_unbackslash) \
|
#define encode_then_expand_string(str, process_bkslash, do_unbackslash) \
|
||||||
encode_then_expand_string(str)
|
encode_then_expand_string(str)
|
||||||
@ -5358,7 +5373,7 @@ static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ENABLE_HUSH_BASH_COMPAT
|
#if BASH_PATTERN_SUBST
|
||||||
/* ${var/[/]pattern[/repl]} helpers */
|
/* ${var/[/]pattern[/repl]} helpers */
|
||||||
static char *strstr_pattern(char *val, const char *pattern, int *size)
|
static char *strstr_pattern(char *val, const char *pattern, int *size)
|
||||||
{
|
{
|
||||||
@ -5410,7 +5425,7 @@ static char *replace_pattern(char *val, const char *pattern, const char *repl, c
|
|||||||
debug_printf_varexp("result:'%s'\n", result);
|
debug_printf_varexp("result:'%s'\n", result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* BASH_PATTERN_SUBST */
|
||||||
|
|
||||||
/* Helper:
|
/* Helper:
|
||||||
* Handles <SPECIAL_VAR_SYMBOL>varname...<SPECIAL_VAR_SYMBOL> construct.
|
* Handles <SPECIAL_VAR_SYMBOL>varname...<SPECIAL_VAR_SYMBOL> construct.
|
||||||
@ -5458,7 +5473,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
|
|||||||
if (exp_op == ':') {
|
if (exp_op == ':') {
|
||||||
exp_op = *exp_word++;
|
exp_op = *exp_word++;
|
||||||
//TODO: try ${var:} and ${var:bogus} in non-bash config
|
//TODO: try ${var:} and ${var:bogus} in non-bash config
|
||||||
if (ENABLE_HUSH_BASH_COMPAT
|
if (BASH_SUBSTR
|
||||||
&& (!exp_op || !strchr(MINUS_PLUS_EQUAL_QUESTION, exp_op))
|
&& (!exp_op || !strchr(MINUS_PLUS_EQUAL_QUESTION, exp_op))
|
||||||
) {
|
) {
|
||||||
/* oops... it's ${var:N[:M]}, not ${var:?xxx} or some such */
|
/* oops... it's ${var:N[:M]}, not ${var:?xxx} or some such */
|
||||||
@ -5540,7 +5555,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if ENABLE_HUSH_BASH_COMPAT
|
#if BASH_PATTERN_SUBST
|
||||||
else if (exp_op == '/' || exp_op == '\\') {
|
else if (exp_op == '/' || exp_op == '\\') {
|
||||||
/* It's ${var/[/]pattern[/repl]} thing.
|
/* It's ${var/[/]pattern[/repl]} thing.
|
||||||
* Note that in encoded form it has TWO parts:
|
* Note that in encoded form it has TWO parts:
|
||||||
@ -5587,9 +5602,9 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
|
|||||||
free(repl);
|
free(repl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* BASH_PATTERN_SUBST */
|
||||||
else if (exp_op == ':') {
|
else if (exp_op == ':') {
|
||||||
#if ENABLE_HUSH_BASH_COMPAT && ENABLE_FEATURE_SH_MATH
|
#if BASH_SUBSTR && ENABLE_FEATURE_SH_MATH
|
||||||
/* It's ${var:N[:M]} bashism.
|
/* It's ${var:N[:M]} bashism.
|
||||||
* Note that in encoded form it has TWO parts:
|
* Note that in encoded form it has TWO parts:
|
||||||
* var:N<SPECIAL_VAR_SYMBOL>M<SPECIAL_VAR_SYMBOL>
|
* var:N<SPECIAL_VAR_SYMBOL>M<SPECIAL_VAR_SYMBOL>
|
||||||
@ -5625,7 +5640,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
|
|||||||
}
|
}
|
||||||
debug_printf_varexp("val:'%s'\n", val);
|
debug_printf_varexp("val:'%s'\n", val);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif /* HUSH_SUBSTR_EXPANSION && FEATURE_SH_MATH */
|
||||||
{
|
{
|
||||||
die_if_script("malformed ${%s:...}", var);
|
die_if_script("malformed ${%s:...}", var);
|
||||||
val = NULL;
|
val = NULL;
|
||||||
@ -5915,7 +5930,7 @@ static char **expand_strvec_to_strvec(char **argv)
|
|||||||
return expand_variables(argv, EXP_FLAG_GLOB | EXP_FLAG_ESC_GLOB_CHARS);
|
return expand_variables(argv, EXP_FLAG_GLOB | EXP_FLAG_ESC_GLOB_CHARS);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_HUSH_BASH_COMPAT
|
#if BASH_TEST2
|
||||||
static char **expand_strvec_to_strvec_singleword_noglob(char **argv)
|
static char **expand_strvec_to_strvec_singleword_noglob(char **argv)
|
||||||
{
|
{
|
||||||
return expand_variables(argv, EXP_FLAG_SINGLEWORD);
|
return expand_variables(argv, EXP_FLAG_SINGLEWORD);
|
||||||
@ -5930,7 +5945,7 @@ static char **expand_strvec_to_strvec_singleword_noglob(char **argv)
|
|||||||
*/
|
*/
|
||||||
static char *expand_string_to_string(const char *str, int do_unbackslash)
|
static char *expand_string_to_string(const char *str, int do_unbackslash)
|
||||||
{
|
{
|
||||||
#if !ENABLE_HUSH_BASH_COMPAT
|
#if !BASH_PATTERN_SUBST
|
||||||
const int do_unbackslash = 1;
|
const int do_unbackslash = 1;
|
||||||
#endif
|
#endif
|
||||||
char *argv[2], **list;
|
char *argv[2], **list;
|
||||||
@ -7652,7 +7667,7 @@ static NOINLINE int run_pipe(struct pipe *pi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Expand the rest into (possibly) many strings each */
|
/* Expand the rest into (possibly) many strings each */
|
||||||
#if ENABLE_HUSH_BASH_COMPAT
|
#if BASH_TEST2
|
||||||
if (command->cmd_type == CMD_SINGLEWORD_NOGLOB) {
|
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);
|
||||||
} else
|
} else
|
||||||
@ -8408,7 +8423,7 @@ int hush_main(int argc, char **argv)
|
|||||||
/* Export PWD */
|
/* Export PWD */
|
||||||
set_pwd_var(/*exp:*/ 1);
|
set_pwd_var(/*exp:*/ 1);
|
||||||
|
|
||||||
#if ENABLE_HUSH_BASH_COMPAT
|
#if BASH_HOSTNAME_VAR
|
||||||
/* Set (but not export) HOSTNAME unless already set */
|
/* Set (but not export) HOSTNAME unless already set */
|
||||||
if (!get_local_var_value("HOSTNAME")) {
|
if (!get_local_var_value("HOSTNAME")) {
|
||||||
struct utsname uts;
|
struct utsname uts;
|
||||||
@ -8816,7 +8831,7 @@ static int run_applet_main(char **argv, int (*applet_main_func)(int argc, char *
|
|||||||
return applet_main_func(argc, argv - argc);
|
return applet_main_func(argc, argv - argc);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if ENABLE_HUSH_TEST
|
#if ENABLE_HUSH_TEST || BASH_TEST2
|
||||||
static int FAST_FUNC builtin_test(char **argv)
|
static int FAST_FUNC builtin_test(char **argv)
|
||||||
{
|
{
|
||||||
return run_applet_main(argv, test_main);
|
return run_applet_main(argv, test_main);
|
||||||
|
Loading…
Reference in New Issue
Block a user