[git commit] hush: case logic for setting $? was still wrong

Denys Vlasenko vda.linux at googlemail.com
Fri Nov 4 19:14:04 UTC 2016


commit: https://git.busybox.net/busybox/commit/?id=aeaee43d5a4fc95405cc2047227d096b1ada55b6
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

Resetting to 0 should happen in "esac". Matched branch must
still see previous $?.

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 shell/hush.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/shell/hush.c b/shell/hush.c
index 4c2ed6c..0bc67ec 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -7874,14 +7874,14 @@ static int run_list(struct pipe *pi)
 #endif
 #if ENABLE_HUSH_CASE
 		if (rword == RES_CASE) {
-			/* Case which does not match and execute anything still sets $? to 0 */
-			G.last_exitcode = rcode = EXIT_SUCCESS;
+			debug_printf_exec("CASE cond_code:%d\n", cond_code);
 			case_word = expand_strvec_to_string(pi->cmds->argv);
 			continue;
 		}
 		if (rword == RES_MATCH) {
 			char **argv;
 
+			debug_printf_exec("MATCH cond_code:%d\n", cond_code);
 			if (!case_word) /* "case ... matched_word) ... WORD)": we executed selected branch, stop */
 				break;
 			/* all prev words didn't match, does this one match? */
@@ -7892,8 +7892,8 @@ static int run_list(struct pipe *pi)
 				cond_code = (fnmatch(pattern, case_word, /*flags:*/ 0) != 0);
 				free(pattern);
 				if (cond_code == 0) { /* match! we will execute this branch */
-					free(case_word); /* make future "word)" stop */
-					case_word = NULL;
+					free(case_word);
+					case_word = NULL; /* make future "word)" stop */
 					break;
 				}
 				argv++;
@@ -7901,9 +7901,17 @@ static int run_list(struct pipe *pi)
 			continue;
 		}
 		if (rword == RES_CASE_BODY) { /* inside of a case branch */
+			debug_printf_exec("CASE_BODY cond_code:%d\n", cond_code);
 			if (cond_code != 0)
 				continue; /* not matched yet, skip this pipe */
 		}
+		if (rword == RES_ESAC) {
+			debug_printf_exec("ESAC cond_code:%d\n", cond_code);
+			if (case_word) {
+				/* "case" did not match anything: still set $? (to 0) */
+				G.last_exitcode = rcode = EXIT_SUCCESS;
+			}
+		}
 #endif
 		/* Just pressing <enter> in shell should check for jobs.
 		 * OTOH, in non-interactive shell this is useless


More information about the busybox-cvs mailing list