aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-04-06 14:11:13 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-04-06 14:11:13 +0000
commita2b11e33950d7e0a352005fec6cfff9bdeb7c668 (patch)
treef9e6cf316f7c678bcac3a4cbacc45cc2a5d4979d /shell
parent0969a49c081aee3c53241e2f53ebc89d14070a39 (diff)
downloadbusybox-w32-a2b11e33950d7e0a352005fec6cfff9bdeb7c668.tar.gz
busybox-w32-a2b11e33950d7e0a352005fec6cfff9bdeb7c668.tar.bz2
busybox-w32-a2b11e33950d7e0a352005fec6cfff9bdeb7c668.zip
hush: fix "false && echo yes || echo no" bug 265
function old new delta run_list 1159 1189 +30
Diffstat (limited to '')
-rw-r--r--shell/hush.c100
1 files changed, 55 insertions, 45 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 3eb03e50b..227e73507 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -271,13 +271,6 @@ static const struct {
271 { O_RDWR, 1, "<>" } 271 { O_RDWR, 1, "<>" }
272}; 272};
273 273
274typedef enum pipe_style {
275 PIPE_SEQ = 1,
276 PIPE_AND = 2,
277 PIPE_OR = 3,
278 PIPE_BG = 4,
279} pipe_style;
280
281typedef enum reserved_style { 274typedef enum reserved_style {
282 RES_NONE = 0, 275 RES_NONE = 0,
283#if ENABLE_HUSH_IF 276#if ENABLE_HUSH_IF
@@ -395,6 +388,12 @@ struct pipe {
395 IF_HAS_KEYWORDS(smallint pi_inverted;) /* "! cmd | cmd" */ 388 IF_HAS_KEYWORDS(smallint pi_inverted;) /* "! cmd | cmd" */
396 IF_HAS_KEYWORDS(smallint res_word;) /* needed for if, for, while, until... */ 389 IF_HAS_KEYWORDS(smallint res_word;) /* needed for if, for, while, until... */
397}; 390};
391typedef enum pipe_style {
392 PIPE_SEQ = 1,
393 PIPE_AND = 2,
394 PIPE_OR = 3,
395 PIPE_BG = 4,
396} pipe_style;
398 397
399/* This holds pointers to the various results of parsing */ 398/* This holds pointers to the various results of parsing */
400struct parse_context { 399struct parse_context {
@@ -2158,7 +2157,7 @@ static void free_pipe_list(struct pipe *head, int indent)
2158 2157
2159 for (pi = head; pi; pi = next) { 2158 for (pi = head; pi; pi = next) {
2160#if HAS_KEYWORDS 2159#if HAS_KEYWORDS
2161 debug_printf_clean("%s pipe reserved mode %d\n", indenter(indent), pi->res_word); 2160 debug_printf_clean("%s pipe reserved word %d\n", indenter(indent), pi->res_word);
2162#endif 2161#endif
2163 free_pipe(pi, indent); 2162 free_pipe(pi, indent);
2164 debug_printf_clean("%s pipe followup code %d\n", indenter(indent), pi->followup); 2163 debug_printf_clean("%s pipe followup code %d\n", indenter(indent), pi->followup);
@@ -2182,7 +2181,7 @@ typedef struct nommu_save_t {
2182 pseudo_exec(command, argv_expanded) 2181 pseudo_exec(command, argv_expanded)
2183#endif 2182#endif
2184 2183
2185/* Called after [v]fork() in run_pipe(), or from builtin_exec(). 2184/* Called after [v]fork() in run_pipe, or from builtin_exec.
2186 * Never returns. 2185 * Never returns.
2187 * XXX no exit() here. If you don't exec, use _exit instead. 2186 * XXX no exit() here. If you don't exec, use _exit instead.
2188 * The at_exit handlers apparently confuse the calling process, 2187 * The at_exit handlers apparently confuse the calling process,
@@ -2389,7 +2388,7 @@ static void clean_up_after_re_execute(void)
2389 2388
2390static int run_list(struct pipe *pi); 2389static int run_list(struct pipe *pi);
2391 2390
2392/* Called after [v]fork() in run_pipe() 2391/* Called after [v]fork() in run_pipe
2393 */ 2392 */
2394static void pseudo_exec(nommu_save_t *nommu_save, 2393static void pseudo_exec(nommu_save_t *nommu_save,
2395 struct command *command, 2394 struct command *command,
@@ -3032,15 +3031,15 @@ static int run_list(struct pipe *pi)
3032 char **for_lcur = NULL; 3031 char **for_lcur = NULL;
3033 char **for_list = NULL; 3032 char **for_list = NULL;
3034#endif 3033#endif
3035 smallint flag_skip = 1; 3034 smallint last_followup;
3036 smalluint rcode = 0; /* probably just for compiler */ 3035 smalluint rcode;
3037#if ENABLE_HUSH_IF || ENABLE_HUSH_CASE 3036#if ENABLE_HUSH_IF || ENABLE_HUSH_CASE
3038 smalluint cond_code = 0; 3037 smalluint cond_code = 0;
3039#else 3038#else
3040 enum { cond_code = 0, }; 3039 enum { cond_code = 0 };
3041#endif 3040#endif
3042 /*enum reserved_style*/ smallint rword = RES_NONE; 3041 /*enum reserved_style*/ smallint rword;
3043 /*enum reserved_style*/ smallint skip_more_for_this_rword = RES_XXXX; 3042 /*enum reserved_style*/ smallint last_rword;
3044 3043
3045 debug_printf_exec("run_list start lvl %d\n", G.run_list_level + 1); 3044 debug_printf_exec("run_list start lvl %d\n", G.run_list_level + 1);
3046 3045
@@ -3119,6 +3118,11 @@ static int run_list(struct pipe *pi)
3119 } 3118 }
3120#endif /* JOB */ 3119#endif /* JOB */
3121 3120
3121 rcode = G.last_return_code;
3122 rword = RES_NONE;
3123 last_rword = RES_XXXX;
3124 last_followup = PIPE_SEQ;
3125
3122 /* Go through list of pipes, (maybe) executing them. */ 3126 /* Go through list of pipes, (maybe) executing them. */
3123 for (; pi; pi = USE_HUSH_LOOPS(rword == RES_DONE ? loop_top : ) pi->next) { 3127 for (; pi; pi = USE_HUSH_LOOPS(rword == RES_DONE ? loop_top : ) pi->next) {
3124 if (G.flag_SIGINT) 3128 if (G.flag_SIGINT)
@@ -3126,8 +3130,8 @@ static int run_list(struct pipe *pi)
3126 3130
3127 IF_HAS_KEYWORDS(rword = pi->res_word;) 3131 IF_HAS_KEYWORDS(rword = pi->res_word;)
3128 IF_HAS_NO_KEYWORDS(rword = RES_NONE;) 3132 IF_HAS_NO_KEYWORDS(rword = RES_NONE;)
3129 debug_printf_exec(": rword=%d cond_code=%d skip_more=%d\n", 3133 debug_printf_exec(": rword=%d cond_code=%d last_rword=%d\n",
3130 rword, cond_code, skip_more_for_this_rword); 3134 rword, cond_code, last_rword);
3131#if ENABLE_HUSH_LOOPS 3135#if ENABLE_HUSH_LOOPS
3132 if ((rword == RES_WHILE || rword == RES_UNTIL || rword == RES_FOR) 3136 if ((rword == RES_WHILE || rword == RES_UNTIL || rword == RES_FOR)
3133 && loop_top == NULL /* avoid bumping G.depth_of_loop twice */ 3137 && loop_top == NULL /* avoid bumping G.depth_of_loop twice */
@@ -3137,15 +3141,20 @@ static int run_list(struct pipe *pi)
3137 G.depth_of_loop++; 3141 G.depth_of_loop++;
3138 } 3142 }
3139#endif 3143#endif
3140 if (rword == skip_more_for_this_rword && flag_skip) { 3144 /* Still in the same "if...", "then..." or "do..." branch? */
3141 if (pi->followup == PIPE_SEQ) 3145 if (rword == last_rword) {
3142 flag_skip = 0; 3146 if ((rcode == 0 && last_followup == PIPE_OR)
3143 /* it is "<false> && CMD" or "<true> || CMD" 3147 || (rcode != 0 && last_followup == PIPE_AND)
3144 * and we should not execute CMD */ 3148 ) {
3145 continue; 3149 /* It is "<true> || CMD" or "<false> && CMD"
3150 * and we should not execute CMD */
3151 debug_printf_exec("skipped cmd because of || or &&\n");
3152 last_followup = pi->followup;
3153 continue;
3154 }
3146 } 3155 }
3147 flag_skip = 1; 3156 last_followup = pi->followup;
3148 skip_more_for_this_rword = RES_XXXX; 3157 last_rword = rword;
3149#if ENABLE_HUSH_IF 3158#if ENABLE_HUSH_IF
3150 if (cond_code) { 3159 if (cond_code) {
3151 if (rword == RES_THEN) { 3160 if (rword == RES_THEN) {
@@ -3176,8 +3185,11 @@ static int run_list(struct pipe *pi)
3176 vals = (char**)encoded_dollar_at_argv; 3185 vals = (char**)encoded_dollar_at_argv;
3177 if (pi->next->res_word == RES_IN) { 3186 if (pi->next->res_word == RES_IN) {
3178 /* if no variable values after "in" we skip "for" */ 3187 /* if no variable values after "in" we skip "for" */
3179 if (!pi->next->cmds[0].argv) 3188 if (!pi->next->cmds[0].argv) {
3189 G.last_return_code = rcode = EXIT_SUCCESS;
3190 debug_printf_exec(": null FOR: exitcode EXIT_SUCCESS\n");
3180 break; 3191 break;
3192 }
3181 vals = pi->next->cmds[0].argv; 3193 vals = pi->next->cmds[0].argv;
3182 } /* else: "for var; do..." -> assume "$@" list */ 3194 } /* else: "for var; do..." -> assume "$@" list */
3183 /* create list of variable values */ 3195 /* create list of variable values */
@@ -3197,7 +3209,7 @@ static int run_list(struct pipe *pi)
3197 pi->cmds[0].argv[0] = for_varname; 3209 pi->cmds[0].argv[0] = for_varname;
3198 break; 3210 break;
3199 } 3211 }
3200 /* insert next value from for_lcur */ 3212 /* Insert next value from for_lcur */
3201//TODO: does it need escaping? 3213//TODO: does it need escaping?
3202 pi->cmds[0].argv[0] = xasprintf("%s=%s", for_varname, *for_lcur++); 3214 pi->cmds[0].argv[0] = xasprintf("%s=%s", for_varname, *for_lcur++);
3203 pi->cmds[0].assignment_cnt = 1; 3215 pi->cmds[0].assignment_cnt = 1;
@@ -3251,7 +3263,7 @@ static int run_list(struct pipe *pi)
3251 3263
3252 /* After analyzing all keywords and conditions, we decided 3264 /* After analyzing all keywords and conditions, we decided
3253 * to execute this pipe. NB: have to do checkjobs(NULL) 3265 * to execute this pipe. NB: have to do checkjobs(NULL)
3254 * after run_pipe() to collect any background children, 3266 * after run_pipe to collect any background children,
3255 * even if list execution is to be stopped. */ 3267 * even if list execution is to be stopped. */
3256 debug_printf_exec(": run_pipe with %d members\n", pi->num_cmds); 3268 debug_printf_exec(": run_pipe with %d members\n", pi->num_cmds);
3257 { 3269 {
@@ -3261,14 +3273,16 @@ static int run_list(struct pipe *pi)
3261#endif 3273#endif
3262 rcode = r = run_pipe(pi); /* NB: rcode is a smallint */ 3274 rcode = r = run_pipe(pi); /* NB: rcode is a smallint */
3263 if (r != -1) { 3275 if (r != -1) {
3264 /* we only ran a builtin: rcode is already known 3276 /* We only ran a builtin: rcode is already known
3265 * and we don't need to wait for anything. */ 3277 * and we don't need to wait for anything. */
3278 G.last_return_code = rcode;
3279 debug_printf_exec(": builtin exitcode %d\n", rcode);
3266 check_and_run_traps(0); 3280 check_and_run_traps(0);
3267#if ENABLE_HUSH_LOOPS 3281#if ENABLE_HUSH_LOOPS
3268 /* was it "break" or "continue"? */ 3282 /* Was it "break" or "continue"? */
3269 if (G.flag_break_continue) { 3283 if (G.flag_break_continue) {
3270 smallint fbc = G.flag_break_continue; 3284 smallint fbc = G.flag_break_continue;
3271 /* we might fall into outer *loop*, 3285 /* We might fall into outer *loop*,
3272 * don't want to break it too */ 3286 * don't want to break it too */
3273 if (loop_top) { 3287 if (loop_top) {
3274 G.depth_break_continue--; 3288 G.depth_break_continue--;
@@ -3284,7 +3298,7 @@ static int run_list(struct pipe *pi)
3284 } 3298 }
3285#endif 3299#endif
3286 } else if (pi->followup == PIPE_BG) { 3300 } else if (pi->followup == PIPE_BG) {
3287 /* what does bash do with attempts to background builtins? */ 3301 /* What does bash do with attempts to background builtins? */
3288 /* even bash 3.2 doesn't do that well with nested bg: 3302 /* even bash 3.2 doesn't do that well with nested bg:
3289 * try "{ { sleep 10; echo DEEP; } & echo HERE; } &". 3303 * try "{ { sleep 10; echo DEEP; } & echo HERE; } &".
3290 * I'm NOT treating inner &'s as jobs */ 3304 * I'm NOT treating inner &'s as jobs */
@@ -3293,25 +3307,26 @@ static int run_list(struct pipe *pi)
3293 if (G.run_list_level == 1) 3307 if (G.run_list_level == 1)
3294 insert_bg_job(pi); 3308 insert_bg_job(pi);
3295#endif 3309#endif
3296 rcode = 0; /* EXIT_SUCCESS */ 3310 rcode = EXIT_SUCCESS;
3311 G.last_return_code = EXIT_SUCCESS;
3312 debug_printf_exec(": cmd&: exitcode EXIT_SUCCESS\n");
3297 } else { 3313 } else {
3298#if ENABLE_HUSH_JOB 3314#if ENABLE_HUSH_JOB
3299 if (G.run_list_level == 1 && G_interactive_fd) { 3315 if (G.run_list_level == 1 && G_interactive_fd) {
3300 /* waits for completion, then fg's main shell */ 3316 /* Waits for completion, then fg's main shell */
3301 rcode = checkjobs_and_fg_shell(pi); 3317 rcode = checkjobs_and_fg_shell(pi);
3318 debug_printf_exec(": checkjobs_and_fg_shell exitcode %d\n", rcode);
3302 check_and_run_traps(0); 3319 check_and_run_traps(0);
3303 debug_printf_exec(": checkjobs_and_fg_shell returned %d\n", rcode);
3304 } else 3320 } else
3305#endif 3321#endif
3306 { /* this one just waits for completion */ 3322 { /* This one just waits for completion */
3307 rcode = checkjobs(pi); 3323 rcode = checkjobs(pi);
3324 debug_printf_exec(": checkjobs exitcode %d\n", rcode);
3308 check_and_run_traps(0); 3325 check_and_run_traps(0);
3309 debug_printf_exec(": checkjobs returned %d\n", rcode);
3310 } 3326 }
3327 G.last_return_code = rcode;
3311 } 3328 }
3312 } 3329 }
3313 debug_printf_exec(": setting last_return_code=%d\n", rcode);
3314 G.last_return_code = rcode;
3315 3330
3316 /* Analyze how result affects subsequent commands */ 3331 /* Analyze how result affects subsequent commands */
3317#if ENABLE_HUSH_IF 3332#if ENABLE_HUSH_IF
@@ -3333,11 +3348,6 @@ static int run_list(struct pipe *pi)
3333 } 3348 }
3334 } 3349 }
3335#endif 3350#endif
3336 if ((rcode == 0 && pi->followup == PIPE_OR)
3337 || (rcode != 0 && pi->followup == PIPE_AND)
3338 ) {
3339 skip_more_for_this_rword = rword;
3340 }
3341 3351
3342 check_jobs_and_continue: 3352 check_jobs_and_continue:
3343 checkjobs(NULL); 3353 checkjobs(NULL);
@@ -3375,7 +3385,7 @@ static int run_and_free_list(struct pipe *pi)
3375 int rcode = 0; 3385 int rcode = 0;
3376 debug_printf_exec("run_and_free_list entered\n"); 3386 debug_printf_exec("run_and_free_list entered\n");
3377 if (!G.fake_mode) { 3387 if (!G.fake_mode) {
3378 debug_printf_exec(": run_list with %d members\n", pi->num_cmds); 3388 debug_printf_exec(": run_list: 1st pipe with %d cmds\n", pi->num_cmds);
3379 rcode = run_list(pi); 3389 rcode = run_list(pi);
3380 } 3390 }
3381 /* free_pipe_list has the side effect of clearing memory. 3391 /* free_pipe_list has the side effect of clearing memory.