aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorKang-Che Sung <explorer09@gmail.com>2017-01-11 14:18:15 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2017-01-11 14:18:30 +0100
commit027d3ab57d6a3a5a872543a6f30e55347d975149 (patch)
tree350985cb3b94227757b737a26bb6fc0230e714a0 /shell
parent7d4aec0c3ecb0c10de60070616d9d8fb9b074497 (diff)
downloadbusybox-w32-027d3ab57d6a3a5a872543a6f30e55347d975149.tar.gz
busybox-w32-027d3ab57d6a3a5a872543a6f30e55347d975149.tar.bz2
busybox-w32-027d3ab57d6a3a5a872543a6f30e55347d975149.zip
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>
Diffstat (limited to 'shell')
-rw-r--r--shell/hush.c73
1 files changed, 44 insertions, 29 deletions
diff --git a/shell/hush.c b/shell/hush.c
index ecef099ac..fb0321a2c 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -326,6 +326,15 @@
326#endif 326#endif
327 327
328 328
329/* So far, all bash compat is controlled by one config option */
330/* Separate defines document which part of code implements what */
331#define BASH_PATTERN_SUBST ENABLE_HUSH_BASH_COMPAT
332#define BASH_SUBSTR ENABLE_HUSH_BASH_COMPAT
333#define BASH_TEST2 ENABLE_HUSH_BASH_COMPAT
334#define BASH_SOURCE ENABLE_HUSH_BASH_COMPAT
335#define BASH_HOSTNAME_VAR ENABLE_HUSH_BASH_COMPAT
336
337
329/* Build knobs */ 338/* Build knobs */
330#define LEAK_HUNTING 0 339#define LEAK_HUNTING 0
331#define BUILD_AS_NOMMU 0 340#define BUILD_AS_NOMMU 0
@@ -411,7 +420,7 @@
411#define _SPECIAL_VARS_STR "_*@$!?#" 420#define _SPECIAL_VARS_STR "_*@$!?#"
412#define SPECIAL_VARS_STR ("_*@$!?#" + 1) 421#define SPECIAL_VARS_STR ("_*@$!?#" + 1)
413#define NUMERIC_SPECVARS_STR ("_*@$!?#" + 3) 422#define NUMERIC_SPECVARS_STR ("_*@$!?#" + 3)
414#if ENABLE_HUSH_BASH_COMPAT 423#if BASH_PATTERN_SUBST
415/* Support / and // replace ops */ 424/* Support / and // replace ops */
416/* Note that // is stored as \ in "encoded" string representation */ 425/* Note that // is stored as \ in "encoded" string representation */
417# define VAR_ENCODED_SUBST_OPS "\\/%#:-=+?" 426# define VAR_ENCODED_SUBST_OPS "\\/%#:-=+?"
@@ -572,7 +581,7 @@ struct command {
572 smallint cmd_type; /* CMD_xxx */ 581 smallint cmd_type; /* CMD_xxx */
573#define CMD_NORMAL 0 582#define CMD_NORMAL 0
574#define CMD_SUBSHELL 1 583#define CMD_SUBSHELL 1
575#if ENABLE_HUSH_BASH_COMPAT 584#if BASH_TEST2
576/* used for "[[ EXPR ]]" */ 585/* used for "[[ EXPR ]]" */
577# define CMD_SINGLEWORD_NOGLOB 2 586# define CMD_SINGLEWORD_NOGLOB 2
578#endif 587#endif
@@ -947,7 +956,7 @@ static int builtin_set(char **argv) FAST_FUNC;
947#endif 956#endif
948static int builtin_shift(char **argv) FAST_FUNC; 957static int builtin_shift(char **argv) FAST_FUNC;
949static int builtin_source(char **argv) FAST_FUNC; 958static int builtin_source(char **argv) FAST_FUNC;
950#if ENABLE_HUSH_TEST 959#if ENABLE_HUSH_TEST || BASH_TEST2
951static int builtin_test(char **argv) FAST_FUNC; 960static int builtin_test(char **argv) FAST_FUNC;
952#endif 961#endif
953#if ENABLE_HUSH_TRAP 962#if ENABLE_HUSH_TRAP
@@ -1044,7 +1053,7 @@ static const struct built_in_command bltins1[] = {
1044 BLTIN("set" , builtin_set , "Set positional parameters"), 1053 BLTIN("set" , builtin_set , "Set positional parameters"),
1045#endif 1054#endif
1046 BLTIN("shift" , builtin_shift , "Shift positional parameters"), 1055 BLTIN("shift" , builtin_shift , "Shift positional parameters"),
1047#if ENABLE_HUSH_BASH_COMPAT 1056#if BASH_SOURCE
1048 BLTIN("source" , builtin_source , NULL), 1057 BLTIN("source" , builtin_source , NULL),
1049#endif 1058#endif
1050#if ENABLE_HUSH_TRAP 1059#if ENABLE_HUSH_TRAP
@@ -2174,7 +2183,7 @@ static void unset_vars(char **strings)
2174 free(strings); 2183 free(strings);
2175} 2184}
2176 2185
2177#if ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_BASH_COMPAT || ENABLE_HUSH_READ 2186#if BASH_HOSTNAME_VAR || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_READ
2178static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val) 2187static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val)
2179{ 2188{
2180 char *var = xasprintf("%s=%s", name, val); 2189 char *var = xasprintf("%s=%s", name, val);
@@ -3633,7 +3642,7 @@ static int done_word(o_string *word, struct parse_context *ctx)
3633 (ctx->ctx_res_w == RES_SNTX)); 3642 (ctx->ctx_res_w == RES_SNTX));
3634 return (ctx->ctx_res_w == RES_SNTX); 3643 return (ctx->ctx_res_w == RES_SNTX);
3635 } 3644 }
3636# if ENABLE_HUSH_BASH_COMPAT 3645# if BASH_TEST2
3637 if (strcmp(word->data, "[[") == 0) { 3646 if (strcmp(word->data, "[[") == 0) {
3638 command->cmd_type = CMD_SINGLEWORD_NOGLOB; 3647 command->cmd_type = CMD_SINGLEWORD_NOGLOB;
3639 } 3648 }
@@ -4231,7 +4240,7 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign
4231{ 4240{
4232 int ch; 4241 int ch;
4233 char dbl = end_ch & DOUBLE_CLOSE_CHAR_FLAG; 4242 char dbl = end_ch & DOUBLE_CLOSE_CHAR_FLAG;
4234# if ENABLE_HUSH_BASH_COMPAT 4243# if BASH_SUBSTR || BASH_PATTERN_SUBST
4235 char end_char2 = end_ch >> 8; 4244 char end_char2 = end_ch >> 8;
4236# endif 4245# endif
4237 end_ch &= (DOUBLE_CLOSE_CHAR_FLAG - 1); 4246 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
4242 syntax_error_unterm_ch(end_ch); 4251 syntax_error_unterm_ch(end_ch);
4243 return 0; 4252 return 0;
4244 } 4253 }
4245 if (ch == end_ch IF_HUSH_BASH_COMPAT( || ch == end_char2)) { 4254 if (ch == end_ch
4255# if BASH_SUBSTR || BASH_PATTERN_SUBST
4256 || ch == end_char2
4257# endif
4258 ) {
4246 if (!dbl) 4259 if (!dbl)
4247 break; 4260 break;
4248 /* we look for closing )) of $((EXPR)) */ 4261 /* we look for closing )) of $((EXPR)) */
@@ -4395,14 +4408,14 @@ static int parse_dollar(o_string *as_string,
4395 4408
4396 /* Eat everything until closing '}' (or ':') */ 4409 /* Eat everything until closing '}' (or ':') */
4397 end_ch = '}'; 4410 end_ch = '}';
4398 if (ENABLE_HUSH_BASH_COMPAT 4411 if (BASH_SUBSTR
4399 && ch == ':' 4412 && ch == ':'
4400 && !strchr(MINUS_PLUS_EQUAL_QUESTION, i_peek(input)) 4413 && !strchr(MINUS_PLUS_EQUAL_QUESTION, i_peek(input))
4401 ) { 4414 ) {
4402 /* It's ${var:N[:M]} thing */ 4415 /* It's ${var:N[:M]} thing */
4403 end_ch = '}' * 0x100 + ':'; 4416 end_ch = '}' * 0x100 + ':';
4404 } 4417 }
4405 if (ENABLE_HUSH_BASH_COMPAT 4418 if (BASH_PATTERN_SUBST
4406 && ch == '/' 4419 && ch == '/'
4407 ) { 4420 ) {
4408 /* It's ${var/[/]pattern[/repl]} thing */ 4421 /* It's ${var/[/]pattern[/repl]} thing */
@@ -4429,7 +4442,9 @@ static int parse_dollar(o_string *as_string,
4429 o_addchr(as_string, last_ch); 4442 o_addchr(as_string, last_ch);
4430 } 4443 }
4431 4444
4432 if (ENABLE_HUSH_BASH_COMPAT && (end_ch & 0xff00)) { 4445 if ((BASH_SUBSTR || BASH_PATTERN_SUBST)
4446 && (end_ch & 0xff00)
4447 ) {
4433 /* close the first block: */ 4448 /* close the first block: */
4434 o_addchr(dest, SPECIAL_VAR_SYMBOL); 4449 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4435 /* while parsing N from ${var:N[:M]} 4450 /* while parsing N from ${var:N[:M]}
@@ -4440,7 +4455,7 @@ static int parse_dollar(o_string *as_string,
4440 goto again; 4455 goto again;
4441 } 4456 }
4442 /* got '}' */ 4457 /* got '}' */
4443 if (end_ch == '}' * 0x100 + ':') { 4458 if (BASH_SUBSTR && end_ch == '}' * 0x100 + ':') {
4444 /* it's ${var:N} - emulate :999999999 */ 4459 /* it's ${var:N} - emulate :999999999 */
4445 o_addstr(dest, "999999999"); 4460 o_addstr(dest, "999999999");
4446 } /* else: it's ${var/[/]pattern} */ 4461 } /* else: it's ${var/[/]pattern} */
@@ -4515,7 +4530,7 @@ static int parse_dollar(o_string *as_string,
4515} 4530}
4516 4531
4517#if BB_MMU 4532#if BB_MMU
4518# if ENABLE_HUSH_BASH_COMPAT 4533# if BASH_PATTERN_SUBST
4519#define encode_string(as_string, dest, input, dquote_end, process_bkslash) \ 4534#define encode_string(as_string, dest, input, dquote_end, process_bkslash) \
4520 encode_string(dest, input, dquote_end, process_bkslash) 4535 encode_string(dest, input, dquote_end, process_bkslash)
4521# else 4536# else
@@ -4527,7 +4542,7 @@ static int parse_dollar(o_string *as_string,
4527 4542
4528#else /* !MMU */ 4543#else /* !MMU */
4529 4544
4530# if ENABLE_HUSH_BASH_COMPAT 4545# if BASH_PATTERN_SUBST
4531/* all parameters are needed, no macro tricks */ 4546/* all parameters are needed, no macro tricks */
4532# else 4547# else
4533#define encode_string(as_string, dest, input, dquote_end, process_bkslash) \ 4548#define encode_string(as_string, dest, input, dquote_end, process_bkslash) \
@@ -4540,7 +4555,7 @@ static int encode_string(o_string *as_string,
4540 int dquote_end, 4555 int dquote_end,
4541 int process_bkslash) 4556 int process_bkslash)
4542{ 4557{
4543#if !ENABLE_HUSH_BASH_COMPAT 4558#if !BASH_PATTERN_SUBST
4544 const int process_bkslash = 1; 4559 const int process_bkslash = 1;
4545#endif 4560#endif
4546 int ch; 4561 int ch;
@@ -5183,7 +5198,7 @@ static struct pipe *parse_stream(char **pstring,
5183/*** Execution routines ***/ 5198/*** Execution routines ***/
5184 5199
5185/* Expansion can recurse, need forward decls: */ 5200/* Expansion can recurse, need forward decls: */
5186#if !ENABLE_HUSH_BASH_COMPAT 5201#if !BASH_PATTERN_SUBST
5187/* only ${var/pattern/repl} (its pattern part) needs additional mode */ 5202/* only ${var/pattern/repl} (its pattern part) needs additional mode */
5188#define expand_string_to_string(str, do_unbackslash) \ 5203#define expand_string_to_string(str, do_unbackslash) \
5189 expand_string_to_string(str) 5204 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
5304 * Returns malloced string. 5319 * Returns malloced string.
5305 * As an optimization, we return NULL if expansion is not needed. 5320 * As an optimization, we return NULL if expansion is not needed.
5306 */ 5321 */
5307#if !ENABLE_HUSH_BASH_COMPAT 5322#if !BASH_PATTERN_SUBST
5308/* only ${var/pattern/repl} (its pattern part) needs additional mode */ 5323/* only ${var/pattern/repl} (its pattern part) needs additional mode */
5309#define encode_then_expand_string(str, process_bkslash, do_unbackslash) \ 5324#define encode_then_expand_string(str, process_bkslash, do_unbackslash) \
5310 encode_then_expand_string(str) 5325 encode_then_expand_string(str)
@@ -5358,7 +5373,7 @@ static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p)
5358} 5373}
5359#endif 5374#endif
5360 5375
5361#if ENABLE_HUSH_BASH_COMPAT 5376#if BASH_PATTERN_SUBST
5362/* ${var/[/]pattern[/repl]} helpers */ 5377/* ${var/[/]pattern[/repl]} helpers */
5363static char *strstr_pattern(char *val, const char *pattern, int *size) 5378static char *strstr_pattern(char *val, const char *pattern, int *size)
5364{ 5379{
@@ -5410,7 +5425,7 @@ static char *replace_pattern(char *val, const char *pattern, const char *repl, c
5410 debug_printf_varexp("result:'%s'\n", result); 5425 debug_printf_varexp("result:'%s'\n", result);
5411 return result; 5426 return result;
5412} 5427}
5413#endif 5428#endif /* BASH_PATTERN_SUBST */
5414 5429
5415/* Helper: 5430/* Helper:
5416 * Handles <SPECIAL_VAR_SYMBOL>varname...<SPECIAL_VAR_SYMBOL> construct. 5431 * 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
5458 if (exp_op == ':') { 5473 if (exp_op == ':') {
5459 exp_op = *exp_word++; 5474 exp_op = *exp_word++;
5460//TODO: try ${var:} and ${var:bogus} in non-bash config 5475//TODO: try ${var:} and ${var:bogus} in non-bash config
5461 if (ENABLE_HUSH_BASH_COMPAT 5476 if (BASH_SUBSTR
5462 && (!exp_op || !strchr(MINUS_PLUS_EQUAL_QUESTION, exp_op)) 5477 && (!exp_op || !strchr(MINUS_PLUS_EQUAL_QUESTION, exp_op))
5463 ) { 5478 ) {
5464 /* oops... it's ${var:N[:M]}, not ${var:?xxx} or some such */ 5479 /* 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
5540 } 5555 }
5541 } 5556 }
5542 } 5557 }
5543#if ENABLE_HUSH_BASH_COMPAT 5558#if BASH_PATTERN_SUBST
5544 else if (exp_op == '/' || exp_op == '\\') { 5559 else if (exp_op == '/' || exp_op == '\\') {
5545 /* It's ${var/[/]pattern[/repl]} thing. 5560 /* It's ${var/[/]pattern[/repl]} thing.
5546 * Note that in encoded form it has TWO parts: 5561 * 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
5587 free(repl); 5602 free(repl);
5588 } 5603 }
5589 } 5604 }
5590#endif 5605#endif /* BASH_PATTERN_SUBST */
5591 else if (exp_op == ':') { 5606 else if (exp_op == ':') {
5592#if ENABLE_HUSH_BASH_COMPAT && ENABLE_FEATURE_SH_MATH 5607#if BASH_SUBSTR && ENABLE_FEATURE_SH_MATH
5593 /* It's ${var:N[:M]} bashism. 5608 /* It's ${var:N[:M]} bashism.
5594 * Note that in encoded form it has TWO parts: 5609 * Note that in encoded form it has TWO parts:
5595 * var:N<SPECIAL_VAR_SYMBOL>M<SPECIAL_VAR_SYMBOL> 5610 * 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
5625 } 5640 }
5626 debug_printf_varexp("val:'%s'\n", val); 5641 debug_printf_varexp("val:'%s'\n", val);
5627 } else 5642 } else
5628#endif 5643#endif /* HUSH_SUBSTR_EXPANSION && FEATURE_SH_MATH */
5629 { 5644 {
5630 die_if_script("malformed ${%s:...}", var); 5645 die_if_script("malformed ${%s:...}", var);
5631 val = NULL; 5646 val = NULL;
@@ -5915,7 +5930,7 @@ static char **expand_strvec_to_strvec(char **argv)
5915 return expand_variables(argv, EXP_FLAG_GLOB | EXP_FLAG_ESC_GLOB_CHARS); 5930 return expand_variables(argv, EXP_FLAG_GLOB | EXP_FLAG_ESC_GLOB_CHARS);
5916} 5931}
5917 5932
5918#if ENABLE_HUSH_BASH_COMPAT 5933#if BASH_TEST2
5919static char **expand_strvec_to_strvec_singleword_noglob(char **argv) 5934static char **expand_strvec_to_strvec_singleword_noglob(char **argv)
5920{ 5935{
5921 return expand_variables(argv, EXP_FLAG_SINGLEWORD); 5936 return expand_variables(argv, EXP_FLAG_SINGLEWORD);
@@ -5930,7 +5945,7 @@ static char **expand_strvec_to_strvec_singleword_noglob(char **argv)
5930 */ 5945 */
5931static char *expand_string_to_string(const char *str, int do_unbackslash) 5946static char *expand_string_to_string(const char *str, int do_unbackslash)
5932{ 5947{
5933#if !ENABLE_HUSH_BASH_COMPAT 5948#if !BASH_PATTERN_SUBST
5934 const int do_unbackslash = 1; 5949 const int do_unbackslash = 1;
5935#endif 5950#endif
5936 char *argv[2], **list; 5951 char *argv[2], **list;
@@ -7652,7 +7667,7 @@ static NOINLINE int run_pipe(struct pipe *pi)
7652 } 7667 }
7653 7668
7654 /* Expand the rest into (possibly) many strings each */ 7669 /* Expand the rest into (possibly) many strings each */
7655#if ENABLE_HUSH_BASH_COMPAT 7670#if BASH_TEST2
7656 if (command->cmd_type == CMD_SINGLEWORD_NOGLOB) { 7671 if (command->cmd_type == CMD_SINGLEWORD_NOGLOB) {
7657 argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt); 7672 argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt);
7658 } else 7673 } else
@@ -8408,7 +8423,7 @@ int hush_main(int argc, char **argv)
8408 /* Export PWD */ 8423 /* Export PWD */
8409 set_pwd_var(/*exp:*/ 1); 8424 set_pwd_var(/*exp:*/ 1);
8410 8425
8411#if ENABLE_HUSH_BASH_COMPAT 8426#if BASH_HOSTNAME_VAR
8412 /* Set (but not export) HOSTNAME unless already set */ 8427 /* Set (but not export) HOSTNAME unless already set */
8413 if (!get_local_var_value("HOSTNAME")) { 8428 if (!get_local_var_value("HOSTNAME")) {
8414 struct utsname uts; 8429 struct utsname uts;
@@ -8816,7 +8831,7 @@ static int run_applet_main(char **argv, int (*applet_main_func)(int argc, char *
8816 return applet_main_func(argc, argv - argc); 8831 return applet_main_func(argc, argv - argc);
8817} 8832}
8818#endif 8833#endif
8819#if ENABLE_HUSH_TEST 8834#if ENABLE_HUSH_TEST || BASH_TEST2
8820static int FAST_FUNC builtin_test(char **argv) 8835static int FAST_FUNC builtin_test(char **argv)
8821{ 8836{
8822 return run_applet_main(argv, test_main); 8837 return run_applet_main(argv, test_main);