mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-07-05 11:20:50 +02:00
bash-5.1 beta release
This commit is contained in:
+114
-16
@@ -896,6 +896,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
|
||||
only the failure of a simple command. We don't want to run the error
|
||||
trap if the command run by the `command' builtin fails; we want to
|
||||
defer that until the command builtin itself returns failure. */
|
||||
/* 2020/07/14 -- this changes with how the command builtin is handled */
|
||||
if (was_error_trap && ignore_return == 0 && invert == 0 &&
|
||||
pipe_in == NO_PIPE && pipe_out == NO_PIPE &&
|
||||
(command->value.Simple->flags & CMD_COMMAND_BUILTIN) == 0 &&
|
||||
@@ -4161,6 +4162,52 @@ fix_assignment_words (words)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef ISOPTION
|
||||
# define ISOPTION(s, c) (s[0] == '-' && s[1] == c && s[2] == 0)
|
||||
#endif
|
||||
|
||||
#define RETURN_NOT_COMMAND() \
|
||||
do { if (typep) *typep = 0; return words; } while (0)
|
||||
|
||||
/* Make sure we have `command [-p] command_name [args]', and handle skipping
|
||||
over the usual `--' that ends the options. Returns the updated WORDS with
|
||||
the command and options stripped and sets *TYPEP to a non-zero value. If
|
||||
any other options are supplied, or there is not a command_name, we punt
|
||||
and return a zero value in *TYPEP without updating WORDS. */
|
||||
static WORD_LIST *
|
||||
check_command_builtin (words, typep)
|
||||
WORD_LIST *words;
|
||||
int *typep;
|
||||
{
|
||||
int type;
|
||||
WORD_LIST *w;
|
||||
|
||||
w = words->next;
|
||||
type = 1;
|
||||
|
||||
if (w && ISOPTION (w->word->word, 'p')) /* command -p */
|
||||
{
|
||||
#if defined (RESTRICTED_SHELL)
|
||||
if (restricted)
|
||||
RETURN_NOT_COMMAND();
|
||||
#endif
|
||||
w = w->next;
|
||||
type = 2;
|
||||
}
|
||||
|
||||
if (w && ISOPTION (w->word->word, '-')) /* command [-p] -- */
|
||||
w = w->next;
|
||||
else if (w && w->word->word[0] == '-') /* any other option */
|
||||
RETURN_NOT_COMMAND();
|
||||
|
||||
if (w == 0 || w->word->word == 0) /* must have a command_name */
|
||||
RETURN_NOT_COMMAND();
|
||||
|
||||
if (typep)
|
||||
*typep = type;
|
||||
return w;
|
||||
}
|
||||
|
||||
/* Return 1 if the file found by searching $PATH for PATHNAME, defaulting
|
||||
to PATHNAME, is a directory. Used by the autocd code below. */
|
||||
static int
|
||||
@@ -4188,7 +4235,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
|
||||
WORD_LIST *words, *lastword;
|
||||
char *command_line, *lastarg, *temp;
|
||||
int first_word_quoted, result, builtin_is_special, already_forked, dofork;
|
||||
int fork_flags;
|
||||
int fork_flags, cmdflags;
|
||||
pid_t old_last_async_pid;
|
||||
sh_builtin_func_t *builtin;
|
||||
SHELL_VAR *func;
|
||||
@@ -4233,6 +4280,8 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
|
||||
return (EXECUTION_SUCCESS);
|
||||
#endif
|
||||
|
||||
cmdflags = simple_command->flags;
|
||||
|
||||
first_word_quoted =
|
||||
simple_command->words ? (simple_command->words->word->flags & W_QUOTED) : 0;
|
||||
|
||||
@@ -4269,7 +4318,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
|
||||
if (make_child (p = savestring (the_printed_command_except_trap), fork_flags) == 0)
|
||||
{
|
||||
already_forked = 1;
|
||||
simple_command->flags |= CMD_NO_FORK;
|
||||
cmdflags |= CMD_NO_FORK;
|
||||
|
||||
subshell_environment = SUBSHELL_FORK; /* XXX */
|
||||
if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
|
||||
@@ -4318,15 +4367,15 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
|
||||
|
||||
/* If we are re-running this as the result of executing the `command'
|
||||
builtin, do not expand the command words a second time. */
|
||||
if ((simple_command->flags & CMD_INHIBIT_EXPANSION) == 0)
|
||||
if ((cmdflags & CMD_INHIBIT_EXPANSION) == 0)
|
||||
{
|
||||
current_fds_to_close = fds_to_close;
|
||||
fix_assignment_words (simple_command->words);
|
||||
/* Pass the ignore return flag down to command substitutions */
|
||||
if (simple_command->flags & CMD_IGNORE_RETURN) /* XXX */
|
||||
if (cmdflags & CMD_IGNORE_RETURN) /* XXX */
|
||||
comsub_ignore_return++;
|
||||
words = expand_words (simple_command->words);
|
||||
if (simple_command->flags & CMD_IGNORE_RETURN)
|
||||
if (cmdflags & CMD_IGNORE_RETURN)
|
||||
comsub_ignore_return--;
|
||||
current_fds_to_close = (struct fd_bitmap *)NULL;
|
||||
}
|
||||
@@ -4356,12 +4405,16 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
|
||||
|
||||
begin_unwind_frame ("simple-command");
|
||||
|
||||
if (echo_command_at_execute && (simple_command->flags & CMD_COMMAND_BUILTIN) == 0)
|
||||
if (echo_command_at_execute && (cmdflags & CMD_COMMAND_BUILTIN) == 0)
|
||||
xtrace_print_word_list (words, 1);
|
||||
|
||||
builtin = (sh_builtin_func_t *)NULL;
|
||||
func = (SHELL_VAR *)NULL;
|
||||
if ((simple_command->flags & CMD_NO_FUNCTIONS) == 0)
|
||||
|
||||
/* This test is still here in case we want to change the command builtin
|
||||
handler code below to recursively call execute_simple_command (after
|
||||
modifying the simple_command struct). */
|
||||
if ((cmdflags & CMD_NO_FUNCTIONS) == 0)
|
||||
{
|
||||
/* Posix.2 says special builtins are found before functions. We
|
||||
don't set builtin_is_special anywhere other than here, because
|
||||
@@ -4393,6 +4446,43 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
|
||||
}
|
||||
tempenv_assign_error = 0; /* don't care about this any more */
|
||||
|
||||
/* This is where we handle the command builtin as a pseudo-reserved word
|
||||
prefix. This allows us to optimize away forks if we can. */
|
||||
old_command_builtin = -1;
|
||||
if (builtin == 0 && func == 0)
|
||||
{
|
||||
WORD_LIST *disposer, *l;
|
||||
int cmdtype;
|
||||
|
||||
builtin = find_shell_builtin (words->word->word);
|
||||
while (builtin == command_builtin)
|
||||
{
|
||||
disposer = words;
|
||||
cmdtype = 0;
|
||||
words = check_command_builtin (words, &cmdtype);
|
||||
if (cmdtype > 0) /* command -p [--] words */
|
||||
{
|
||||
for (l = disposer; l->next != words; l = l->next)
|
||||
;
|
||||
l->next = 0;
|
||||
dispose_words (disposer);
|
||||
cmdflags |= CMD_COMMAND_BUILTIN | CMD_NO_FUNCTIONS;
|
||||
if (cmdtype == 2)
|
||||
cmdflags |= CMD_STDPATH;
|
||||
builtin = find_shell_builtin (words->word->word);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (cmdflags & CMD_COMMAND_BUILTIN)
|
||||
{
|
||||
old_command_builtin = executing_command_builtin;
|
||||
unwind_protect_int (executing_command_builtin);
|
||||
executing_command_builtin |= 1;
|
||||
}
|
||||
builtin = 0;
|
||||
}
|
||||
|
||||
add_unwind_protect (dispose_words, words);
|
||||
QUIT;
|
||||
|
||||
@@ -4469,9 +4559,12 @@ run_builtin:
|
||||
if (builtin)
|
||||
{
|
||||
old_builtin = executing_builtin;
|
||||
old_command_builtin = executing_command_builtin;
|
||||
unwind_protect_int (executing_builtin); /* modified in execute_builtin */
|
||||
unwind_protect_int (executing_command_builtin); /* ditto */
|
||||
if (old_command_builtin == -1) /* sentinel, can be set above */
|
||||
{
|
||||
old_command_builtin = executing_command_builtin;
|
||||
unwind_protect_int (executing_command_builtin); /* ditto and set above */
|
||||
}
|
||||
}
|
||||
if (already_forked)
|
||||
{
|
||||
@@ -4484,7 +4577,7 @@ run_builtin:
|
||||
|
||||
if (async)
|
||||
{
|
||||
if ((simple_command->flags & CMD_STDIN_REDIR) &&
|
||||
if ((cmdflags & CMD_STDIN_REDIR) &&
|
||||
pipe_in == NO_PIPE &&
|
||||
(stdin_redirects (simple_command->redirects) == 0))
|
||||
async_redirect_stdin ();
|
||||
@@ -4496,14 +4589,14 @@ run_builtin:
|
||||
execute_subshell_builtin_or_function
|
||||
(words, simple_command->redirects, builtin, func,
|
||||
pipe_in, pipe_out, async, fds_to_close,
|
||||
simple_command->flags);
|
||||
cmdflags);
|
||||
subshell_level--;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = execute_builtin_or_function
|
||||
(words, builtin, func, simple_command->redirects, fds_to_close,
|
||||
simple_command->flags);
|
||||
cmdflags);
|
||||
if (builtin)
|
||||
{
|
||||
if (result > EX_SHERRBASE)
|
||||
@@ -4569,12 +4662,12 @@ execute_from_filesystem:
|
||||
/* The old code did not test already_forked and only did this if
|
||||
subshell_environment&SUBSHELL_COMSUB != 0 (comsubs and procsubs). Other
|
||||
uses of the no-fork optimization left FIFOs in $TMPDIR */
|
||||
if (already_forked == 0 && (simple_command->flags & CMD_NO_FORK) && fifos_pending() > 0)
|
||||
simple_command->flags &= ~CMD_NO_FORK;
|
||||
if (already_forked == 0 && (cmdflags & CMD_NO_FORK) && fifos_pending() > 0)
|
||||
cmdflags &= ~CMD_NO_FORK;
|
||||
#endif
|
||||
result = execute_disk_command (words, simple_command->redirects, command_line,
|
||||
pipe_in, pipe_out, async, fds_to_close,
|
||||
simple_command->flags);
|
||||
cmdflags);
|
||||
|
||||
return_result:
|
||||
bind_lastarg (lastarg);
|
||||
@@ -4637,7 +4730,7 @@ execute_builtin (builtin, words, flags, subshell)
|
||||
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))
|
||||
(builtin == eval_builtin || (flags & CMD_COMMAND_BUILTIN) || builtin == source_builtin))
|
||||
{
|
||||
begin_unwind_frame ("eval_builtin");
|
||||
unwind_protect_int (exit_immediately_on_error);
|
||||
@@ -4831,6 +4924,11 @@ execute_function (var, words, flags, fds_to_close, async, subshell)
|
||||
if (tc && (flags & CMD_IGNORE_RETURN))
|
||||
tc->flags |= CMD_IGNORE_RETURN;
|
||||
|
||||
/* A limited attempt at optimization: shell functions at the end of command
|
||||
substitutions that are already marked NO_FORK. */
|
||||
if (tc && (flags & CMD_NO_FORK) && (subshell_environment & SUBSHELL_COMSUB))
|
||||
optimize_shell_function (tc);
|
||||
|
||||
gs = sh_getopt_save_istate ();
|
||||
if (subshell == 0)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user