commit bash-20080703 snapshot

This commit is contained in:
Chet Ramey
2011-12-07 09:25:28 -05:00
parent fdf670eaa1
commit 09767ff09d
113 changed files with 38264 additions and 36052 deletions
+327 -3
View File
@@ -181,6 +181,9 @@ static void execute_disk_command __P((WORD_LIST *, REDIRECT *, char *,
static char *getinterp __P((char *, int, int *));
static void initialize_subshell __P((void));
static int execute_in_subshell __P((COMMAND *, int, int, int, struct fd_bitmap *));
#if defined (COPROCESS_SUPPORT)
static int execute_coproc __P((COMMAND *, int, int, struct fd_bitmap *));
#endif
static int execute_pipeline __P((COMMAND *, int, int, int, struct fd_bitmap *));
@@ -540,6 +543,11 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
if (command->type == cm_subshell && (command->flags & CMD_NO_FORK))
return (execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close));
#if defined (COPROCESS_SUPPORT)
if (command->type == cm_coproc)
return (execute_coproc (command, pipe_in, pipe_out, fds_to_close));
#endif
if (command->type == cm_subshell ||
(command->flags & (CMD_WANT_SUBSHELL|CMD_FORCE_SUBSHELL)) ||
(shell_control_structure (command->type) &&
@@ -1199,10 +1207,11 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
struct fd_bitmap *fds_to_close;
{
int user_subshell, return_code, function_value, should_redir_stdin, invert;
int ois;
int ois, user_coproc;
COMMAND *tcom;
USE_VAR(user_subshell);
USE_VAR(user_coproc);
USE_VAR(invert);
USE_VAR(tcom);
USE_VAR(asynchronous);
@@ -1214,6 +1223,7 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
invert = (command->flags & CMD_INVERT_RETURN) != 0;
user_subshell = command->type == cm_subshell || ((command->flags & CMD_WANT_SUBSHELL) != 0);
user_coproc = command->type == cm_coproc;
command->flags &= ~(CMD_FORCE_SUBSHELL | CMD_WANT_SUBSHELL | CMD_INVERT_RETURN);
@@ -1266,6 +1276,8 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
subshell_environment |= SUBSHELL_ASYNC;
if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
subshell_environment |= SUBSHELL_PIPE;
if (user_coproc)
subshell_environment |= SUBSHELL_COPROC;
}
reset_terminating_signals (); /* in sig.c */
@@ -1299,6 +1311,10 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
do_piping (pipe_in, pipe_out);
#if defined (COPROCESS_SUPPORT)
coproc_close (&sh_coproc);
#endif
/* 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
@@ -1325,7 +1341,12 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
command->redirects = (REDIRECT *)NULL;
}
tcom = (command->type == cm_subshell) ? command->value.Subshell->command : command;
if (command->type == cm_subshell)
tcom = command->value.Subshell->command;
else if (user_coproc)
tcom = command->value.Coproc->command;
else
tcom = command;
if (command->flags & CMD_TIME_PIPELINE)
tcom->flags |= CMD_TIME_PIPELINE;
@@ -1341,7 +1362,7 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
This means things like ( sleep 10 ) will only cause one fork.
If we're timing the command or inverting its return value, however,
we cannot do this optimization. */
if (user_subshell && (tcom->type == cm_simple || tcom->type == cm_subshell) &&
if ((user_subshell || user_coproc) && (tcom->type == cm_simple || tcom->type == cm_subshell) &&
((tcom->flags & CMD_TIME_PIPELINE) == 0) &&
((tcom->flags & CMD_INVERT_RETURN) == 0))
{
@@ -1382,6 +1403,302 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
/* NOTREACHED */
}
#if defined (COPROCESS_SUPPORT)
Coproc sh_coproc = { 0, NO_PID, -1, -1, 0, 0 };
/* These currently use a single global "shell coproc" but are written in a
way to not preclude additional coprocs later */
struct coproc *
getcoprocbypid (pid)
pid_t pid;
{
return (pid == sh_coproc.c_pid ? &sh_coproc : 0);
}
struct coproc *
getcoprocbyname (name)
const char *name;
{
return ((sh_coproc.c_name && STREQ (sh_coproc.c_name, name)) ? &sh_coproc : 0);
}
void
coproc_init (cp)
struct coproc *cp;
{
cp->c_name = 0;
cp->c_pid = NO_PID;
cp->c_rfd = cp->c_wfd = -1;
cp->c_rsave = cp->c_wsave = -1;
cp->c_flags = cp->c_status = 0;
}
struct coproc *
coproc_alloc (name, pid)
char *name;
pid_t pid;
{
struct coproc *cp;
cp = &sh_coproc;
coproc_init (cp);
cp->c_name = savestring (name);
cp->c_pid = pid;
return (cp);
}
void
coproc_dispose (cp)
struct coproc *cp;
{
if (cp == 0)
return;
coproc_unsetvars (cp);
FREE (cp->c_name);
coproc_close (cp);
coproc_init (cp);
}
void
coproc_close (cp)
struct coproc *cp;
{
if (cp->c_rfd >= 0)
{
close (cp->c_rfd);
cp->c_rfd = -1;
}
if (cp->c_wfd >= 0)
{
close (cp->c_wfd);
cp->c_wfd = -1;
}
cp->c_rsave = cp->c_wsave = -1;
}
void
coproc_rclose (cp, fd)
struct coproc *cp;
int fd;
{
if (cp->c_rfd >= 0 && cp->c_rfd == fd)
{
close (cp->c_rfd);
cp->c_rfd = -1;
}
}
void
coproc_wclose (cp, fd)
struct coproc *cp;
int fd;
{
if (cp->c_wfd >= 0 && cp->c_wfd == fd)
{
close (cp->c_wfd);
cp->c_wfd = -1;
}
}
void
coproc_fdchk (cp, fd)
struct coproc *cp;
int fd;
{
int update;
update = 0;
if (cp->c_rfd >= 0 && cp->c_rfd == fd)
update = cp->c_rfd = -1;
if (cp->c_wfd >= 0 && cp->c_wfd == fd)
update = cp->c_wfd = -1;
if (update)
coproc_setvars (cp);
}
void
coproc_fdclose (cp, fd)
struct coproc *cp;
int fd;
{
coproc_rclose (cp, fd);
coproc_wclose (cp, fd);
coproc_setvars (cp);
}
void
coproc_fdsave (cp)
struct coproc *cp;
{
cp->c_rsave = cp->c_rfd;
cp->c_wsave = cp->c_wfd;
}
void
coproc_fdrestore (cp)
struct coproc *cp;
{
cp->c_rfd = cp->c_rsave;
cp->c_wfd = cp->c_wsave;
}
void
coproc_pidchk (pid)
pid_t pid;
{
struct coproc *cp;
cp = getcoprocbypid (pid);
if (cp)
coproc_dispose (cp);
}
void
coproc_setvars (cp)
struct coproc *cp;
{
SHELL_VAR *v;
char *namevar, *t;
int l;
#if defined (ARRAY_VARS)
arrayind_t ind;
#endif
if (cp->c_name == 0)
return;
l = strlen (cp->c_name);
namevar = xmalloc (l + 16);
#if defined (ARRAY_VARS)
v = find_variable (cp->c_name);
if (v == 0)
v = make_new_array_variable (cp->c_name);
if (array_p (v) == 0)
v = convert_var_to_array (v);
t = itos (cp->c_rfd);
ind = 0;
v = bind_array_variable (cp->c_name, ind, t, 0);
free (t);
t = itos (cp->c_wfd);
ind = 1;
bind_array_variable (cp->c_name, ind, t, 0);
free (t);
#else
sprintf (namevar, "%s_READ", cp->c_name);
t = itos (cp->c_rfd);
bind_variable (namevar, t, 0);
free (t);
sprintf (namevar, "%s_WRITE", cp->c_name);
t = itos (cp->c_wfd);
bind_variable (namevar, t, 0);
free (t);
#endif
sprintf (namevar, "%s_PID", cp->c_name);
t = itos (cp->c_pid);
bind_variable (namevar, t, 0);
free (t);
free (namevar);
}
void
coproc_unsetvars (cp)
struct coproc *cp;
{
int l;
char *namevar;
if (cp->c_name == 0)
return;
l = strlen (cp->c_name);
namevar = xmalloc (l + 16);
sprintf (namevar, "%s_PID", cp->c_name);
unbind_variable (namevar);
#if defined (ARRAY_VARS)
unbind_variable (cp->c_name);
#else
sprintf (namevar, "%s_READ", cp->c_name);
unbind_variable (namevar);
sprintf (namevar, "%s_WRITE", cp->c_name);
unbind_variable (namevar);
#endif
free (namevar);
}
static int
execute_coproc (command, pipe_in, pipe_out, fds_to_close)
COMMAND *command;
int pipe_in, pipe_out;
struct fd_bitmap *fds_to_close;
{
int rpipe[2], wpipe[2];
pid_t coproc_pid;
Coproc *cp;
char *tcmd;
if (sh_coproc.c_pid != -1)
{
internal_error ("execute_coproc: coproc [%d:%s] already exists", sh_coproc.c_pid, sh_coproc.c_name);
return (last_command_exit_value = EXECUTION_FAILURE);
}
coproc_init (&sh_coproc);
command_string_index = 0;
tcmd = make_command_string (command);
sh_openpipe ((int *)&rpipe); /* 0 = parent read, 1 = child write */
sh_openpipe ((int *)&wpipe); /* 0 = child read, 1 = parent write */
coproc_pid = make_child (savestring (tcmd), 1);
if (coproc_pid == 0)
{
close (rpipe[0]);
close (wpipe[1]);
exit (execute_in_subshell (command, 1, wpipe[0], rpipe[1], fds_to_close));
}
close (rpipe[1]);
close (wpipe[0]);
cp = coproc_alloc (command->value.Coproc->name, coproc_pid);
cp->c_rfd = rpipe[0];
cp->c_wfd = wpipe[1];
SET_CLOSE_ON_EXEC (cp->c_rfd);
SET_CLOSE_ON_EXEC (cp->c_wfd);
coproc_setvars (cp);
#if defined (DEBUG)
itrace ("execute_coproc: [%d] %s", coproc_pid, the_printed_command);
#endif
close_pipes (pipe_in, pipe_out);
#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
unlink_fifo_list ();
#endif
stop_pipeline (1, (COMMAND *)NULL);
DESCRIBE_PID (coproc_pid);
run_pending_traps ();
return (EXECUTION_SUCCESS);
}
#endif
static int
execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close)
COMMAND *command;
@@ -2692,6 +3009,10 @@ execute_null_command (redirects, pipe_in, pipe_out, async)
do_piping (pipe_in, pipe_out);
#if defined (COPROCESS_SUPPORT)
coproc_close (&sh_coproc);
#endif
subshell_environment = 0;
if (async)
subshell_environment |= SUBSHELL_ASYNC;
@@ -2894,6 +3215,9 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
do_piping (pipe_in, pipe_out);
pipe_in = pipe_out = NO_PIPE;
#if defined (COPROCESS_SUPPORT)
coproc_close (&sh_coproc);
#endif
last_asynchronous_pid = old_last_async_pid;
}