diff options
author | Jari Aalto <jari.aalto@cante.net> | 2000-03-17 21:46:59 +0000 |
---|---|---|
committer | Jari Aalto <jari.aalto@cante.net> | 2009-09-12 16:46:53 +0000 |
commit | bb70624e964126b7ac4ff085ba163a9c35ffa18f (patch) | |
tree | ba2dd4add13ada94b1899c6d4aca80195b80b74b /execute_cmd.c | |
parent | b72432fdcc59300c6fe7c9d6c8a31ad3447933f5 (diff) | |
download | android_external_bash-bb70624e964126b7ac4ff085ba163a9c35ffa18f.tar.gz android_external_bash-bb70624e964126b7ac4ff085ba163a9c35ffa18f.tar.bz2 android_external_bash-bb70624e964126b7ac4ff085ba163a9c35ffa18f.zip |
Imported from ../bash-2.04.tar.gz.
Diffstat (limited to 'execute_cmd.c')
-rw-r--r-- | execute_cmd.c | 638 |
1 files changed, 372 insertions, 266 deletions
diff --git a/execute_cmd.c b/execute_cmd.c index f2a2392..fd32f2f 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -6,7 +6,7 @@ Bash is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 1, or (at your option) + the Free Software Foundation; either version 2, or (at your option) any later version. Bash is distributed in the hope that it will be useful, but WITHOUT @@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along with Bash; see the file COPYING. If not, write to the Free - Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #include "config.h" #if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX) @@ -44,19 +44,7 @@ # include <limits.h> #endif -/* Some systems require this, mostly for the definition of `struct timezone'. - For example, Dynix/ptx has that definition in <time.h> rather than - sys/time.h */ -#if defined (TIME_WITH_SYS_TIME) -# include <sys/time.h> -# include <time.h> -#else -# if defined (HAVE_SYS_TIME_H) -# include <sys/time.h> -# else -# include <time.h> -# endif -#endif +#include "posixtime.h" #if defined (HAVE_SYS_RESOURCE_H) && !defined (RLIMTYPE) # include <sys/resource.h> @@ -145,6 +133,9 @@ static int execute_cond_command (); #if defined (COMMAND_TIMING) static int time_command (); #endif +#if defined (ARITH_FOR_COMMAND) +static int execute_arith_for_command (); +#endif static int execute_case_command (); static int execute_while_command (), execute_until_command (); static int execute_while_or_until (); @@ -158,6 +149,8 @@ static void execute_disk_command (); static int execute_connection (); static int execute_intern_function (); +static int execute_in_subshell (); + /* The line number that the currently executing function starts on. */ static int function_line_number; @@ -196,6 +189,9 @@ REDIRECT *exec_redirection_undo_list = (REDIRECT *)NULL; environment. */ int subshell_environment; +/* Currently-executing shell function. */ +SHELL_VAR *this_shell_function; + struct fd_bitmap *current_fds_to_close = (struct fd_bitmap *)NULL; #define FD_BITMAP_DEFAULT_SIZE 32L @@ -287,7 +283,10 @@ execute_command (command) discard_unwind_frame ("execute-command"); #if defined (PROCESS_SUBSTITUTION) - unlink_fifo_list (); + /* don't unlink fifos if we're in a shell function; wait until the function + returns. */ + if (variable_context == 0) + unlink_fifo_list (); #endif /* PROCESS_SUBSTITUTION */ return (result); @@ -301,6 +300,9 @@ shell_control_structure (type) switch (type) { case cm_for: +#if defined (ARITH_FOR_COMMAND) + case cm_arith_for: +#endif #if defined (SELECT_COMMAND) case cm_select: #endif @@ -443,8 +445,11 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, /* If a command was being explicitly run in a subshell, or if it is a shell control-structure, and it has a pipe, then we do the command in a subshell. */ + if (command->type == cm_subshell && (command->flags & CMD_NO_FORK)) + return (execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)); - if ((command->flags & (CMD_WANT_SUBSHELL|CMD_FORCE_SUBSHELL)) || + if (command->type == cm_subshell || + (command->flags & (CMD_WANT_SUBSHELL|CMD_FORCE_SUBSHELL)) || (shell_control_structure (command->type) && (pipe_out != NO_PIPE || pipe_in != NO_PIPE || asynchronous))) { @@ -455,134 +460,8 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, paren_pid = make_child (savestring (make_command_string (command)), asynchronous); if (paren_pid == 0) - { - int user_subshell, return_code, function_value, should_redir_stdin; - - should_redir_stdin = (asynchronous && (command->flags & CMD_STDIN_REDIR) && - pipe_in == NO_PIPE && - stdin_redirects (command->redirects) == 0); - - user_subshell = (command->flags & CMD_WANT_SUBSHELL) != 0; - command->flags &= ~(CMD_FORCE_SUBSHELL | CMD_WANT_SUBSHELL | CMD_INVERT_RETURN); - - /* If a command is asynchronous in a subshell (like ( foo ) & or - the special case of an asynchronous GROUP command where the - the subshell bit is turned on down in case cm_group: below), - turn off `asynchronous', so that two subshells aren't spawned. - - This seems semantically correct to me. For example, - ( foo ) & seems to say ``do the command `foo' in a subshell - environment, but don't wait for that subshell to finish'', - and "{ foo ; bar } &" seems to me to be like functions or - builtins in the background, which executed in a subshell - environment. I just don't see the need to fork two subshells. */ - - /* Don't fork again, we are already in a subshell. A `doubly - async' shell is not interactive, however. */ - if (asynchronous) - { -#if defined (JOB_CONTROL) - /* If a construct like ( exec xxx yyy ) & is given while job - control is active, we want to prevent exec from putting the - subshell back into the original process group, carefully - undoing all the work we just did in make_child. */ - original_pgrp = -1; -#endif /* JOB_CONTROL */ - interactive_shell = 0; - expand_aliases = 0; - asynchronous = 0; - } - - /* Subshells are neither login nor interactive. */ - login_shell = interactive = 0; - - subshell_environment = user_subshell ? SUBSHELL_PAREN : SUBSHELL_ASYNC; - - reset_terminating_signals (); /* in shell.c */ - /* Cancel traps, in trap.c. */ - restore_original_signals (); - if (asynchronous) - setup_async_signals (); - -#if defined (JOB_CONTROL) - set_sigchld_handler (); -#endif /* JOB_CONTROL */ - - set_sigint_handler (); - -#if defined (JOB_CONTROL) - /* Delete all traces that there were any jobs running. This is - only for subshells. */ - without_job_control (); -#endif /* JOB_CONTROL */ - do_piping (pipe_in, pipe_out); - - /* If this is a user subshell, set a flag if stdin was redirected. - This is used later to decide whether to redirect fd 0 to - /dev/null for async commands in the subshell. This adds more - sh compatibility, but I'm not sure it's the right thing to do. */ - if (user_subshell) - { - stdin_redir = stdin_redirects (command->redirects); - restore_default_signal (0); - } - - if (fds_to_close) - close_fd_bitmap (fds_to_close); - - /* If this is an asynchronous command (command &), we want to - redirect the standard input from /dev/null in the absence of - any specific redirection involving stdin. */ - if (should_redir_stdin && stdin_redir == 0) - async_redirect_stdin (); - - /* Do redirections, then dispose of them before recursive call. */ - if (command->redirects) - { - if (do_redirections (command->redirects, 1, 0, 0) != 0) - exit (EXECUTION_FAILURE); - - dispose_redirects (command->redirects); - command->redirects = (REDIRECT *)NULL; - } - - /* If this is a simple command, tell execute_disk_command that it - might be able to get away without forking and simply exec. - This means things like ( sleep 10 ) will only cause one fork. - If we're timing the command, however, we cannot do this - optimization. */ -#if 0 - if (user_subshell && command->type == cm_simple) -#else - if (user_subshell && command->type == cm_simple && (command->flags & CMD_TIME_PIPELINE) == 0) -#endif - { - command->flags |= CMD_NO_FORK; - command->value.Simple->flags |= CMD_NO_FORK; - } - - /* 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) - return_code = return_catch_value; - else - return_code = execute_command_internal - (command, asynchronous, NO_PIPE, NO_PIPE, fds_to_close); - - /* If we were explicitly placed in a subshell with (), we need - to do the `shell cleanup' things, such as running traps[0]. */ - if (user_subshell && signal_is_trapped (0)) - { - last_command_exit_value = return_code; - return_code = run_exit_trap (); - } - - exit (return_code); - } + exit (execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)); + /* NOTREACHED */ else { close_pipes (pipe_in, pipe_out); @@ -606,11 +485,13 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, /* If we have to, invert the return value. */ if (invert) - return ((last_command_exit_value == EXECUTION_SUCCESS) - ? EXECUTION_FAILURE - : EXECUTION_SUCCESS); + exec_result = ((last_command_exit_value == EXECUTION_SUCCESS) + ? EXECUTION_FAILURE + : EXECUTION_SUCCESS); else - return (last_command_exit_value); + exec_result = last_command_exit_value; + + return (last_command_exit_value = exec_result); } else { @@ -748,7 +629,10 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, } if (was_debug_trap) - run_debug_trap (); + { + last_command_exit_value = exec_result; + run_debug_trap (); + } if (ignore_return == 0 && invert == 0 && ((posixly_correct && interactive == 0 && special_builtin_failed) || @@ -767,6 +651,14 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, exec_result = execute_for_command (command->value.For); break; +#if defined (ARITH_FOR_COMMAND) + case cm_arith_for: + if (ignore_return) + command->value.ArithFor->flags |= CMD_IGNORE_RETURN; + exec_result = execute_arith_for_command (command->value.ArithFor); + break; +#endif + #if defined (SELECT_COMMAND) case cm_select: if (ignore_return) @@ -899,77 +791,12 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, } #if defined (COMMAND_TIMING) -#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY) -static struct timeval * -difftimeval (d, t1, t2) - struct timeval *d, *t1, *t2; -{ - d->tv_sec = t2->tv_sec - t1->tv_sec; - d->tv_usec = t2->tv_usec - t1->tv_usec; - if (d->tv_usec < 0) - { - d->tv_usec += 1000000; - d->tv_sec -= 1; - if (d->tv_sec < 0) /* ??? -- BSD/OS does this */ - { - d->tv_sec = 0; - d->tv_usec = 0; - } - } - return d; -} - -static struct timeval * -addtimeval (d, t1, t2) - struct timeval *d, *t1, *t2; -{ - d->tv_sec = t1->tv_sec + t2->tv_sec; - d->tv_usec = t1->tv_usec + t2->tv_usec; - if (d->tv_usec >= 1000000) - { - d->tv_usec -= 1000000; - d->tv_sec += 1; - } - return d; -} - -/* Do "cpu = ((user + sys) * 10000) / real;" with timevals. - Barely-tested code from Deven T. Corzine <deven@ties.org>. */ -static int -timeval_to_cpu (rt, ut, st) - struct timeval *rt, *ut, *st; /* real, user, sys */ -{ - struct timeval t1, t2; - register int i; - - addtimeval (&t1, ut, st); - t2.tv_sec = rt->tv_sec; - t2.tv_usec = rt->tv_usec; - - for (i = 0; i < 6; i++) - { - if ((t1.tv_sec > 99999999) || (t2.tv_sec > 99999999)) - break; - t1.tv_sec *= 10; - t1.tv_sec += t1.tv_usec / 100000; - t1.tv_usec *= 10; - t1.tv_usec %= 1000000; - t2.tv_sec *= 10; - t2.tv_sec += t2.tv_usec / 100000; - t2.tv_usec *= 10; - t2.tv_usec %= 1000000; - } - for (i = 0; i < 4; i++) - { - if (t1.tv_sec < 100000000) - t1.tv_sec *= 10; - else - t2.tv_sec /= 10; - } - return ((t2.tv_sec == 0) ? 0 : t1.tv_sec / t2.tv_sec); -} -#endif /* HAVE_GETRUSAGE && HAVE_GETTIMEOFDAY */ +#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY) +extern struct timeval *difftimeval(); +extern struct timeval *addtimeval(); +extern int timeval_to_cpu(); +#endif #define POSIX_TIMEFORMAT "real %2R\nuser %2U\nsys %2S" #define BASH_TIMEFORMAT "\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS" @@ -1229,6 +1056,146 @@ time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close) } #endif /* COMMAND_TIMING */ +/* Execute a command that's supposed to be in a subshell. This must be + called after make_child and we must be running in the child process. */ +static int +execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close) + COMMAND *command; + int asynchronous; + int pipe_in, pipe_out; + struct fd_bitmap *fds_to_close; +{ + int user_subshell, return_code, function_value, should_redir_stdin; + COMMAND *tcom; + + should_redir_stdin = (asynchronous && (command->flags & CMD_STDIN_REDIR) && + pipe_in == NO_PIPE && + stdin_redirects (command->redirects) == 0); + + user_subshell = command->type == cm_subshell || ((command->flags & CMD_WANT_SUBSHELL) != 0); + command->flags &= ~(CMD_FORCE_SUBSHELL | CMD_WANT_SUBSHELL | CMD_INVERT_RETURN); + + /* If a command is asynchronous in a subshell (like ( foo ) & or + the special case of an asynchronous GROUP command where the + the subshell bit is turned on down in case cm_group: below), + turn off `asynchronous', so that two subshells aren't spawned. + + This seems semantically correct to me. For example, + ( foo ) & seems to say ``do the command `foo' in a subshell + environment, but don't wait for that subshell to finish'', + and "{ foo ; bar ; } &" seems to me to be like functions or + builtins in the background, which executed in a subshell + environment. I just don't see the need to fork two subshells. */ + + /* Don't fork again, we are already in a subshell. A `doubly + async' shell is not interactive, however. */ + if (asynchronous) + { +#if defined (JOB_CONTROL) + /* If a construct like ( exec xxx yyy ) & is given while job + control is active, we want to prevent exec from putting the + subshell back into the original process group, carefully + undoing all the work we just did in make_child. */ + original_pgrp = -1; +#endif /* JOB_CONTROL */ + interactive_shell = 0; + expand_aliases = 0; + asynchronous = 0; + } + + /* Subshells are neither login nor interactive. */ + login_shell = interactive = 0; + + subshell_environment = user_subshell ? SUBSHELL_PAREN : SUBSHELL_ASYNC; + + reset_terminating_signals (); /* in sig.c */ + /* Cancel traps, in trap.c. */ + restore_original_signals (); + if (asynchronous) + setup_async_signals (); + +#if defined (JOB_CONTROL) + set_sigchld_handler (); +#endif /* JOB_CONTROL */ + + set_sigint_handler (); + +#if defined (JOB_CONTROL) + /* Delete all traces that there were any jobs running. This is + only for subshells. */ + without_job_control (); +#endif /* JOB_CONTROL */ + + if (fds_to_close) + close_fd_bitmap (fds_to_close); + + do_piping (pipe_in, pipe_out); + + /* If this is a user subshell, set a flag if stdin was redirected. + This is used later to decide whether to redirect fd 0 to + /dev/null for async commands in the subshell. This adds more + sh compatibility, but I'm not sure it's the right thing to do. */ + if (user_subshell) + { + stdin_redir = stdin_redirects (command->redirects); + restore_default_signal (0); + } + + /* If this is an asynchronous command (command &), we want to + redirect the standard input from /dev/null in the absence of + any specific redirection involving stdin. */ + if (should_redir_stdin && stdin_redir == 0) + async_redirect_stdin (); + + /* Do redirections, then dispose of them before recursive call. */ + if (command->redirects) + { + if (do_redirections (command->redirects, 1, 0, 0) != 0) + exit (EXECUTION_FAILURE); + + dispose_redirects (command->redirects); + command->redirects = (REDIRECT *)NULL; + } + + tcom = (command->type == cm_subshell) ? command->value.Subshell->command : command; + + /* If this is a simple command, tell execute_disk_command that it + might be able to get away without forking and simply exec. + This means things like ( sleep 10 ) will only cause one fork. + If we're timing the command, however, we cannot do this + optimization. */ + if (user_subshell && (tcom->type == cm_simple || tcom->type == cm_subshell) && + (tcom->flags & CMD_TIME_PIPELINE) == 0) + { + tcom->flags |= CMD_NO_FORK; + if (tcom->type == cm_simple) + tcom->value.Simple->flags |= CMD_NO_FORK; + } + + /* 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) + return_code = return_catch_value; + else + return_code = execute_command_internal + (tcom, asynchronous, NO_PIPE, NO_PIPE, fds_to_close); + + /* If we were explicitly placed in a subshell with (), we need + to do the `shell cleanup' things, such as running traps[0]. */ + if (user_subshell && signal_is_trapped (0)) + { + last_command_exit_value = return_code; + return_code = run_exit_trap (); + } + + return (return_code); + /* NOTREACHED */ +} + static int execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close) COMMAND *command; @@ -1489,24 +1456,13 @@ execute_connection (command, asynchronous, pipe_in, pipe_out, fds_to_close) return exec_result; } -#if defined (JOB_CONTROL) -# define REAP() \ - do \ - { \ - if (!interactive_shell) \ - reap_dead_jobs (); \ - } \ - while (0) -#else /* !JOB_CONTROL */ -# define REAP() \ - do \ - { \ - if (!interactive_shell) \ - cleanup_dead_jobs (); \ - } \ - while (0) -#endif /* !JOB_CONTROL */ - +#define REAP() \ + do \ + { \ + if (!interactive_shell) \ + reap_dead_jobs (); \ + } \ + while (0) /* Execute a FOR command. The syntax is: FOR word_desc IN word_list; DO command; DONE */ @@ -1612,6 +1568,107 @@ execute_for_command (for_command) return (retval); } +#if defined (ARITH_FOR_COMMAND) +/* Execute an arithmetic for command. The syntax is + + for (( init ; step ; test )) + do + body + done + + The execution should be exactly equivalent to + + eval \(\( init \)\) + while eval \(\( test \)\) ; do + body; + eval \(\( step \)\) + done +*/ +static long +eval_arith_for_expr (l, okp) + WORD_LIST *l; + int *okp; +{ + WORD_LIST *new; + long expresult; + + new = expand_words_no_vars (l); + if (echo_command_at_execute) + xtrace_print_arith_cmd (new); + expresult = evalexp (new->word->word, okp); + dispose_words (new); + return (expresult); +} + +static int +execute_arith_for_command (arith_for_command) + ARITH_FOR_COM *arith_for_command; +{ + long expresult; + int expok, result, body_status; + + body_status = EXECUTION_SUCCESS; + loop_level++; + + if (arith_for_command->flags & CMD_IGNORE_RETURN) + arith_for_command->action->flags |= CMD_IGNORE_RETURN; + + this_command_name = "(("; /* )) for expression error messages */ + + if (variable_context) + line_number = arith_for_command->line - function_line_number; + + /* Evaluate the initialization expression. */ + expresult = eval_arith_for_expr (arith_for_command->init, &expok); + if (expok == 0) + return (EXECUTION_FAILURE); + + while (1) + { + /* Evaluate the test expression. */ + expresult = eval_arith_for_expr (arith_for_command->test, &expok); + if (expok == 0) + { + body_status = EXECUTION_FAILURE; + break; + } + REAP (); + if (expresult == 0) + break; + + /* Execute the body of the arithmetic for command. */ + QUIT; + body_status = execute_command (arith_for_command->action); + QUIT; + + /* Handle any `break' or `continue' commands executed by the body. */ + if (breaking) + { + breaking--; + break; + } + + if (continuing) + { + continuing--; + if (continuing) + break; + } + + /* Evaluate the step expression. */ + expresult = eval_arith_for_expr (arith_for_command->step, &expok); + if (expok == 0) + { + body_status = EXECUTION_FAILURE; + break; + } + } + + loop_level--; + return (body_status); +} +#endif + #if defined (SELECT_COMMAND) static int LINES, COLS, tabsize; @@ -1863,6 +1920,13 @@ execute_select_command (select_command) breaking--; break; } + + if (continuing) + { + continuing--; + if (continuing) + break; + } } loop_level--; @@ -2198,7 +2262,7 @@ bind_lastarg (arg) if (arg == 0) arg = ""; var = bind_variable ("_", arg); - var->attributes &= ~att_exported; + VUNSETATTR (var, att_exported); } /* Execute a null command. Fork a subshell if the command uses pipes or is @@ -2207,7 +2271,8 @@ bind_lastarg (arg) static int execute_null_command (redirects, pipe_in, pipe_out, async, old_last_command_subst_pid) REDIRECT *redirects; - int pipe_in, pipe_out, async, old_last_command_subst_pid; + int pipe_in, pipe_out, async; + pid_t old_last_command_subst_pid; { if (pipe_in != NO_PIPE || pipe_out != NO_PIPE || async) { @@ -2330,11 +2395,21 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close) /* XXX memory leak if expand_words() error causes a jump_to_top_level */ command_line = savestring (the_printed_command); + /* Do this now, because execute_disk_command will do it anyway in the + vast majority of cases. */ + maybe_make_export_env (); + if (make_child (command_line, async) == 0) { already_forked = 1; simple_command->flags |= CMD_NO_FORK; + /* We need to do this before piping to handle some really + pathological cases where one of the pipe file descriptors + is < 2. */ + if (fds_to_close) + close_fd_bitmap (fds_to_close); + do_piping (pipe_in, pipe_out); pipe_in = pipe_out = -1; @@ -2681,6 +2756,7 @@ execute_function (var, words, flags, fds_to_close, async, subshell) int return_val, result; COMMAND *tc, *fc; char *debug_trap; + SHELL_VAR *old_shell_function; tc = (COMMAND *)copy_command (function_cell (var)); if (tc && (flags & CMD_IGNORE_RETURN)) @@ -2695,9 +2771,13 @@ execute_function (var, words, flags, fds_to_close, async, subshell) unwind_protect_int (return_catch_flag); unwind_protect_jmp_buf (return_catch); add_unwind_protect (dispose_command, (char *)tc); + unwind_protect_pointer (this_shell_function); unwind_protect_int (loop_level); } + this_shell_function = var; + make_funcname_visible (1); + debug_trap = (signal_is_trapped (DEBUG_TRAP) && signal_is_ignored (DEBUG_TRAP) == 0) ? trap_list[DEBUG_TRAP] : (char *)NULL; @@ -2761,9 +2841,34 @@ execute_function (var, words, flags, fds_to_close, async, subshell) if (subshell == 0) run_unwind_frame ("function_calling"); + if (variable_context == 0 || this_shell_function == 0) + make_funcname_visible (0); + return (result); } +/* A convenience routine for use by other parts of the shell to execute + a particular shell function. */ +int +execute_shell_function (var, words) + SHELL_VAR *var; + WORD_LIST *words; +{ + int ret; + struct fd_bitmap *bitmap; + + bitmap = new_fd_bitmap (FD_BITMAP_DEFAULT_SIZE); + begin_unwind_frame ("execute-shell-function"); + add_unwind_protect (dispose_fd_bitmap, (char *)bitmap); + + ret = execute_function (var, words, 0, bitmap, 0, 0); + + dispose_fd_bitmap (bitmap); + discard_unwind_frame ("execute-shell-function"); + + return ret; +} + /* Execute a shell builtin or function in a subshell environment. This routine does not return; it only calls exit(). If BUILTIN is non-null, it points to a function to call to execute a shell builtin; otherwise @@ -2782,13 +2887,16 @@ execute_subshell_builtin_or_function (words, redirects, builtin, var, struct fd_bitmap *fds_to_close; int flags; { - int result, r, jobs_hack; - - /* A subshell is neither a login shell nor interactive. */ - login_shell = interactive = 0; + int result, r; +#if defined (JOB_CONTROL) + int jobs_hack; jobs_hack = (builtin == jobs_builtin) && ((subshell_environment & SUBSHELL_ASYNC) == 0 || pipe_out != NO_PIPE); +#endif + + /* A subshell is neither a login shell nor interactive. */ + login_shell = interactive = 0; subshell_environment = SUBSHELL_ASYNC; @@ -2810,11 +2918,11 @@ execute_subshell_builtin_or_function (words, redirects, builtin, var, set_sigint_handler (); - do_piping (pipe_in, pipe_out); - if (fds_to_close) close_fd_bitmap (fds_to_close); + do_piping (pipe_in, pipe_out); + if (do_redirections (redirects, 1, 0, 0) != 0) exit (EXECUTION_FAILURE); @@ -2955,7 +3063,7 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out, { char *pathname, *command, **args; int nofork; - int pid; + pid_t pid; nofork = (cmdflags & CMD_NO_FORK); /* Don't fork, just exec, if no pipes */ pathname = words->word->word; @@ -2978,7 +3086,7 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out, put_command_name_into_env (command); } - /* We have to make the child before we check for the non-existance + /* We have to make the child before we check for the non-existence of COMMAND, since we want the error messages to be redirected. */ /* If we can get away without forking and there are no pipes to deal with, don't bother to fork, just directly exec the command. */ @@ -3014,6 +3122,14 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out, setup_async_signals (); } + /* This functionality is now provided by close-on-exec of the + file descriptors manipulated by redirection and piping. + Some file descriptors still need to be closed in all children + because of the way bash does pipes; fds_to_close is a + bitmap of all such file descriptors. */ + if (fds_to_close) + close_fd_bitmap (fds_to_close); + do_piping (pipe_in, pipe_out); if (async) @@ -3024,14 +3140,6 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out, subshell_environment = SUBSHELL_FORK; - /* This functionality is now provided by close-on-exec of the - file descriptors manipulated by redirection and piping. - Some file descriptors still need to be closed in all children - because of the way bash does pipes; fds_to_close is a - bitmap of all such file descriptors. */ - if (fds_to_close) - close_fd_bitmap (fds_to_close); - if (redirects && (do_redirections (redirects, 1, 0, 0) != 0)) { #if defined (PROCESS_SUBSTITUTION) @@ -3098,10 +3206,14 @@ execute_shell_script (sample, sample_len, command, args, env) i++) ; +#if 1 + execname = substring ((char *)sample, start, i); +#else larry = i - start; execname = xmalloc (1 + larry); strncpy (execname, (char *)(sample + start), larry); execname[larry] = '\0'; +#endif size_increment = 1; /* Now the argument, if any. */ @@ -3119,10 +3231,14 @@ execute_shell_script (sample, sample_len, command, args, env) !whitespace (sample[i]) && sample[i] != '\n' && i < sample_len; i++) ; +#if 1 + firstarg = substring ((char *)sample, start, i); +#else larry = i - start; firstarg = xmalloc (1 + larry); strncpy (firstarg, (char *)(sample + start), larry); firstarg[larry] = '\0'; +#endif size_increment = 2; } @@ -3363,9 +3479,6 @@ do_piping (pipe_in, pipe_out) sys_error ("cannot duplicate fd %d to fd 0", pipe_in); if (pipe_in > 0) close (pipe_in); -#ifdef __CYGWIN32__ - setmode (0, O_TEXT); -#endif } if (pipe_out != NO_PIPE) { @@ -3375,18 +3488,11 @@ do_piping (pipe_in, pipe_out) sys_error ("cannot duplicate fd %d to fd 1", pipe_out); if (pipe_out == 0 || pipe_out > 1) close (pipe_out); -#ifdef __CYGWIN32__ - setmode (1, O_TEXT); -#endif } else { if (dup2 (1, 2) < 0) sys_error ("cannot duplicate fd 1 to fd 2"); -#ifdef __CYGWIN32__ - setmode (1, O_TEXT); - setmode (2, O_TEXT); -#endif } } } |