aboutsummaryrefslogtreecommitdiffstats
path: root/execute_cmd.c
diff options
context:
space:
mode:
authorJari Aalto <jari.aalto@cante.net>2002-07-17 14:10:11 +0000
committerJari Aalto <jari.aalto@cante.net>2009-09-12 16:46:55 +0000
commit7117c2d221b2aed4ede8600f6a36b7c1454b4f55 (patch)
treeb792f26ecca68813c51ed5ba2e381790758ef31b /execute_cmd.c
parentf73dda092b33638d2d5e9c35375f687a607b5403 (diff)
downloadandroid_external_bash-7117c2d221b2aed4ede8600f6a36b7c1454b4f55.tar.gz
android_external_bash-7117c2d221b2aed4ede8600f6a36b7c1454b4f55.tar.bz2
android_external_bash-7117c2d221b2aed4ede8600f6a36b7c1454b4f55.zip
Imported from ../bash-2.05b.tar.gz.
Diffstat (limited to 'execute_cmd.c')
-rw-r--r--execute_cmd.c316
1 files changed, 154 insertions, 162 deletions
diff --git a/execute_cmd.c b/execute_cmd.c
index d8bde10..2291c7a 100644
--- a/execute_cmd.c
+++ b/execute_cmd.c
@@ -1,6 +1,6 @@
/* execute_command.c -- Execute a COMMAND structure. */
-/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -101,7 +101,6 @@ extern int parse_and_execute_level, running_trap, trap_line_number;
extern int command_string_index, line_number;
extern int dot_found_in_search;
extern int already_making_children;
-extern char **temporary_env, **function_env, **builtin_env;
extern char *the_printed_command, *shell_name;
extern pid_t last_command_subst_pid;
extern sh_builtin_func_t *last_shell_builtin, *this_shell_builtin;
@@ -133,7 +132,7 @@ static int execute_for_command __P((FOR_COM *));
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 *));
+static char *select_query __P((WORD_LIST *, int, char *, int));
static int execute_select_command __P((SELECT_COM *));
#endif
#if defined (DPAREN_ARITHMETIC)
@@ -151,7 +150,7 @@ static void print_formatted_time __P((FILE *, char *,
static int time_command __P((COMMAND *, int, int, int, struct fd_bitmap *));
#endif
#if defined (ARITH_FOR_COMMAND)
-static long eval_arith_for_expr __P((WORD_LIST *, int *));
+static intmax_t eval_arith_for_expr __P((WORD_LIST *, int *));
static int execute_arith_for_command __P((ARITH_FOR_COM *));
#endif
static int execute_case_command __P((CASE_COM *));
@@ -186,8 +185,6 @@ static int execute_connection __P((COMMAND *, int, int, int, struct fd_bitmap *)
static int execute_intern_function __P((WORD_DESC *, COMMAND *));
-
-
/* The line number that the currently executing function starts on. */
static int function_line_number;
@@ -249,7 +246,7 @@ new_fd_bitmap (size)
if (size)
{
ret->bitmap = (char *)xmalloc (size);
- bzero (ret->bitmap, size);
+ memset (ret->bitmap, '\0', size);
}
else
ret->bitmap = (char *)NULL;
@@ -285,9 +282,19 @@ close_fd_bitmap (fdbp)
int
executing_line_number ()
{
- if (executing && variable_context == 0 && currently_executing_command &&
- currently_executing_command->type == cm_simple)
- return currently_executing_command->value.Simple->line;
+ if (executing && (variable_context == 0 || interactive_shell == 0) && currently_executing_command)
+ {
+ if (currently_executing_command->type == cm_simple)
+ return currently_executing_command->value.Simple->line;
+ else if (currently_executing_command->type == cm_cond)
+ return currently_executing_command->value.Cond->line;
+ else if (currently_executing_command->type == cm_arith)
+ return currently_executing_command->value.Arith->line;
+ else if (currently_executing_command->type == cm_arith_for)
+ return currently_executing_command->value.ArithFor->line;
+ else
+ return line_number;
+ }
else if (running_trap)
return trap_line_number;
else
@@ -459,7 +466,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
int pipe_in, pipe_out;
struct fd_bitmap *fds_to_close;
{
- int exec_result, invert, ignore_return, was_debug_trap, was_error_trap;
+ int exec_result, invert, ignore_return, was_error_trap;
REDIRECT *my_undo_list, *exec_undo_list;
volatile pid_t last_pid;
@@ -613,7 +620,6 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
call to execute_simple_command if a longjmp occurs as the
result of a `return' builtin. This is true for sure with gcc. */
last_pid = last_made_pid;
- was_debug_trap = signal_is_trapped (DEBUG_TRAP) && signal_is_ignored (DEBUG_TRAP) == 0;
was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
if (ignore_return && command->value.Simple)
@@ -668,12 +674,6 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
}
}
- if (was_debug_trap)
- {
- last_command_exit_value = exec_result;
- run_debug_trap ();
- }
-
if (was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)
{
last_command_exit_value = exec_result;
@@ -910,16 +910,16 @@ mkfmt (buf, prec, lng, sec, sec_fraction)
/* Interpret the format string FORMAT, interpolating the following escape
sequences:
- %[prec][l][RUS]
+ %[prec][l][RUS]
where the optional `prec' is a precision, meaning the number of
characters after the decimal point, the optional `l' means to format
using minutes and seconds (MMmNN[.FF]s), like the `times' builtin',
and the last character is one of
- R number of seconds of `real' time
- U number of seconds of `user' time
- S number of seconds of `system' time
+ R number of seconds of `real' time
+ U number of seconds of `user' time
+ S number of seconds of `system' time
An occurrence of `%%' in the format string is translated to a `%'. The
result is printed to FP, a pointer to a FILE. The other variables are
@@ -1392,9 +1392,6 @@ execute_connection (command, asynchronous, pipe_in, pipe_out, fds_to_close)
int asynchronous, pipe_in, pipe_out;
struct fd_bitmap *fds_to_close;
{
-#if 0
- REDIRECT *tr, *tl;
-#endif
REDIRECT *rp;
COMMAND *tc, *second;
int ignore_return, exec_result;
@@ -1424,37 +1421,12 @@ execute_connection (command, asynchronous, pipe_in, pipe_out, fds_to_close)
#else
if (!stdin_redir)
#endif /* JOB_CONTROL */
- {
-#if 0
- rd.filename = make_bare_word ("/dev/null");
- tr = make_redirection (0, r_inputa_direction, rd);
- tr->next = tc->redirects;
- tc->redirects = tr;
-#endif
- tc->flags |= CMD_STDIN_REDIR;
- }
+ tc->flags |= CMD_STDIN_REDIR;
exec_result = execute_command_internal (tc, 1, pipe_in, pipe_out, fds_to_close);
if (tc->flags & CMD_STDIN_REDIR)
- {
-#if 0
- /* Remove the redirection we added above. It matters,
- especially for loops, which call execute_command ()
- multiple times with the same command. */
- tr = tc->redirects;
- do
- {
- tl = tc->redirects;
- tc->redirects = tc->redirects->next;
- }
- while (tc->redirects && tc->redirects != rp);
-
- tl->next = (REDIRECT *)NULL;
- dispose_redirects (tr);
-#endif
- tc->flags &= ~CMD_STDIN_REDIR;
- }
+ tc->flags &= ~CMD_STDIN_REDIR;
second = command->value.Connection->second;
if (second)
@@ -1628,7 +1600,7 @@ execute_for_command (for_command)
if (lexical_scoping)
{
if (!old_value)
- makunbound (identifier, shell_variables);
+ unbind_variable (identifier);
else
{
SHELL_VAR *new_value;
@@ -1661,19 +1633,22 @@ execute_for_command (for_command)
eval \(\( step \)\)
done
*/
-static long
+static intmax_t
eval_arith_for_expr (l, okp)
WORD_LIST *l;
int *okp;
{
WORD_LIST *new;
- long expresult;
+ intmax_t expresult;
new = expand_words_no_vars (l);
if (new)
{
if (echo_command_at_execute)
xtrace_print_arith_cmd (new);
+ this_command_name = "(("; /* )) for expression error messages */
+ if (signal_is_trapped (DEBUG_TRAP) && signal_is_ignored (DEBUG_TRAP) == 0)
+ run_debug_trap ();
expresult = evalexp (new->word->word, okp);
dispose_words (new);
}
@@ -1690,8 +1665,8 @@ static int
execute_arith_for_command (arith_for_command)
ARITH_FOR_COM *arith_for_command;
{
- long expresult;
- int expok, body_status;
+ intmax_t expresult;
+ int expok, body_status, arith_lineno, save_lineno;
body_status = EXECUTION_SUCCESS;
loop_level++;
@@ -1701,8 +1676,12 @@ execute_arith_for_command (arith_for_command)
this_command_name = "(("; /* )) for expression error messages */
- if (variable_context)
- line_number = arith_for_command->line - function_line_number;
+ /* save the starting line number of the command so we can reset
+ line_number before executing each expression -- for $LINENO
+ and the DEBUG trap. */
+ arith_lineno = arith_for_command->line;
+ if (variable_context && interactive_shell)
+ line_number = arith_lineno -= function_line_number;
/* Evaluate the initialization expression. */
expresult = eval_arith_for_expr (arith_for_command->init, &expok);
@@ -1712,7 +1691,11 @@ execute_arith_for_command (arith_for_command)
while (1)
{
/* Evaluate the test expression. */
+ save_lineno = line_number;
+ line_number = arith_lineno;
expresult = eval_arith_for_expr (arith_for_command->test, &expok);
+ line_number = save_lineno;
+
if (expok == 0)
{
body_status = EXECUTION_FAILURE;
@@ -1742,7 +1725,11 @@ execute_arith_for_command (arith_for_command)
}
/* Evaluate the step expression. */
+ save_lineno = line_number;
+ line_number = arith_lineno;
expresult = eval_arith_for_expr (arith_for_command->step, &expok);
+ line_number = save_lineno;
+
if (expok == 0)
{
body_status = EXECUTION_FAILURE;
@@ -1859,13 +1846,14 @@ print_select_list (list, list_len, max_elem_len, indices_len)
is read, return a null string. If a blank line is entered, or an invalid
number is entered, the loop is executed again. */
static char *
-select_query (list, list_len, prompt)
+select_query (list, list_len, prompt, print_menu)
WORD_LIST *list;
int list_len;
char *prompt;
+ int print_menu;
{
int max_elem_len, indices_len, len;
- long reply;
+ intmax_t reply;
WORD_LIST *l;
char *repl_string, *t;
@@ -1895,7 +1883,8 @@ select_query (list, list_len, prompt)
while (1)
{
- print_select_list (list, list_len, max_elem_len, indices_len);
+ if (print_menu)
+ print_select_list (list, list_len, max_elem_len, indices_len);
fprintf (stderr, "%s", prompt);
fflush (stderr);
QUIT;
@@ -1907,7 +1896,10 @@ select_query (list, list_len, prompt)
}
repl_string = get_string_value ("REPLY");
if (*repl_string == 0)
- continue;
+ {
+ print_menu = 1;
+ continue;
+ }
if (legal_number (repl_string, &reply) == 0)
return "";
if (reply < 1 || reply > list_len)
@@ -1930,8 +1922,8 @@ execute_select_command (select_command)
WORD_LIST *releaser, *list;
SHELL_VAR *v;
char *identifier, *ps3_prompt, *selection;
- int retval, list_len;
-
+ int retval, list_len, show_menu;
+
if (check_identifier (select_command->name, 1) == 0)
return (EXECUTION_FAILURE);
@@ -1956,6 +1948,7 @@ execute_select_command (select_command)
select_command->action->flags |= CMD_IGNORE_RETURN;
retval = EXECUTION_SUCCESS;
+ show_menu = 1;
while (1)
{
@@ -1964,10 +1957,15 @@ execute_select_command (select_command)
ps3_prompt = "#? ";
QUIT;
- selection = select_query (list, list_len, ps3_prompt);
+ selection = select_query (list, list_len, ps3_prompt, show_menu);
QUIT;
if (selection == 0)
- break;
+ {
+ /* select_query returns EXECUTION_FAILURE if the read builtin
+ fails, so we want to return failure in this case. */
+ retval = EXECUTION_FAILURE;
+ break;
+ }
v = bind_variable (identifier, selection);
if (readonly_p (v) || noassign_p (v))
@@ -2001,6 +1999,13 @@ execute_select_command (select_command)
if (continuing)
break;
}
+
+#if defined (KSH_COMPATIBLE_SELECT)
+ show_menu = 0;
+ selection = get_string_value ("REPLY");
+ if (selection && *selection == '\0')
+ show_menu = 1;
+#endif
}
loop_level--;
@@ -2027,7 +2032,7 @@ execute_case_command (case_command)
/* Posix.2 specifies that the WORD is tilde expanded. */
if (member ('~', case_command->word->word))
{
- word = bash_tilde_expand (case_command->word->word);
+ word = bash_tilde_expand (case_command->word->word, 0);
free (case_command->word->word);
case_command->word->word = word;
}
@@ -2053,7 +2058,7 @@ execute_case_command (case_command)
list. */
if (member ('~', list->word->word))
{
- pattern = bash_tilde_expand (list->word->word);
+ pattern = bash_tilde_expand (list->word->word, 0);
free (list->word->word);
list->word->word = pattern;
}
@@ -2217,16 +2222,22 @@ execute_arith_command (arith_command)
ARITH_COM *arith_command;
{
int expok;
- long expresult;
+ intmax_t expresult;
WORD_LIST *new;
expresult = 0;
this_command_name = "(("; /* )) */
/* If we're in a function, update the line number information. */
- if (variable_context)
+ if (variable_context && interactive_shell)
line_number = arith_command->line - function_line_number;
+ /* Run the debug trap before each arithmetic command, but do it after we
+ update the line number information and before we expand the various
+ words in the expression. */
+ if (signal_is_trapped (DEBUG_TRAP) && signal_is_ignored (DEBUG_TRAP) == 0)
+ run_debug_trap ();
+
new = expand_words (arith_command->exp);
/* If we're tracing, make a new word list with `((' at the front and `))'
@@ -2329,9 +2340,14 @@ execute_cond_command (cond_command)
this_command_name = "[[";
/* If we're in a function, update the line number information. */
- if (variable_context)
+ if (variable_context && interactive_shell)
line_number = cond_command->line - function_line_number;
+ /* Run the debug trap before each conditional command, but do it after we
+ update the line number information. */
+ if (signal_is_trapped (DEBUG_TRAP) && signal_is_ignored (DEBUG_TRAP) == 0)
+ run_debug_trap ();
+
#if 0
debug_print_cond_command (cond_command);
#endif
@@ -2418,13 +2434,19 @@ fix_assignment_words (words)
if (words == 0)
return;
- b = builtin_address_internal (words->word->word, 0);
- if (b == 0 || (b->flags & ASSIGNMENT_BUILTIN) == 0)
- return;
+ b = 0;
for (w = words; w; w = w->next)
if (w->word->flags & W_ASSIGNMENT)
- w->word->flags |= (W_NOSPLIT|W_NOGLOB);
+ {
+ if (b == 0)
+ {
+ b = builtin_address_internal (words->word->word, 0);
+ if (b == 0 || (b->flags & ASSIGNMENT_BUILTIN) == 0)
+ return;
+ }
+ w->word->flags |= (W_NOSPLIT|W_NOGLOB|W_TILDEEXP);
+ }
}
/* The meaty part of all the executions. We have to start hacking the
@@ -2448,9 +2470,14 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
command_line = (char *)0;
/* If we're in a function, update the line number information. */
- if (variable_context)
+ if (variable_context && interactive_shell)
line_number = simple_command->line - function_line_number;
+ /* Run the debug trap before each simple command, but do it after we
+ update the line number information. */
+ if (signal_is_trapped (DEBUG_TRAP) && signal_is_ignored (DEBUG_TRAP) == 0)
+ run_debug_trap ();
+
/* Remember what this command line looks like at invocation. */
command_string_index = 0;
print_simple_command (simple_command);
@@ -2607,48 +2634,25 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
pipe_out == NO_PIPE &&
(temp = get_string_value ("auto_resume")))
{
- char *word;
- register int i;
- int wl, cl, exact_p, substring_p, match, started_status;
- register PROCESS *p;
+ int job, jflags, started_status;
- word = words->word->word;
- exact_p = STREQ (temp, "exact");
- substring_p = STREQ (temp, "substring");
- wl = strlen (word);
- for (i = job_slots - 1; i > -1; i--)
+ jflags = JM_STOPPED|JM_FIRSTMATCH;
+ if (STREQ (temp, "exact"))
+ jflags |= JM_EXACT;
+ else if (STREQ (temp, "substring"))
+ jflags |= JM_SUBSTRING;
+ else
+ jflags |= JM_PREFIX;
+ job = get_job_by_name (words->word->word, jflags);
+ if (job != NO_JOB)
{
- if (jobs[i] == 0 || (JOBSTATE (i) != JSTOPPED))
- continue;
+ run_unwind_frame ("simple-command");
+ this_command_name = "fg";
+ last_shell_builtin = this_shell_builtin;
+ this_shell_builtin = builtin_address ("fg");
- p = jobs[i]->pipe;
- do
- {
- if (exact_p)
- {
- cl = strlen (p->command);
- match = STREQN (p->command, word, cl);
- }
- else if (substring_p)
- match = strindex (p->command, word) != (char *)0;
- else
- match = STREQN (p->command, word, wl);
-
- if (match == 0)
- {
- p = p->next;
- continue;
- }
-
- run_unwind_frame ("simple-command");
- this_command_name = "fg";
- last_shell_builtin = this_shell_builtin;
- this_shell_builtin = builtin_address ("fg");
-
- started_status = start_job (i, 1);
- return ((started_status < 0) ? EXECUTION_FAILURE : started_status);
- }
- while (p != jobs[i]->pipe);
+ started_status = start_job (job, 1);
+ return ((started_status < 0) ? EXECUTION_FAILURE : started_status);
}
}
#endif /* JOB_CONTROL */
@@ -2771,6 +2775,7 @@ execute_builtin (builtin, words, flags, subshell)
int flags, subshell;
{
int old_e_flag, result, eval_unwind;
+ int isbltinenv;
old_e_flag = exit_immediately_on_error;
/* The eval builtin calls parse_and_execute, which does not know about
@@ -2792,19 +2797,19 @@ execute_builtin (builtin, words, flags, subshell)
/* The temporary environment for a builtin is supposed to apply to
all commands executed by that builtin. Currently, this is a
problem only with the `source' and `eval' builtins. */
- if (builtin == source_builtin || builtin == eval_builtin)
+ isbltinenv = (builtin == source_builtin || builtin == eval_builtin);
+ if (isbltinenv)
{
if (subshell == 0)
begin_unwind_frame ("builtin_env");
if (temporary_env)
{
- builtin_env = copy_array (temporary_env);
+ push_scope (VC_BLTNENV, temporary_env);
if (subshell == 0)
- add_unwind_protect (dispose_builtin_env, (char *)NULL);
- dispose_used_env_vars ();
+ add_unwind_protect (pop_scope, "1");
+ temporary_env = (HASH_TABLE *)NULL;
}
- /* Otherwise we inherit builtin_env from our caller. */
}
/* `return' does a longjmp() back to a saved environment in execute_function.
@@ -2824,16 +2829,8 @@ execute_builtin (builtin, words, flags, subshell)
if (posixly_correct && subshell == 0 && builtin == return_builtin && temporary_env)
discard_unwind_frame ("return_temp_env");
- if (subshell == 0 && (builtin == source_builtin || builtin == eval_builtin))
- {
- /* In POSIX mode, if any variable assignments precede the `.' or
- `eval' builtin, they persist after the builtin completes, since `.'
- and `eval' are special builtins. */
- if (posixly_correct && builtin_env)
- merge_builtin_env ();
-
- run_unwind_frame ("builtin_env");
- }
+ if (subshell == 0 && isbltinenv)
+ run_unwind_frame ("builtin_env");
if (eval_unwind)
{
@@ -2865,7 +2862,7 @@ execute_function (var, words, flags, fds_to_close, async, subshell)
if (subshell == 0)
{
begin_unwind_frame ("function_calling");
- push_context ();
+ push_context (var->name, subshell, temporary_env);
add_unwind_protect (pop_context, (char *)NULL);
unwind_protect_int (line_number);
unwind_protect_int (return_catch_flag);
@@ -2874,6 +2871,10 @@ execute_function (var, words, flags, fds_to_close, async, subshell)
unwind_protect_pointer (this_shell_function);
unwind_protect_int (loop_level);
}
+ else
+ push_context (var->name, subshell, temporary_env); /* don't unwind-protect for subshells */
+
+ temporary_env = (HASH_TABLE *)NULL;
this_shell_function = var;
make_funcname_visible (1);
@@ -2885,7 +2886,7 @@ execute_function (var, words, flags, fds_to_close, async, subshell)
important here! unwind-protect commands are run in reverse order
of registration. If this causes problems, take out the xfree
unwind-protect calls and live with the small memory leak. */
- if (debug_trap)
+ if (debug_trap && (trace_p (var) == 0))
{
if (subshell == 0)
{
@@ -2909,27 +2910,12 @@ execute_function (var, words, flags, fds_to_close, async, subshell)
/* The temporary environment for a function is supposed to apply to
all commands executed within the function body. */
- if (temporary_env)
- {
- function_env = copy_array (temporary_env);
- /* In POSIX mode, variable assignments preceding function names are
- supposed to persist in the environment after the function returns,
- as if a special builtin command had been executed. */
- if (subshell == 0)
- {
- if (posixly_correct)
- add_unwind_protect (merge_function_env, (char *)NULL);
- else
- add_unwind_protect (dispose_function_env, (char *)NULL);
- }
- dispose_used_env_vars ();
- }
- /* Otherwise, we inherit function_env from our caller. */
remember_args (words->next, 1);
/* Number of the line on which the function body starts. */
- line_number = function_line_number = tc->line;
+ if (interactive_shell)
+ line_number = function_line_number = tc->line;
if (subshell)
{
@@ -2940,8 +2926,6 @@ execute_function (var, words, flags, fds_to_close, async, subshell)
if (fc && (flags & CMD_IGNORE_RETURN))
fc->flags |= CMD_IGNORE_RETURN;
-
- variable_context++;
}
else
fc = tc;
@@ -3202,7 +3186,7 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
pathname = words->word->word;
#if defined (RESTRICTED_SHELL)
- if (restricted && strchr (pathname, '/'))
+ if (restricted && xstrchr (pathname, '/'))
{
internal_error ("%s: restricted: cannot specify `/' in command names",
pathname);
@@ -3293,7 +3277,7 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
/* 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. */
- args = word_list_to_argv (words, 0, 0, (int *)NULL);
+ args = strvec_from_word_list (words, 0, 0, (int *)NULL);
exit (shell_execve (command, args, export_env));
}
else
@@ -3387,9 +3371,8 @@ execute_shell_script (sample, sample_len, command, args, env)
size_increment = 2;
}
- larry = array_len (args) + size_increment;
-
- args = (char **)xrealloc ((char *)args, (1 + larry) * sizeof (char *));
+ larry = strvec_len (args) + size_increment;
+ args = strvec_resize (args, larry + 1);
for (i = larry - 1; i; i--)
args[i] = args[i - size_increment];
@@ -3440,8 +3423,10 @@ initialize_subshell ()
/* Zero out builtin_env, since this could be a shell script run from a
sourced file with a temporary environment supplied to the `source/.'
builtin. Such variables are not supposed to be exported (empirical
- testing with sh and ksh). */
- builtin_env = 0;
+ testing with sh and ksh). Just throw it away; don't worry about a
+ memory leak. */
+ if (vc_isbltnenv (shell_variables))
+ shell_variables = shell_variables->down;
clear_unwind_protect_list (0);
@@ -3497,8 +3482,15 @@ shell_execve (command, args, env)
{
if ((stat (command, &finfo) == 0) && (S_ISDIR (finfo.st_mode)))
internal_error ("%s: is a directory", command);
+ else if (executable_file (command) == 0)
+ {
+ errno = i;
+ file_error (command);
+ }
else
{
+ /* The file has the execute bits set, but the kernel refuses to
+ run it for some reason. See why. */
#if defined (HAVE_HASH_BANG_EXEC)
READ_SAMPLE_BUF (command, sample, sample_len);
if (sample_len > 2 && sample[0] == '#' && sample[1] == '!')
@@ -3557,8 +3549,8 @@ shell_execve (command, args, env)
set_sigint_handler ();
/* Insert the name of this shell into the argument list. */
- larray = array_len (args) + 1;
- args = (char **)xrealloc ((char *)args, (1 + larray) * sizeof (char *));
+ larray = strvec_len (args) + 1;
+ args = strvec_resize (args, larray + 1);
for (i = larray - 1; i; i--)
args[i] = args[i - 1];
@@ -3634,7 +3626,7 @@ close_all_files ()
fd_table_size = getdtablesize ();
if (fd_table_size > 256) /* clamp to a reasonable value */
- fd_table_size = 256;
+ fd_table_size = 256;
for (i = 3; i < fd_table_size; i++)
close (i);