aboutsummaryrefslogtreecommitdiff
path: root/shell/hush.c
diff options
context:
space:
mode:
Diffstat (limited to 'shell/hush.c')
-rw-r--r--shell/hush.c57
1 files changed, 40 insertions, 17 deletions
diff --git a/shell/hush.c b/shell/hush.c
index bc6e6014f..7c1e1d748 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -84,13 +84,12 @@
84 * [[ args ]] are CMD_SINGLEWORD_NOGLOB: 84 * [[ args ]] are CMD_SINGLEWORD_NOGLOB:
85 * v='a b'; [[ $v = 'a b' ]]; echo 0:$? 85 * v='a b'; [[ $v = 'a b' ]]; echo 0:$?
86 * [[ /bin/n* ]]; echo 0:$? 86 * [[ /bin/n* ]]; echo 0:$?
87 * = is glob match operator, not equality operator: STR = GLOB
88 * (in GLOB, quoting is significant on char-by-char basis: a*cd"*")
89 * == same as =
90 * =~ is regex match operator: STR =~ REGEX
87 * TODO: 91 * TODO:
88 * &&/|| are AND/OR ops, -a/-o are not
89 * quoting needs to be considered (-f is an operator, "-f" and ""-f are not; etc) 92 * quoting needs to be considered (-f is an operator, "-f" and ""-f are not; etc)
90 * = is glob match operator, not equality operator: STR = GLOB
91 * (in GLOB, quoting is significant on char-by-char basis: a*cd"*")
92 * == same as =
93 * add =~ regex match operator: STR =~ REGEX
94 */ 93 */
95//config:config HUSH 94//config:config HUSH
96//config: bool "hush (68 kb)" 95//config: bool "hush (68 kb)"
@@ -651,14 +650,16 @@ struct command {
651 smallint cmd_type; /* CMD_xxx */ 650 smallint cmd_type; /* CMD_xxx */
652#define CMD_NORMAL 0 651#define CMD_NORMAL 0
653#define CMD_SUBSHELL 1 652#define CMD_SUBSHELL 1
654#if BASH_TEST2 || ENABLE_HUSH_LOCAL || ENABLE_HUSH_EXPORT || ENABLE_HUSH_READONLY 653#if BASH_TEST2
655/* used for "[[ EXPR ]]", and to prevent word splitting and globbing in 654/* used for "[[ EXPR ]]" */
656 * "export v=t*" 655# define CMD_TEST2_SINGLEWORD_NOGLOB 2
657 */ 656#endif
658# define CMD_SINGLEWORD_NOGLOB 2 657#if ENABLE_HUSH_LOCAL || ENABLE_HUSH_EXPORT || ENABLE_HUSH_READONLY
658/* used to prevent word splitting and globbing in "export v=t*" */
659# define CMD_SINGLEWORD_NOGLOB 3
659#endif 660#endif
660#if ENABLE_HUSH_FUNCTIONS 661#if ENABLE_HUSH_FUNCTIONS
661# define CMD_FUNCDEF 3 662# define CMD_FUNCDEF 4
662#endif 663#endif
663 664
664 smalluint cmd_exitcode; 665 smalluint cmd_exitcode;
@@ -4112,6 +4113,14 @@ static int done_word(struct parse_context *ctx)
4112 ctx->ctx_dsemicolon = 0; 4113 ctx->ctx_dsemicolon = 0;
4113 } else 4114 } else
4114# endif 4115# endif
4116# if defined(CMD_TEST2_SINGLEWORD_NOGLOB)
4117 if (command->cmd_type == CMD_TEST2_SINGLEWORD_NOGLOB
4118 && strcmp(ctx->word.data, "]]") == 0
4119 ) {
4120 /* allow "[[ ]] >file" etc */
4121 command->cmd_type = CMD_SINGLEWORD_NOGLOB;
4122 } else
4123# endif
4115 if (!command->argv /* if it's the first word... */ 4124 if (!command->argv /* if it's the first word... */
4116# if ENABLE_HUSH_LOOPS 4125# if ENABLE_HUSH_LOOPS
4117 && ctx->ctx_res_w != RES_FOR /* ...not after FOR or IN */ 4126 && ctx->ctx_res_w != RES_FOR /* ...not after FOR or IN */
@@ -4146,11 +4155,13 @@ static int done_word(struct parse_context *ctx)
4146 (ctx->ctx_res_w == RES_SNTX)); 4155 (ctx->ctx_res_w == RES_SNTX));
4147 return (ctx->ctx_res_w == RES_SNTX); 4156 return (ctx->ctx_res_w == RES_SNTX);
4148 } 4157 }
4158# if defined(CMD_TEST2_SINGLEWORD_NOGLOB)
4159 if (strcmp(ctx->word.data, "[[") == 0) {
4160 command->cmd_type = CMD_TEST2_SINGLEWORD_NOGLOB;
4161 } else
4162# endif
4149# if defined(CMD_SINGLEWORD_NOGLOB) 4163# if defined(CMD_SINGLEWORD_NOGLOB)
4150 if (0 4164 if (0
4151# if BASH_TEST2
4152 || strcmp(ctx->word.data, "[[") == 0
4153# endif
4154 /* In bash, local/export/readonly are special, args 4165 /* In bash, local/export/readonly are special, args
4155 * are assignments and therefore expansion of them 4166 * are assignments and therefore expansion of them
4156 * should be "one-word" expansion: 4167 * should be "one-word" expansion:
@@ -4172,7 +4183,8 @@ static int done_word(struct parse_context *ctx)
4172 ) { 4183 ) {
4173 command->cmd_type = CMD_SINGLEWORD_NOGLOB; 4184 command->cmd_type = CMD_SINGLEWORD_NOGLOB;
4174 } 4185 }
4175 /* fall through */ 4186# else
4187 { /* empty block to pair "if ... else" */ }
4176# endif 4188# endif
4177 } 4189 }
4178#endif /* HAS_KEYWORDS */ 4190#endif /* HAS_KEYWORDS */
@@ -5354,9 +5366,15 @@ static struct pipe *parse_stream(char **pstring,
5354 if (ch != '\n') 5366 if (ch != '\n')
5355 next = i_peek_and_eat_bkslash_nl(input); 5367 next = i_peek_and_eat_bkslash_nl(input);
5356 5368
5357 is_special = "{}<>;&|()#" /* special outside of "str" */ 5369 is_special = "{}<>&|();#" /* special outside of "str" */
5358 "$\"" IF_HUSH_TICK("`") /* always special */ 5370 "$\"" IF_HUSH_TICK("`") /* always special */
5359 SPECIAL_VAR_SYMBOL_STR; 5371 SPECIAL_VAR_SYMBOL_STR;
5372#if defined(CMD_TEST2_SINGLEWORD_NOGLOB)
5373 if (ctx.command->cmd_type == CMD_TEST2_SINGLEWORD_NOGLOB) {
5374 /* In [[ ]], {}<>&|() are not special */
5375 is_special += 8;
5376 } else
5377#endif
5360 /* Are { and } special here? */ 5378 /* Are { and } special here? */
5361 if (ctx.command->argv /* word [word]{... - non-special */ 5379 if (ctx.command->argv /* word [word]{... - non-special */
5362 || ctx.word.length /* word{... - non-special */ 5380 || ctx.word.length /* word{... - non-special */
@@ -6953,7 +6971,7 @@ static char **expand_strvec_to_strvec(char **argv)
6953 return expand_variables(argv, EXP_FLAG_GLOB | EXP_FLAG_ESC_GLOB_CHARS); 6971 return expand_variables(argv, EXP_FLAG_GLOB | EXP_FLAG_ESC_GLOB_CHARS);
6954} 6972}
6955 6973
6956#if defined(CMD_SINGLEWORD_NOGLOB) 6974#if defined(CMD_SINGLEWORD_NOGLOB) || defined(CMD_TEST2_SINGLEWORD_NOGLOB)
6957static char **expand_strvec_to_strvec_singleword_noglob(char **argv) 6975static char **expand_strvec_to_strvec_singleword_noglob(char **argv)
6958{ 6976{
6959 return expand_variables(argv, EXP_FLAG_SINGLEWORD); 6977 return expand_variables(argv, EXP_FLAG_SINGLEWORD);
@@ -9133,6 +9151,11 @@ static NOINLINE int run_pipe(struct pipe *pi)
9133 } 9151 }
9134 9152
9135 /* Expand the rest into (possibly) many strings each */ 9153 /* Expand the rest into (possibly) many strings each */
9154#if defined(CMD_TEST2_SINGLEWORD_NOGLOB)
9155 if (command->cmd_type == CMD_TEST2_SINGLEWORD_NOGLOB)
9156 argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt);
9157 else
9158#endif
9136#if defined(CMD_SINGLEWORD_NOGLOB) 9159#if defined(CMD_SINGLEWORD_NOGLOB)
9137 if (command->cmd_type == CMD_SINGLEWORD_NOGLOB) 9160 if (command->cmd_type == CMD_SINGLEWORD_NOGLOB)
9138 argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt); 9161 argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt);