bash-5.1-alpha release

This commit is contained in:
Chet Ramey
2020-06-15 15:57:21 -04:00
parent 9e49d343e3
commit 712f80b0a4
806 changed files with 88194 additions and 53253 deletions
+214 -187
View File
@@ -1,6 +1,6 @@
/* execute_cmd.c -- Execute a COMMAND structure. */
/* Copyright (C) 1987-2018 Free Software Foundation, Inc.
/* Copyright (C) 1987-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -109,89 +109,90 @@ extern int errno;
extern int command_string_index;
extern char *the_printed_command;
extern time_t shell_start_time;
#if defined (HAVE_GETTIMEOFDAY)
extern struct timeval shellstart;
#endif
#if 0
extern char *glob_argv_flags;
#endif
extern int close __P((int));
extern int close PARAMS((int));
/* Static functions defined and used in this file. */
static void close_pipes __P((int, int));
static void do_piping __P((int, int));
static void bind_lastarg __P((char *));
static int shell_control_structure __P((enum command_type));
static void cleanup_redirects __P((REDIRECT *));
static void close_pipes PARAMS((int, int));
static void do_piping PARAMS((int, int));
static void bind_lastarg PARAMS((char *));
static int shell_control_structure PARAMS((enum command_type));
static void cleanup_redirects PARAMS((REDIRECT *));
#if defined (JOB_CONTROL)
static int restore_signal_mask __P((sigset_t *));
static int restore_signal_mask PARAMS((sigset_t *));
#endif
static void async_redirect_stdin __P((void));
static int builtin_status PARAMS((int));
static int builtin_status __P((int));
static int execute_for_command __P((FOR_COM *));
static int execute_for_command PARAMS((FOR_COM *));
#if defined (SELECT_COMMAND)
static int displen __P((const char *));
static int print_index_and_element __P((int, int, WORD_LIST *));
static void indent __P((int, int));
static void print_select_list __P((WORD_LIST *, int, int, int));
static char *select_query __P((WORD_LIST *, int, char *, int));
static int execute_select_command __P((SELECT_COM *));
static int displen PARAMS((const char *));
static int print_index_and_element PARAMS((int, int, WORD_LIST *));
static void indent PARAMS((int, int));
static void print_select_list PARAMS((WORD_LIST *, int, int, int));
static char *select_query PARAMS((WORD_LIST *, int, char *, int));
static int execute_select_command PARAMS((SELECT_COM *));
#endif
#if defined (DPAREN_ARITHMETIC)
static int execute_arith_command __P((ARITH_COM *));
static int execute_arith_command PARAMS((ARITH_COM *));
#endif
#if defined (COND_COMMAND)
static int execute_cond_node __P((COND_COM *));
static int execute_cond_command __P((COND_COM *));
static int execute_cond_node PARAMS((COND_COM *));
static int execute_cond_command PARAMS((COND_COM *));
#endif
#if defined (COMMAND_TIMING)
static int mkfmt __P((char *, int, int, time_t, int));
static void print_formatted_time __P((FILE *, char *,
static int mkfmt PARAMS((char *, int, int, time_t, int));
static void print_formatted_time PARAMS((FILE *, char *,
time_t, int, time_t, int,
time_t, int, int));
static int time_command __P((COMMAND *, int, int, int, struct fd_bitmap *));
static int time_command PARAMS((COMMAND *, int, int, int, struct fd_bitmap *));
#endif
#if defined (ARITH_FOR_COMMAND)
static intmax_t eval_arith_for_expr __P((WORD_LIST *, int *));
static int execute_arith_for_command __P((ARITH_FOR_COM *));
static intmax_t eval_arith_for_expr PARAMS((WORD_LIST *, int *));
static int execute_arith_for_command PARAMS((ARITH_FOR_COM *));
#endif
static int execute_case_command __P((CASE_COM *));
static int execute_while_command __P((WHILE_COM *));
static int execute_until_command __P((WHILE_COM *));
static int execute_while_or_until __P((WHILE_COM *, int));
static int execute_if_command __P((IF_COM *));
static int execute_null_command __P((REDIRECT *, int, int, int));
static void fix_assignment_words __P((WORD_LIST *));
static int execute_simple_command __P((SIMPLE_COM *, int, int, int, struct fd_bitmap *));
static int execute_builtin __P((sh_builtin_func_t *, WORD_LIST *, int, int));
static int execute_function __P((SHELL_VAR *, WORD_LIST *, int, struct fd_bitmap *, int, int));
static int execute_builtin_or_function __P((WORD_LIST *, sh_builtin_func_t *,
static int execute_case_command PARAMS((CASE_COM *));
static int execute_while_command PARAMS((WHILE_COM *));
static int execute_until_command PARAMS((WHILE_COM *));
static int execute_while_or_until PARAMS((WHILE_COM *, int));
static int execute_if_command PARAMS((IF_COM *));
static int execute_null_command PARAMS((REDIRECT *, int, int, int));
static void fix_assignment_words PARAMS((WORD_LIST *));
static int execute_simple_command PARAMS((SIMPLE_COM *, int, int, int, struct fd_bitmap *));
static int execute_builtin PARAMS((sh_builtin_func_t *, WORD_LIST *, int, int));
static int execute_function PARAMS((SHELL_VAR *, WORD_LIST *, int, struct fd_bitmap *, int, int));
static int execute_builtin_or_function PARAMS((WORD_LIST *, sh_builtin_func_t *,
SHELL_VAR *,
REDIRECT *, struct fd_bitmap *, int));
static void execute_subshell_builtin_or_function __P((WORD_LIST *, REDIRECT *,
static void execute_subshell_builtin_or_function PARAMS((WORD_LIST *, REDIRECT *,
sh_builtin_func_t *,
SHELL_VAR *,
int, int, int,
struct fd_bitmap *,
int));
static int execute_disk_command __P((WORD_LIST *, REDIRECT *, char *,
static int execute_disk_command PARAMS((WORD_LIST *, REDIRECT *, char *,
int, int, int, struct fd_bitmap *, int));
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 *));
static char *getinterp PARAMS((char *, int, int *));
static void initialize_subshell PARAMS((void));
static int execute_in_subshell PARAMS((COMMAND *, int, int, int, struct fd_bitmap *));
#if defined (COPROCESS_SUPPORT)
static void coproc_setstatus __P((struct coproc *, int));
static int execute_coproc __P((COMMAND *, int, int, struct fd_bitmap *));
static void coproc_setstatus PARAMS((struct coproc *, int));
static int execute_coproc PARAMS((COMMAND *, int, int, struct fd_bitmap *));
#endif
static int execute_pipeline __P((COMMAND *, int, int, int, struct fd_bitmap *));
static int execute_pipeline PARAMS((COMMAND *, int, int, int, struct fd_bitmap *));
static int execute_connection __P((COMMAND *, int, int, int, struct fd_bitmap *));
static int execute_connection PARAMS((COMMAND *, int, int, int, struct fd_bitmap *));
static int execute_intern_function __P((WORD_DESC *, FUNCTION_DEF *));
static int execute_intern_function PARAMS((WORD_DESC *, FUNCTION_DEF *));
/* Set to 1 if fd 0 was the subject of redirection to a subshell. Global
so that reader_loop can set it to zero before executing a command. */
@@ -521,7 +522,7 @@ open_files ()
}
#endif
static void
void
async_redirect_stdin ()
{
int fd;
@@ -540,7 +541,7 @@ async_redirect_stdin ()
/* Execute the command passed in COMMAND, perhaps doing it asynchronously.
COMMAND is exactly what read_command () places into GLOBAL_COMMAND.
ASYNCHROUNOUS, if non-zero, says to do this command in the background.
ASYNCHRONOUS, if non-zero, says to do this command in the background.
PIPE_IN and PIPE_OUT are file descriptors saying where input comes
from and where it goes. They can have the value of NO_PIPE, which means
I/O is stdin/stdout.
@@ -558,7 +559,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
int pipe_in, pipe_out;
struct fd_bitmap *fds_to_close;
{
int exec_result, user_subshell, invert, ignore_return, was_error_trap;
int exec_result, user_subshell, invert, ignore_return, was_error_trap, fork_flags;
REDIRECT *my_undo_list, *exec_undo_list;
char *tcmd;
volatile int save_line_number;
@@ -624,11 +625,13 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
/* Fork a subshell, turn off the subshell bit, turn off job
control and call execute_command () on the command again. */
save_line_number = line_number;
if (command->type == cm_subshell)
line_number_for_err_trap = line_number = command->value.Subshell->line; /* XXX - save value? */
/* Otherwise we defer setting line_number */
tcmd = make_command_string (command);
paren_pid = make_child (p = savestring (tcmd), asynchronous);
fork_flags = asynchronous ? FORK_ASYNC : 0;
paren_pid = make_child (p = savestring (tcmd), fork_flags);
if (user_subshell && signal_is_trapped (ERROR_TRAP) &&
signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0)
@@ -677,13 +680,15 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
stop_pipeline (asynchronous, (COMMAND *)NULL);
line_number = save_line_number;
if (asynchronous == 0)
{
was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
invert = (command->flags & CMD_INVERT_RETURN) != 0;
ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
exec_result = wait_for (paren_pid);
exec_result = wait_for (paren_pid, 0);
/* If we have to, invert the return value. */
if (invert)
@@ -751,7 +756,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
# endif
/* XXX - also if sourcelevel != 0? */
if (variable_context != 0)
if (variable_context != 0 || executing_list)
{
ofifo = num_fifos ();
ofifo_list = copy_fifo_list ((int *)&osize);
@@ -766,6 +771,9 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
/* Handle WHILE FOR CASE etc. with redirections. (Also '&' input
redirection.) */
was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
if (do_redirections (command->redirects, RX_ACTIVE|RX_UNDOABLE) != 0)
{
undo_partial_redirects ();
@@ -777,36 +785,32 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
discard_unwind_frame ("internal_fifos");
}
#endif
return (last_command_exit_value = EXECUTION_FAILURE);
/* Handle redirection error as command failure if errexit set. */
last_command_exit_value = EXECUTION_FAILURE;
if (ignore_return == 0 && invert == 0 && pipe_in == NO_PIPE && pipe_out == NO_PIPE)
{
if (was_error_trap)
{
save_line_number = line_number;
line_number = line_number_for_err_trap;
run_error_trap ();
line_number = save_line_number;
}
if (exit_immediately_on_error)
{
run_pending_traps ();
jump_to_top_level (ERREXIT);
}
}
return (last_command_exit_value);
}
#if 0
if (redirection_undo_list)
{
/* XXX - why copy here? */
my_undo_list = (REDIRECT *)copy_redirects (redirection_undo_list);
dispose_partial_redirects ();
}
else
my_undo_list = (REDIRECT *)NULL;
#else
my_undo_list = redirection_undo_list;
redirection_undo_list = (REDIRECT *)NULL;
#endif
#if 0
if (exec_redirection_undo_list)
{
/* XXX - why copy here? */
exec_undo_list = (REDIRECT *)copy_redirects (exec_redirection_undo_list);
dispose_exec_redirects ();
}
else
exec_undo_list = (REDIRECT *)NULL;
#else
exec_undo_list = exec_redirection_undo_list;
exec_redirection_undo_list = (REDIRECT *)NULL;
#endif
if (my_undo_list || exec_undo_list)
begin_unwind_frame ("loop_redirections");
@@ -817,8 +821,6 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
if (exec_undo_list)
add_unwind_protect ((Function *)dispose_redirects, exec_undo_list);
ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
QUIT;
switch (command->type)
@@ -886,7 +888,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
the function to be waited for twice. This also causes
subshells forked to execute builtin commands (e.g., in
pipelines) to be waited for twice. */
exec_result = wait_for (last_made_pid);
exec_result = wait_for (last_made_pid, 0);
}
}
@@ -1023,40 +1025,35 @@ 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:
#endif
case cm_function_def:
was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
if (ignore_return)
#if defined (DPAREN_ARITHMETIC)
if (ignore_return && command->type == cm_arith)
command->value.Arith->flags |= CMD_IGNORE_RETURN;
#endif
#if defined (COND_COMMAND)
if (ignore_return && command->type == cm_cond)
command->value.Cond->flags |= CMD_IGNORE_RETURN;
#endif
line_number_for_err_trap = save_line_number = line_number;
exec_result = execute_cond_command (command->value.Cond);
#if defined (DPAREN_ARITHMETIC)
if (command->type == cm_arith)
exec_result = execute_arith_command (command->value.Arith);
else
#endif
#if defined (COND_COMMAND)
if (command->type == cm_cond)
exec_result = execute_cond_command (command->value.Cond);
else
#endif
if (command->type == cm_function_def)
exec_result = execute_intern_function (command->value.Function_def->name,
command->value.Function_def);
line_number = save_line_number;
if (was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)
@@ -1076,12 +1073,6 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
}
break;
#endif
case cm_function_def:
exec_result = execute_intern_function (command->value.Function_def->name,
command->value.Function_def);
break;
default:
command_error ("execute_command", CMDERR_BADTYPE, command->type, 0);
@@ -1135,10 +1126,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
last_command_exit_value = exec_result;
run_pending_traps ();
#if 0
if (running_trap == 0)
#endif
currently_executing_command = (COMMAND *)NULL;
currently_executing_command = (COMMAND *)NULL;
return (last_command_exit_value);
}
@@ -1146,9 +1134,9 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
#if defined (COMMAND_TIMING)
#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY)
extern struct timeval *difftimeval __P((struct timeval *, struct timeval *, struct timeval *));
extern struct timeval *addtimeval __P((struct timeval *, struct timeval *, struct timeval *));
extern int timeval_to_cpu __P((struct timeval *, struct timeval *, struct timeval *));
extern struct timeval *difftimeval PARAMS((struct timeval *, struct timeval *, struct timeval *));
extern struct timeval *addtimeval PARAMS((struct timeval *, struct timeval *, struct timeval *));
extern int timeval_to_cpu PARAMS((struct timeval *, struct timeval *, struct timeval *));
#endif
#define POSIX_TIMEFORMAT "real %2R\nuser %2U\nsys %2S"
@@ -1371,8 +1359,7 @@ time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close)
#if defined (HAVE_GETRUSAGE)
selfb.ru_utime.tv_sec = kidsb.ru_utime.tv_sec = selfb.ru_stime.tv_sec = kidsb.ru_stime.tv_sec = 0;
selfb.ru_utime.tv_usec = kidsb.ru_utime.tv_usec = selfb.ru_stime.tv_usec = kidsb.ru_stime.tv_usec = 0;
before.tv_sec = shell_start_time;
before.tv_usec = 0;
before = shellstart;
#else
before.tms_utime = before.tms_stime = before.tms_cutime = before.tms_cstime = 0;
tbefore = shell_start_time;
@@ -1548,22 +1535,25 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
subshell_environment |= SUBSHELL_COPROC;
}
QUIT;
CHECK_TERMSIG;
reset_terminating_signals (); /* in sig.c */
/* Cancel traps, in trap.c. */
/* Reset the signal handlers in the child, but don't free the
trap strings. Set a flag noting that we have to free the
trap strings if we run trap to change a signal disposition. */
clear_pending_traps ();
reset_signal_handlers ();
subshell_environment |= SUBSHELL_RESETTRAP;
#if 0 /* TAG:bash-5.1 */
/* We are in a subshell, so forget that we are running a trap handler or
that the signal handler has changed (we haven't changed it!) */
if (running_trap > 0)
{
run_trap_cleanup (running_trap - 1);
running_trap = 0;
running_trap = 0; /* XXX - maybe leave this */
}
#endif
/* Make sure restore_original_signals doesn't undo the work done by
make_child to ensure that asynchronous children are immune to SIGINT
@@ -1594,6 +1584,10 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
coproc_closeall ();
#endif
#if defined (PROCESS_SUBSTITUTION)
clear_fifo_list (); /* XXX- we haven't created any FIFOs */
#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
@@ -1617,8 +1611,12 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
if (should_redir_stdin && stdin_redir == 0)
async_redirect_stdin ();
#if 0
/* XXX - TAG:bash-5.1 */
#if defined (BUFFERED_INPUT)
/* In any case, we are not reading our command input from stdin. */
default_buffered_input = -1;
#endif
#if 0 /* XXX - TAG:bash-5.1 */
if (user_subshell && command->type == cm_subshell)
optimize_subshell_command (command->value.Subshell->command);
#endif
@@ -1725,18 +1723,18 @@ typedef struct cplist
}
cplist_t;
static struct cpelement *cpe_alloc __P((struct coproc *));
static void cpe_dispose __P((struct cpelement *));
static struct cpelement *cpl_add __P((struct coproc *));
static struct cpelement *cpl_delete __P((pid_t));
static void cpl_reap __P((void));
static void cpl_flush __P((void));
static void cpl_closeall __P((void));
static struct cpelement *cpl_search __P((pid_t));
static struct cpelement *cpl_searchbyname __P((const char *));
static void cpl_prune __P((void));
static struct cpelement *cpe_alloc PARAMS((struct coproc *));
static void cpe_dispose PARAMS((struct cpelement *));
static struct cpelement *cpl_add PARAMS((struct coproc *));
static struct cpelement *cpl_delete PARAMS((pid_t));
static void cpl_reap PARAMS((void));
static void cpl_flush PARAMS((void));
static void cpl_closeall PARAMS((void));
static struct cpelement *cpl_search PARAMS((pid_t));
static struct cpelement *cpl_searchbyname PARAMS((const char *));
static void cpl_prune PARAMS((void));
static void coproc_free __P((struct coproc *));
static void coproc_free PARAMS((struct coproc *));
/* Will go away when there is fully-implemented support for multiple coprocs. */
Coproc sh_coproc = { 0, NO_PID, -1, -1, 0, 0, 0, 0, 0 };
@@ -2388,7 +2386,7 @@ execute_coproc (command, pipe_in, pipe_out, fds_to_close)
BLOCK_SIGNAL (SIGCHLD, set, oset);
coproc_pid = make_child (p = savestring (tcmd), 1);
coproc_pid = make_child (p = savestring (tcmd), FORK_ASYNC);
if (coproc_pid == 0)
{
@@ -2581,6 +2579,9 @@ execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close)
old_frozen = freeze_jobs_list ();
lastpipe_jid = stop_pipeline (0, (COMMAND *)NULL); /* XXX */
add_unwind_protect (lastpipe_cleanup, old_frozen);
#if defined (JOB_CONTROL)
UNBLOCK_CHILD (oset); /* XXX */
#endif
}
if (cmd)
cmd->flags |= CMD_LASTPIPE;
@@ -2608,12 +2609,12 @@ execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close)
if (INVALID_JOB (lastpipe_jid) == 0)
{
append_process (savestring (the_printed_command_except_trap), dollar_dollar_pid, exec_result, lastpipe_jid);
lstdin = wait_for (lastpid);
lstdin = wait_for (lastpid, 0);
}
else
lstdin = wait_for_single_pid (lastpid, 0); /* checks bgpids list */
#else
lstdin = wait_for (lastpid);
lstdin = wait_for (lastpid, 0);
#endif
#if defined (JOB_CONTROL)
@@ -2699,8 +2700,17 @@ execute_connection (command, asynchronous, pipe_in, pipe_out, fds_to_close)
}
executing_list++;
QUIT;
#if 1
execute_command (command->value.Connection->first);
#else
execute_command_internal (command->value.Connection->first,
asynchronous, pipe_in, pipe_out,
fds_to_close);
#endif
QUIT;
optimize_fork (command); /* XXX */
exec_result = execute_command_internal (command->value.Connection->second,
asynchronous, pipe_in, pipe_out,
fds_to_close);
@@ -2762,7 +2772,11 @@ execute_connection (command, asynchronous, pipe_in, pipe_out, fds_to_close)
if (command->value.Connection->first)
command->value.Connection->first->flags |= CMD_IGNORE_RETURN;
#if 1
exec_result = execute_command (command->value.Connection->first);
#else
exec_result = execute_command_internal (command->value.Connection->first, 0, NO_PIPE, NO_PIPE, fds_to_close);
#endif
QUIT;
if (((command->value.Connection->connector == AND_AND) &&
(exec_result == EXECUTION_SUCCESS)) ||
@@ -2912,6 +2926,8 @@ execute_for_command (for_command)
if (ifsname (identifier))
setifs (v);
else
stupidly_hack_special_variables (identifier);
retval = execute_command (for_command->action);
REAP ();
@@ -3246,7 +3262,7 @@ select_query (list, list_len, prompt, print_menu)
char *prompt;
int print_menu;
{
int max_elem_len, indices_len, len;
int max_elem_len, indices_len, len, r, oe;
intmax_t reply;
WORD_LIST *l;
char *repl_string, *t;
@@ -3280,7 +3296,11 @@ select_query (list, list_len, prompt, print_menu)
fflush (stderr);
QUIT;
if (read_builtin ((WORD_LIST *)NULL) != EXECUTION_SUCCESS)
oe = executing_builtin;
executing_builtin = 1;
r = read_builtin ((WORD_LIST *)NULL);
executing_builtin = oe;
if (r != EXECUTION_SUCCESS)
{
putchar ('\n');
return ((char *)NULL);
@@ -3407,6 +3427,8 @@ execute_select_command (select_command)
}
}
stupidly_hack_special_variables (identifier);
retval = execute_command (select_command->action);
REAP ();
@@ -3702,7 +3724,7 @@ execute_arith_command (arith_command)
int expok, save_line_number, retval;
intmax_t expresult;
WORD_LIST *new;
char *exp;
char *exp, *t;
expresult = 0;
@@ -3741,27 +3763,37 @@ execute_arith_command (arith_command)
}
#endif
new = expand_words_no_vars (arith_command->exp);
t = (char *)NULL;
new = arith_command->exp;
if (new->next)
exp = t = string_list (new); /* just in case */
else
exp = new->word->word;
exp = expand_arith_string (exp, Q_DOUBLE_QUOTES|Q_ARITH);
/* If we're tracing, make a new word list with `((' at the front and `))'
at the back and print it. */
at the back and print it. Change xtrace_print_arith_cmd to take a string
when I change eval_arith_for_expr to use expand_arith_string(). */
if (echo_command_at_execute)
xtrace_print_arith_cmd (new);
if (new)
{
exp = new->next ? string_list (new) : new->word->word;
new = make_word_list (make_word (exp ? exp : ""), (WORD_LIST *)NULL);
xtrace_print_arith_cmd (new);
dispose_words (new);
}
if (exp)
{
expresult = evalexp (exp, EXP_EXPANDED, &expok);
line_number = save_line_number;
if (exp != new->word->word)
free (exp);
dispose_words (new);
free (exp);
}
else
{
expresult = 0;
expok = 1;
}
FREE (t);
if (expok == 0)
return (EXECUTION_FAILURE);
@@ -3973,7 +4005,7 @@ execute_null_command (redirects, pipe_in, pipe_out, async)
int pipe_in, pipe_out, async;
{
int r;
int forcefork;
int forcefork, fork_flags;
REDIRECT *rd;
for (forcefork = 0, rd = redirects; rd; rd = rd->next)
@@ -3987,7 +4019,8 @@ execute_null_command (redirects, pipe_in, pipe_out, 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. */
if (make_child ((char *)NULL, async) == 0)
fork_flags = async ? FORK_ASYNC : 0;
if (make_child ((char *)NULL, fork_flags) == 0)
{
/* Cancel traps, in trap.c. */
restore_original_signals (); /* XXX */
@@ -4100,10 +4133,8 @@ fix_assignment_words (words)
an existing local variable, if there is one. */
if (b && ((b->flags & (ASSIGNMENT_BUILTIN|LOCALVAR_BUILTIN)) == ASSIGNMENT_BUILTIN))
w->word->flags |= W_ASSNGLOBAL|W_CHKLOCAL;
#if 0
else if (b && (b->flags & ASSIGNMENT_BUILTIN) && (b->flags & LOCALVAR_BUILTIN))
w->word->flags |= W_CHKLOCAL;
#endif
else if (b && (b->flags & ASSIGNMENT_BUILTIN) && (b->flags & LOCALVAR_BUILTIN) && variable_context)
w->word->flags |= W_FORCELOCAL;
}
#if defined (ARRAY_VARS)
/* Note that we saw an associative array option to a builtin that takes
@@ -4157,6 +4188,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;
pid_t old_last_async_pid;
sh_builtin_func_t *builtin;
SHELL_VAR *func;
@@ -4233,7 +4265,8 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
/* Don't let a DEBUG trap overwrite the command string to be saved with
the process/job associated with this child. */
if (make_child (p = savestring (the_printed_command_except_trap), async) == 0)
fork_flags = async ? FORK_ASYNC : 0;
if (make_child (p = savestring (the_printed_command_except_trap), fork_flags) == 0)
{
already_forked = 1;
simple_command->flags |= CMD_NO_FORK;
@@ -4262,8 +4295,6 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
last_asynchronous_pid = old_last_async_pid;
CHECK_SIGTERM;
if (async)
subshell_level++; /* not for pipes yet */
@@ -4278,19 +4309,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
if (pipe_out != NO_PIPE)
result = last_command_exit_value;
close_pipes (pipe_in, pipe_out);
#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
#if 0
/* Close /dev/fd file descriptors in the parent after forking the
last child in a (possibly one-element) pipeline. Defer this
until any running shell function completes. */
if (pipe_out == NO_PIPE && variable_context == 0) /* XXX */
unlink_fifo_list (); /* XXX */
#endif
#endif
command_line = (char *)NULL; /* don't free this. */
#if 0
bind_lastarg ((char *)NULL);
#endif
return (result);
}
}
@@ -4337,7 +4356,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
begin_unwind_frame ("simple-command");
if (echo_command_at_execute)
if (echo_command_at_execute && (simple_command->flags & CMD_COMMAND_BUILTIN) == 0)
xtrace_print_word_list (words, 1);
builtin = (sh_builtin_func_t *)NULL;
@@ -4362,7 +4381,12 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
/* In POSIX mode, assignment errors in the temporary environment cause a
non-interactive shell to exit. */
#if 1
if (posixly_correct && builtin_is_special && interactive_shell == 0 && tempenv_assign_error)
#else
/* This is for strict posix conformance. */
if (posixly_correct && interactive_shell == 0 && tempenv_assign_error)
#endif
{
last_command_exit_value = EXECUTION_FAILURE;
jump_to_top_level (ERREXIT);
@@ -5118,11 +5142,11 @@ execute_subshell_builtin_or_function (words, redirects, builtin, var,
funcvalue = setjmp_nosigs (return_catch);
if (result == EXITPROG)
exit (last_command_exit_value);
subshell_exit (last_command_exit_value);
else if (result)
exit (EXECUTION_FAILURE);
subshell_exit (EXECUTION_FAILURE);
else if (funcvalue)
exit (return_catch_value);
subshell_exit (return_catch_value);
else
{
r = execute_builtin (builtin, words, flags, 1);
@@ -5138,14 +5162,14 @@ execute_subshell_builtin_or_function (words, redirects, builtin, var,
r = execute_disk_command (words, (REDIRECT *)0, command_line,
-1, -1, async, (struct fd_bitmap *)0, flags|CMD_NO_FORK);
}
sh_exit (r);
subshell_exit (r);
}
}
else
{
r = execute_function (var, words, flags, fds_to_close, async, 1);
fflush (stdout);
sh_exit (r);
subshell_exit (r);
}
}
@@ -5171,7 +5195,7 @@ execute_builtin_or_function (words, builtin, var, redirects,
REDIRECT *saved_undo_list;
#if defined (PROCESS_SUBSTITUTION)
int ofifo, nfifo, osize;
char *ofifo_list;
void *ofifo_list;
#endif
#if defined (PROCESS_SUBSTITUTION)
@@ -5326,7 +5350,7 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
int cmdflags;
{
char *pathname, *command, **args, *p;
int nofork, stdpath, result;
int nofork, stdpath, result, fork_flags;
pid_t pid;
SHELL_VAR *hookf;
WORD_LIST *wl;
@@ -5375,7 +5399,10 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
if (nofork && pipe_in == NO_PIPE && pipe_out == NO_PIPE)
pid = 0;
else
pid = make_child (p = savestring (command_line), async);
{
fork_flags = async ? FORK_ASYNC : 0;
pid = make_child (p = savestring (command_line), fork_flags);
}
if (pid == 0)
{
@@ -5385,8 +5412,6 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
/* Cancel traps, in trap.c. */
restore_original_signals ();
CHECK_SIGTERM;
#if defined (JOB_CONTROL)
FREE (p);
#endif
@@ -5419,6 +5444,10 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
subshell_environment |= SUBSHELL_FORK; /* XXX - was just = */
#if defined (PROCESS_SUBSTITUTION) && !defined (HAVE_DEV_FD)
clear_fifo_list (); /* XXX - we haven't created any FIFOs */
#endif
if (redirects && (do_redirections (redirects, RX_ACTIVE) != 0))
{
#if defined (PROCESS_SUBSTITUTION)
@@ -5456,8 +5485,6 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
exit (execute_shell_function (hookf, wl));
}
CHECK_SIGTERM;
/* Execve expects the command name to be in args[0]. So we
leave it there, in the same format that the user used to
type it in. */
@@ -5808,7 +5835,7 @@ shell_execve (command, args, env)
unbind_args (); /* remove the positional parameters */
#if defined (PROCESS_SUBSTITUTION)
#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
clear_fifo_list (); /* pipe fds are what they are now */
#endif