diff options
author | Chet Ramey <chet.ramey@case.edu> | 2011-11-21 20:51:19 -0500 |
---|---|---|
committer | Chet Ramey <chet.ramey@case.edu> | 2011-11-21 20:51:19 -0500 |
commit | 0001803f0b9523c94fa2ede48eaecb047fef4524 (patch) | |
tree | f334332811e033ff966d94f6268f0629a94304b3 /execute_cmd.c | |
parent | 89a92869e56aba4e4cab2d639c00a86f0545c862 (diff) | |
download | android_external_bash-0001803f0b9523c94fa2ede48eaecb047fef4524.tar.gz android_external_bash-0001803f0b9523c94fa2ede48eaecb047fef4524.tar.bz2 android_external_bash-0001803f0b9523c94fa2ede48eaecb047fef4524.zip |
Bash-4.1 distribution source
Diffstat (limited to 'execute_cmd.c')
-rw-r--r-- | execute_cmd.c | 154 |
1 files changed, 132 insertions, 22 deletions
diff --git a/execute_cmd.c b/execute_cmd.c index 9761125..e65a03f 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -57,6 +57,8 @@ extern int errno; #endif +#define NEED_FPURGE_DECL + #include "bashansi.h" #include "bashintl.h" @@ -100,7 +102,7 @@ extern int posixly_correct; extern int expand_aliases; extern int autocd; extern int breaking, continuing, loop_level; -extern int parse_and_execute_level, running_trap; +extern int parse_and_execute_level, running_trap, sourcelevel; extern int command_string_index, line_number; extern int dot_found_in_search; extern int already_making_children; @@ -267,6 +269,10 @@ static int showing_function_line; static int line_number_for_err_trap; +/* A sort of function nesting level counter */ +static int funcnest = 0; +int funcnest_max = 0; /* XXX - for bash-4.2 */ + struct fd_bitmap *current_fds_to_close = (struct fd_bitmap *)NULL; #define FD_BITMAP_DEFAULT_SIZE 32 @@ -607,7 +613,6 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, else exec_result = last_command_exit_value; - if (user_subshell && was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS) { last_command_exit_value = exec_result; @@ -883,19 +888,58 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, #if defined (DPAREN_ARITHMETIC) case cm_arith: + was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0; if (ignore_return) command->value.Arith->flags |= CMD_IGNORE_RETURN; + line_number_for_err_trap = save_line_number = line_number; exec_result = execute_arith_command (command->value.Arith); + line_number = save_line_number; + + if (was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS) + { + last_command_exit_value = exec_result; + save_line_number = line_number; + line_number = line_number_for_err_trap; + run_error_trap (); + line_number = save_line_number; + } + + if (ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS) + { + last_command_exit_value = exec_result; + run_pending_traps (); + jump_to_top_level (ERREXIT); + } + break; #endif #if defined (COND_COMMAND) case cm_cond: + was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0; if (ignore_return) command->value.Cond->flags |= CMD_IGNORE_RETURN; - save_line_number = line_number; + + line_number_for_err_trap = save_line_number = line_number; exec_result = execute_cond_command (command->value.Cond); line_number = save_line_number; + + if (was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS) + { + last_command_exit_value = exec_result; + save_line_number = line_number; + line_number = line_number_for_err_trap; + run_error_trap (); + line_number = save_line_number; + } + + if (ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS) + { + last_command_exit_value = exec_result; + run_pending_traps (); + jump_to_top_level (ERREXIT); + } + break; #endif @@ -1248,6 +1292,7 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close) { int user_subshell, return_code, function_value, should_redir_stdin, invert; int ois, user_coproc; + int result; COMMAND *tcom; USE_VAR(user_subshell); @@ -1414,13 +1459,21 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close) invert = (tcom->flags & CMD_INVERT_RETURN) != 0; tcom->flags &= ~CMD_INVERT_RETURN; + result = setjmp (top_level); + /* If we're inside a function while executing this subshell, we need to handle a possible `return'. */ function_value = 0; if (return_catch_flag) function_value = setjmp (return_catch); - if (function_value) + /* If we're going to exit the shell, we don't want to invert the return + status. */ + if (result == EXITPROG) + invert = 0, return_code = last_command_exit_value; + else if (result) + return_code = EXECUTION_FAILURE; + else if (function_value) return_code = return_catch_value; else return_code = execute_command_internal (tcom, asynchronous, NO_PIPE, NO_PIPE, fds_to_close); @@ -1928,7 +1981,7 @@ execute_coproc (command, pipe_in, pipe_out, fds_to_close) int pipe_in, pipe_out; struct fd_bitmap *fds_to_close; { - int rpipe[2], wpipe[2]; + int rpipe[2], wpipe[2], estat; pid_t coproc_pid; Coproc *cp; char *tcmd; @@ -1957,7 +2010,12 @@ execute_coproc (command, pipe_in, pipe_out, fds_to_close) close (rpipe[0]); close (wpipe[1]); - exit (execute_in_subshell (command, 1, wpipe[0], rpipe[1], fds_to_close)); + estat = execute_in_subshell (command, 1, wpipe[0], rpipe[1], fds_to_close); + + fflush (stdout); + fflush (stderr); + + exit (estat); } close (rpipe[1]); @@ -3156,11 +3214,19 @@ static int execute_cond_node (cond) COND_COM *cond; { - int result, invert, patmatch, rmatch, mflags; + int result, invert, patmatch, rmatch, mflags, ignore; char *arg1, *arg2; invert = (cond->flags & CMD_INVERT_RETURN); - + ignore = (cond->flags & CMD_IGNORE_RETURN); + if (ignore) + { + if (cond->left) + cond->left->flags |= CMD_IGNORE_RETURN; + if (cond->right) + cond->right->flags |= CMD_IGNORE_RETURN; + } + if (cond->type == COND_EXPR) result = execute_cond_node (cond->left); else if (cond->type == COND_OR) @@ -3177,7 +3243,11 @@ execute_cond_node (cond) } else if (cond->type == COND_UNARY) { + if (ignore) + comsub_ignore_return++; arg1 = cond_expand_word (cond->left->op, 0); + if (ignore) + comsub_ignore_return--; if (arg1 == 0) arg1 = nullstr; if (echo_command_at_execute) @@ -3197,11 +3267,19 @@ execute_cond_node (cond) cond->op->word[2] == '\0'); #endif + if (ignore) + comsub_ignore_return++; arg1 = cond_expand_word (cond->left->op, 0); + if (ignore) + comsub_ignore_return--; if (arg1 == 0) arg1 = nullstr; + if (ignore) + comsub_ignore_return++; arg2 = cond_expand_word (cond->right->op, (rmatch && shell_compatibility_level > 31) ? 2 : (patmatch ? 1 : 0)); + if (ignore) + comsub_ignore_return--; if (arg2 == 0) arg2 = nullstr; @@ -3224,7 +3302,7 @@ execute_cond_node (cond) int oe; oe = extended_glob; extended_glob = 1; - result = binary_test (cond->op->word, arg1, arg2, TEST_PATMATCH|TEST_ARITHEXP) + result = binary_test (cond->op->word, arg1, arg2, TEST_PATMATCH|TEST_ARITHEXP|TEST_LOCALE) ? EXECUTION_SUCCESS : EXECUTION_FAILURE; extended_glob = oe; @@ -3261,7 +3339,6 @@ execute_cond_command (cond_command) /* If we're in a function, update the line number information. */ if (variable_context && interactive_shell) line_number -= function_line_number; - command_string_index = 0; print_cond_command (cond_command); @@ -3315,8 +3392,13 @@ execute_null_command (redirects, pipe_in, pipe_out, async) int pipe_in, pipe_out, async; { int r; + int forcefork; + REDIRECT *rd; - if (pipe_in != NO_PIPE || pipe_out != NO_PIPE || async) + for (forcefork = 0, rd = redirects; rd; rd = rd->next) + forcefork += rd->rflags & REDIR_VARASSIGN; + + if (forcefork || pipe_in != NO_PIPE || pipe_out != NO_PIPE || async) { /* We have a null command, but we really want a subshell to take care of it. Just fork, do piping and redirections, and exit. */ @@ -3457,7 +3539,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close) command_line = (char *)0; /* If we're in a function, update the line number information. */ - if (variable_context && interactive_shell) + if (variable_context && interactive_shell && sourcelevel == 0) line_number -= function_line_number; /* Remember what this command line looks like at invocation. */ @@ -3814,25 +3896,35 @@ execute_builtin (builtin, words, flags, subshell) { int old_e_flag, result, eval_unwind; int isbltinenv; + char *error_trap; #if 0 /* XXX -- added 12/11 */ terminate_immediately++; #endif + error_trap = 0; old_e_flag = exit_immediately_on_error; /* The eval builtin calls parse_and_execute, which does not know about the setting of flags, and always calls the execution functions with flags that will exit the shell on an error if -e is set. If the eval builtin is being called, and we're supposed to ignore the exit - value of the command, we turn the -e flag off ourselves, then - restore it when the command completes. This is also a problem (as - below) for the command and source/. builtins. */ + value of the command, we turn the -e flag off ourselves and disable + the ERR trap, then restore them when the command completes. This is + also a problem (as below) for the command and source/. builtins. */ if (subshell == 0 && (flags & CMD_IGNORE_RETURN) && (builtin == eval_builtin || builtin == command_builtin || builtin == source_builtin)) { begin_unwind_frame ("eval_builtin"); unwind_protect_int (exit_immediately_on_error); + error_trap = TRAP_STRING (ERROR_TRAP); + if (error_trap) + { + error_trap = savestring (error_trap); + add_unwind_protect (xfree, error_trap); + add_unwind_protect (set_error_trap, error_trap); + restore_default_signal (ERROR_TRAP); + } exit_immediately_on_error = 0; eval_unwind = 1; } @@ -3883,6 +3975,11 @@ execute_builtin (builtin, words, flags, subshell) if (eval_unwind) { exit_immediately_on_error += old_e_flag; + if (error_trap) + { + set_error_trap (error_trap); + xfree (error_trap); + } discard_unwind_frame ("eval_builtin"); } @@ -3911,10 +4008,17 @@ execute_function (var, words, flags, fds_to_close, async, subshell) #endif FUNCTION_DEF *shell_fn; char *sfile, *t; - static int funcnest = 0; USE_VAR(fc); +#if 0 /* for bash-4.2 */ + if (funcnest_max > 0 && funcnest >= funcnest_max) + { + internal_error ("%s: maximum function nesting level exceeded (%d)", var->name, funcnest); + jump_to_top_level (DISCARD); + } +#endif + #if defined (ARRAY_VARS) GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v, funcname_a); GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v, bash_source_a); @@ -3936,6 +4040,7 @@ execute_function (var, words, flags, fds_to_close, async, subshell) add_unwind_protect (dispose_command, (char *)tc); unwind_protect_pointer (this_shell_function); unwind_protect_int (loop_level); + unwind_protect_int (funcnest); } else push_context (var->name, subshell, temporary_env); /* don't unwind-protect for subshells */ @@ -4077,7 +4182,6 @@ execute_function (var, words, flags, fds_to_close, async, subshell) if (subshell == 0) run_unwind_frame ("function_calling"); - funcnest--; #if defined (ARRAY_VARS) /* These two variables cannot be unset, and cannot be affected by the function. */ @@ -4092,8 +4196,13 @@ execute_function (var, words, flags, fds_to_close, async, subshell) #endif if (variable_context == 0 || this_shell_function == 0) - make_funcname_visible (0); - + { + make_funcname_visible (0); +#if defined (PROCESS_SUBSTITUTION) + unlink_fifo_list (); +#endif + } + return (result); } @@ -4369,7 +4478,7 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out, #if defined (RESTRICTED_SHELL) command = (char *)NULL; - if (restricted && xstrchr (pathname, '/')) + if (restricted && mbschr (pathname, '/')) { internal_error (_("%s: restricted: cannot specify `/' in command names"), pathname); @@ -4482,7 +4591,8 @@ parent_return: /* Make sure that the pipes are closed in the parent. */ close_pipes (pipe_in, pipe_out); #if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD) - unlink_fifo_list (); + if (variable_context == 0) + unlink_fifo_list (); #endif FREE (command); } @@ -4631,7 +4741,7 @@ initialize_subshell () parse_and_execute_level = 0; /* nothing left to restore it */ /* We're no longer inside a shell function. */ - variable_context = return_catch_flag = 0; + variable_context = return_catch_flag = funcnest = 0; executing_list = 0; /* XXX */ |