Imported from ../bash-2.04.tar.gz.

This commit is contained in:
Jari Aalto
2000-03-17 21:46:59 +00:00
parent b72432fdcc
commit bb70624e96
387 changed files with 28522 additions and 9334 deletions

View File

@@ -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 */
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
}
}
}