aboutsummaryrefslogtreecommitdiffstats
path: root/execute_cmd.c
diff options
context:
space:
mode:
authorJari Aalto <jari.aalto@cante.net>2001-11-13 17:56:06 +0000
committerJari Aalto <jari.aalto@cante.net>2009-09-12 16:46:54 +0000
commitf73dda092b33638d2d5e9c35375f687a607b5403 (patch)
treef21584e70a444d6a1ecba0fb5e2cf79e8cce91db /execute_cmd.c
parent28ef6c316f1aff914bb95ac09787a3c83c1815fd (diff)
downloadandroid_external_bash-f73dda092b33638d2d5e9c35375f687a607b5403.tar.gz
android_external_bash-f73dda092b33638d2d5e9c35375f687a607b5403.tar.bz2
android_external_bash-f73dda092b33638d2d5e9c35375f687a607b5403.zip
Imported from ../bash-2.05a.tar.gz.
Diffstat (limited to 'execute_cmd.c')
-rw-r--r--execute_cmd.c408
1 files changed, 254 insertions, 154 deletions
diff --git a/execute_cmd.c b/execute_cmd.c
index 79abc28..d8bde10 100644
--- a/execute_cmd.c
+++ b/execute_cmd.c
@@ -24,7 +24,7 @@
#endif /* _AIX && RISC6000 && !__GNUC__ */
#include <stdio.h>
-#include <ctype.h>
+#include "chartypes.h"
#include "bashtypes.h"
#ifndef _MINIX
# include <sys/file.h>
@@ -40,10 +40,6 @@
# include <unistd.h>
#endif
-#if defined (HAVE_LIMITS_H)
-# include <limits.h>
-#endif
-
#include "posixtime.h"
#if defined (HAVE_SYS_RESOURCE_H) && !defined (RLIMTYPE)
@@ -83,7 +79,7 @@ extern int errno;
#include "builtins/common.h"
#include "builtins/builtext.h" /* list of builtins */
-#include <glob/fnmatch.h>
+#include <glob/strmatch.h>
#include <tilde/tilde.h>
#if defined (BUFFERED_INPUT)
@@ -99,57 +95,98 @@ extern int errno;
#endif
extern int posixly_correct;
-extern int executing, breaking, continuing, loop_level;
-extern int interactive, interactive_shell, login_shell, expand_aliases;
+extern int breaking, continuing, loop_level;
+extern int expand_aliases;
extern int parse_and_execute_level, running_trap, trap_line_number;
-extern int command_string_index, variable_context, 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 Function *last_shell_builtin, *this_shell_builtin;
+extern sh_builtin_func_t *last_shell_builtin, *this_shell_builtin;
extern char **subshell_argv, **subshell_envp;
extern int subshell_argc;
+#if 0
extern char *glob_argv_flags;
+#endif
-extern int getdtablesize ();
-extern int close ();
+extern int close __P((int));
/* Static functions defined and used in this file. */
-static void close_pipes (), do_piping (), bind_lastarg ();
-static void cleanup_redirects ();
+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 *));
+
+#if defined (JOB_CONTROL)
+static int restore_signal_mask __P((sigset_t *));
+#endif
-static int execute_for_command ();
+static void async_redirect_stdin __P((void));
+
+static int builtin_status __P((int));
+
+static int execute_for_command __P((FOR_COM *));
#if defined (SELECT_COMMAND)
-static int execute_select_command ();
+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 int execute_select_command __P((SELECT_COM *));
#endif
#if defined (DPAREN_ARITHMETIC)
-static int execute_arith_command ();
+static int execute_arith_command __P((ARITH_COM *));
#endif
#if defined (COND_COMMAND)
-static int execute_cond_command ();
+static int execute_cond_node __P((COND_COM *));
+static int execute_cond_command __P((COND_COM *));
#endif
#if defined (COMMAND_TIMING)
-static int time_command ();
+static int mkfmt __P((char *, int, int, time_t, int));
+static void print_formatted_time __P((FILE *, char *,
+ time_t, int, time_t, int,
+ time_t, int, int));
+static int time_command __P((COMMAND *, int, int, int, struct fd_bitmap *));
#endif
#if defined (ARITH_FOR_COMMAND)
-static int execute_arith_for_command ();
+static long eval_arith_for_expr __P((WORD_LIST *, int *));
+static int execute_arith_for_command __P((ARITH_FOR_COM *));
#endif
-static int execute_case_command ();
-static int execute_while_command (), execute_until_command ();
-static int execute_while_or_until ();
-static int execute_if_command ();
-static int execute_simple_command ();
-static int execute_builtin (), execute_function ();
-static int execute_builtin_or_function ();
-static int builtin_status ();
-static void execute_subshell_builtin_or_function ();
-static void execute_disk_command ();
-static int execute_connection ();
-static int execute_intern_function ();
-
-static int execute_in_subshell ();
+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, pid_t));
+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 *,
+ SHELL_VAR *,
+ REDIRECT *, struct fd_bitmap *, int));
+static void execute_subshell_builtin_or_function __P((WORD_LIST *, REDIRECT *,
+ sh_builtin_func_t *,
+ SHELL_VAR *,
+ int, int, int,
+ struct fd_bitmap *,
+ int));
+static void execute_disk_command __P((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 int execute_pipeline __P((COMMAND *, int, int, int, struct fd_bitmap *));
+
+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;
@@ -194,14 +231,14 @@ SHELL_VAR *this_shell_function;
struct fd_bitmap *current_fds_to_close = (struct fd_bitmap *)NULL;
-#define FD_BITMAP_DEFAULT_SIZE 32L
+#define FD_BITMAP_DEFAULT_SIZE 32
/* Functions to allocate and deallocate the structures used to pass
information from the shell to its children about file descriptors
to close. */
struct fd_bitmap *
new_fd_bitmap (size)
- long size;
+ int size;
{
struct fd_bitmap *ret;
@@ -211,7 +248,7 @@ new_fd_bitmap (size)
if (size)
{
- ret->bitmap = xmalloc (size);
+ ret->bitmap = (char *)xmalloc (size);
bzero (ret->bitmap, size);
}
else
@@ -359,12 +396,13 @@ dispose_exec_redirects ()
is interrupted or errors occur while creating a pipeline. */
static int
restore_signal_mask (set)
- sigset_t set;
+ sigset_t *set;
{
- return (sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL));
+ return (sigprocmask (SIG_SETMASK, set, (sigset_t *)NULL));
}
#endif /* JOB_CONTROL */
+#ifdef DEBUG
/* A debugging function that can be called from gdb, for instance. */
void
open_files ()
@@ -374,7 +412,7 @@ open_files ()
fd_table_size = getdtablesize ();
- fprintf (stderr, "pid %d open files:", (int)getpid ());
+ fprintf (stderr, "pid %ld open files:", (long)getpid ());
for (i = 3; i < fd_table_size; i++)
{
if ((f = fcntl (i, F_GETFD, 0)) != -1)
@@ -382,6 +420,7 @@ open_files ()
}
fprintf (stderr, "\n");
}
+#endif
static void
async_redirect_stdin ()
@@ -420,7 +459,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;
+ int exec_result, invert, ignore_return, was_debug_trap, was_error_trap;
REDIRECT *my_undo_list, *exec_undo_list;
volatile pid_t last_pid;
@@ -575,6 +614,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
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)
command->value.Simple->flags |= CMD_IGNORE_RETURN;
@@ -634,6 +674,12 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
run_debug_trap ();
}
+ if (was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)
+ {
+ last_command_exit_value = exec_result;
+ run_error_trap ();
+ }
+
if (ignore_return == 0 && invert == 0 &&
((posixly_correct && interactive == 0 && special_builtin_failed) ||
(exit_immediately_on_error && (exec_result != EXECUTION_SUCCESS))))
@@ -793,9 +839,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();
-extern struct timeval *addtimeval();
-extern int timeval_to_cpu();
+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 *));
#endif
#define POSIX_TIMEFORMAT "real %2R\nuser %2U\nsys %2S"
@@ -808,22 +854,22 @@ static int
mkfmt (buf, prec, lng, sec, sec_fraction)
char *buf;
int prec, lng;
- long sec;
+ time_t sec;
int sec_fraction;
{
- long min;
- char abuf[16];
+ time_t min;
+ char abuf[INT_STRLEN_BOUND(time_t) + 1];
int ind, aind;
ind = 0;
- abuf[15] = '\0';
+ abuf[sizeof(abuf) - 1] = '\0';
/* If LNG is non-zero, we want to decompose SEC into minutes and seconds. */
if (lng)
{
min = sec / 60;
sec %= 60;
- aind = 14;
+ aind = sizeof(abuf) - 2;
do
abuf[aind--] = (min % 10) + '0';
while (min /= 10);
@@ -834,7 +880,7 @@ mkfmt (buf, prec, lng, sec, sec_fraction)
}
/* Now add the seconds. */
- aind = 14;
+ aind = sizeof (abuf) - 2;
do
abuf[aind--] = (sec % 10) + '0';
while (sec /= 10);
@@ -883,18 +929,22 @@ static void
print_formatted_time (fp, format, rs, rsf, us, usf, ss, ssf, cpu)
FILE *fp;
char *format;
- long rs, us, ss;
- int rsf, usf, ssf, cpu;
+ time_t rs;
+ int rsf;
+ time_t us;
+ int usf;
+ time_t ss;
+ int ssf, cpu;
{
int prec, lng, len;
- char *str, *s, ts[32];
- long sum;
+ char *str, *s, ts[INT_STRLEN_BOUND (time_t) + sizeof ("mSS.FFFF")];
+ time_t sum;
int sum_frac;
int sindex, ssize;
len = strlen (format);
ssize = (len + 64) - (len % 64);
- str = xmalloc (ssize);
+ str = (char *)xmalloc (ssize);
sindex = 0;
for (s = format; *s; s++)
@@ -927,7 +977,7 @@ print_formatted_time (fp, format, rs, rsf, us, usf, ss, ssf, cpu)
prec = 3; /* default is three places past the decimal point. */
lng = 0; /* default is to not use minutes or append `s' */
s++;
- if (isdigit (*s)) /* `precision' */
+ if (DIGIT (*s)) /* `precision' */
{
prec = *s++ - '0';
if (prec > 3) prec = 3;
@@ -969,7 +1019,7 @@ time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close)
struct fd_bitmap *fds_to_close;
{
int rv, posix_time, old_flags;
- long rs, us, ss;
+ time_t rs, us, ss;
int rsf, usf, ssf;
int cpu;
char *time_format;
@@ -1003,7 +1053,7 @@ time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close)
rv = execute_command_internal (command, asynchronous, pipe_in, pipe_out, fds_to_close);
command->flags = old_flags;
- rs = us = ss = 0L;
+ rs = us = ss = 0;
rsf = usf = ssf = cpu = 0;
#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY)
@@ -1039,7 +1089,7 @@ time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close)
cpu = (real == 0) ? 0 : ((user + sys) * 10000) / real;
# else
- rs = us = ss = 0L;
+ rs = us = ss = 0;
rsf = usf = ssf = cpu = 0;
# endif
#endif
@@ -1070,6 +1120,11 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
int ois;
COMMAND *tcom;
+ USE_VAR(user_subshell);
+ USE_VAR(invert);
+ USE_VAR(tcom);
+ USE_VAR(asynchronous);
+
should_redir_stdin = (asynchronous && (command->flags & CMD_STDIN_REDIR) &&
pipe_in == NO_PIPE &&
stdin_redirects (command->redirects) == 0);
@@ -1169,6 +1224,10 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
tcom = (command->type == cm_subshell) ? command->value.Subshell->command : command;
+ /* Make sure the subshell inherits any CMD_IGNORE_RETURN flag. */
+ if ((command->flags & CMD_IGNORE_RETURN) && tcom != command)
+ tcom->flags |= CMD_IGNORE_RETURN;
+
/* 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.
@@ -1292,7 +1351,7 @@ execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close)
add_unwind_protect (close, dummyfd);
#if defined (JOB_CONTROL)
- add_unwind_protect (restore_signal_mask, oset);
+ add_unwind_protect (restore_signal_mask, &oset);
#endif /* JOB_CONTROL */
if (ignore_return && cmd->value.Connection->first)
@@ -1356,13 +1415,12 @@ execute_connection (command, asynchronous, pipe_in, pipe_out, fds_to_close)
tc->flags |= CMD_IGNORE_RETURN;
tc->flags |= CMD_AMPERSAND;
- /* If this shell was compiled without job control support, if
- the shell is not running interactively, if we are currently
- in a subshell via `( xxx )', or if job control is not active
- then the standard input for an asynchronous command is
- forced to /dev/null. */
+ /* If this shell was compiled without job control support,
+ if we are currently in a subshell via `( xxx )', or if job
+ control is not active then the standard input for an
+ asynchronous command is forced to /dev/null. */
#if defined (JOB_CONTROL)
- if ((!interactive_shell || subshell_environment || !job_control) && !stdin_redir)
+ if ((subshell_environment || !job_control) && !stdin_redir)
#else
if (!stdin_redir)
#endif /* JOB_CONTROL */
@@ -1612,10 +1670,19 @@ eval_arith_for_expr (l, okp)
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);
+ if (new)
+ {
+ if (echo_command_at_execute)
+ xtrace_print_arith_cmd (new);
+ expresult = evalexp (new->word->word, okp);
+ dispose_words (new);
+ }
+ else
+ {
+ expresult = 0;
+ if (okp)
+ *okp = 1;
+ }
return (expresult);
}
@@ -1624,7 +1691,7 @@ execute_arith_for_command (arith_for_command)
ARITH_FOR_COM *arith_for_command;
{
long expresult;
- int expok, result, body_status;
+ int expok, body_status;
body_status = EXECUTION_SUCCESS;
loop_level++;
@@ -1863,8 +1930,8 @@ execute_select_command (select_command)
WORD_LIST *releaser, *list;
SHELL_VAR *v;
char *identifier, *ps3_prompt, *selection;
- int retval, list_len, return_val;
-
+ int retval, list_len;
+
if (check_identifier (select_command->name, 1) == 0)
return (EXECUTION_FAILURE);
@@ -1890,10 +1957,6 @@ execute_select_command (select_command)
retval = EXECUTION_SUCCESS;
- unwind_protect_int (return_catch_flag);
- unwind_protect_jmp_buf (return_catch);
- return_catch_flag++;
-
while (1)
{
ps3_prompt = get_string_value ("PS3");
@@ -1921,15 +1984,7 @@ execute_select_command (select_command)
}
}
- return_val = setjmp (return_catch);
-
- if (return_val)
- {
- retval = return_catch_value;
- break;
- }
- else
- retval = execute_command (select_command->action);
+ retval = execute_command (select_command->action);
REAP ();
QUIT;
@@ -2009,14 +2064,14 @@ execute_case_command (case_command)
pattern = quote_string_for_globbing (es->word->word, QGLOB_CVTNULL);
else
{
- pattern = xmalloc (1);
+ pattern = (char *)xmalloc (1);
pattern[0] = '\0';
}
/* Since the pattern does not undergo quote removal (as per
- Posix.2, section 3.9.4.3), the fnmatch () call must be able
+ Posix.2, section 3.9.4.3), the strmatch () call must be able
to recognize backslashes as escape characters. */
- match = fnmatch (pattern, word, FNMATCH_EXTFLAG) != FNM_NOMATCH;
+ match = strmatch (pattern, word, FNMATCH_EXTFLAG) != FNM_NOMATCH;
free (pattern);
dispose_words (es);
@@ -2084,10 +2139,23 @@ execute_while_or_until (while_command, type)
return_value = execute_command (while_command->test);
REAP ();
+ /* Need to handle `break' in the test when we would break out of the
+ loop. The job control code will set `breaking' to loop_level
+ when a job in a loop is stopped with SIGTSTP. If the stopped job
+ is in the loop test, `breaking' will not be reset unless we do
+ this, and the shell will cease to execute commands. */
if (type == CMD_WHILE && return_value != EXECUTION_SUCCESS)
- break;
+ {
+ if (breaking)
+ breaking--;
+ break;
+ }
if (type == CMD_UNTIL && return_value == EXECUTION_SUCCESS)
- break;
+ {
+ if (breaking)
+ breaking--;
+ break;
+ }
QUIT;
body_status = execute_command (while_command->action);
@@ -2148,11 +2216,11 @@ static int
execute_arith_command (arith_command)
ARITH_COM *arith_command;
{
- int result, expok, expresult;
- WORD_LIST *new, *p, *printit;
- WORD_DESC *w;
+ int expok;
+ long expresult;
+ WORD_LIST *new;
- result = 0;
+ expresult = 0;
this_command_name = "(("; /* )) */
/* If we're in a function, update the line number information. */
@@ -2166,13 +2234,13 @@ execute_arith_command (arith_command)
if (echo_command_at_execute)
xtrace_print_arith_cmd (new);
- result = evalexp (new->word->word, &expok);
+ expresult = evalexp (new->word->word, &expok);
dispose_words (new);
if (expok == 0)
return (EXECUTION_FAILURE);
- return (result == 0 ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
+ return (expresult == 0 ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
}
#endif /* DPAREN_ARITHMETIC */
@@ -2184,8 +2252,8 @@ static int
execute_cond_node (cond)
COND_COM *cond;
{
- int result, invert, patmatch, flags;
- char *arg1, *arg2, *print2;
+ int result, invert, patmatch;
+ char *arg1, *arg2;
invert = (cond->flags & CMD_INVERT_RETURN);
@@ -2372,7 +2440,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
char *command_line, *lastarg, *temp;
int first_word_quoted, result, builtin_is_special, already_forked, dofork;
pid_t old_last_command_subst_pid, old_last_async_pid;
- Function *builtin;
+ sh_builtin_func_t *builtin;
SHELL_VAR *func;
result = EXECUTION_SUCCESS;
@@ -2434,7 +2502,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
close_fd_bitmap (fds_to_close);
do_piping (pipe_in, pipe_out);
- pipe_in = pipe_out = -1;
+ pipe_in = pipe_out = NO_PIPE;
last_asynchronous_pid = old_last_async_pid;
}
@@ -2488,7 +2556,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
if (echo_command_at_execute)
xtrace_print_word_list (words);
- builtin = (Function *)NULL;
+ builtin = (sh_builtin_func_t *)NULL;
func = (SHELL_VAR *)NULL;
if ((simple_command->flags & CMD_NO_FUNCTIONS) == 0)
{
@@ -2541,12 +2609,12 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
{
char *word;
register int i;
- int wl, cl, exact, substring, match, started_status;
+ int wl, cl, exact_p, substring_p, match, started_status;
register PROCESS *p;
word = words->word->word;
- exact = STREQ (temp, "exact");
- substring = STREQ (temp, "substring");
+ exact_p = STREQ (temp, "exact");
+ substring_p = STREQ (temp, "substring");
wl = strlen (word);
for (i = job_slots - 1; i > -1; i--)
{
@@ -2556,12 +2624,12 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
p = jobs[i]->pipe;
do
{
- if (exact)
+ if (exact_p)
{
cl = strlen (p->command);
match = STREQN (p->command, word, cl);
}
- else if (substring)
+ else if (substring_p)
match = strindex (p->command, word) != (char *)0;
else
match = STREQN (p->command, word, wl);
@@ -2698,7 +2766,7 @@ builtin_status (result)
static int
execute_builtin (builtin, words, flags, subshell)
- Function *builtin;
+ sh_builtin_func_t *builtin;
WORD_LIST *words;
int flags, subshell;
{
@@ -2780,13 +2848,15 @@ static int
execute_function (var, words, flags, fds_to_close, async, subshell)
SHELL_VAR *var;
WORD_LIST *words;
- int flags, subshell, async;
+ int flags;
struct fd_bitmap *fds_to_close;
+ int async, subshell;
{
int return_val, result;
COMMAND *tc, *fc;
- char *debug_trap;
- SHELL_VAR *old_shell_function;
+ char *debug_trap, *error_trap;
+
+ USE_VAR(fc);
tc = (COMMAND *)copy_command (function_cell (var));
if (tc && (flags & CMD_IGNORE_RETURN))
@@ -2808,24 +2878,35 @@ execute_function (var, words, flags, fds_to_close, async, subshell)
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;
+ debug_trap = TRAP_STRING(DEBUG_TRAP);
+ error_trap = TRAP_STRING(ERROR_TRAP);
+
+ /* The order of the unwind protects for debug_trap and error_trap is
+ 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 (subshell == 0)
{
debug_trap = savestring (debug_trap);
- /* XXX order is important here! unwind-protect commands are run
- in reverse order of registering. If this causes problems,
- take out the xfree unwind-protect and live with the small
- memory leak. */
add_unwind_protect (xfree, debug_trap);
add_unwind_protect (set_debug_trap, debug_trap);
}
restore_default_signal (DEBUG_TRAP);
}
+ if (error_trap)
+ {
+ if (subshell == 0)
+ {
+ error_trap = savestring (error_trap);
+ add_unwind_protect (xfree, error_trap);
+ add_unwind_protect (set_error_trap, error_trap);
+ }
+ restore_default_signal (ERROR_TRAP);
+ }
+
/* The temporary environment for a function is supposed to apply to
all commands executed within the function body. */
if (temporary_env)
@@ -2916,7 +2997,7 @@ execute_subshell_builtin_or_function (words, redirects, builtin, var,
flags)
WORD_LIST *words;
REDIRECT *redirects;
- Function *builtin;
+ sh_builtin_func_t *builtin;
SHELL_VAR *var;
int pipe_in, pipe_out, async;
struct fd_bitmap *fds_to_close;
@@ -2995,7 +3076,7 @@ static int
execute_builtin_or_function (words, builtin, var, redirects,
fds_to_close, flags)
WORD_LIST *words;
- Function *builtin;
+ sh_builtin_func_t *builtin;
SHELL_VAR *var;
REDIRECT *redirects;
struct fd_bitmap *fds_to_close;
@@ -3003,7 +3084,7 @@ execute_builtin_or_function (words, builtin, var, redirects,
{
int result;
REDIRECT *saved_undo_list;
- Function *saved_this_shell_builtin;
+ sh_builtin_func_t *saved_this_shell_builtin;
if (do_redirections (redirects, 1, 1, 0) != 0)
{
@@ -3155,7 +3236,7 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
/* This has been disabled for the time being. */
#if !defined (ARG_MAX) || ARG_MAX >= 10240
if (posixly_correct == 0)
- put_gnu_argv_flags_into_env ((int)getpid (), glob_argv_flags);
+ put_gnu_argv_flags_into_env ((long)getpid (), glob_argv_flags);
#endif
#endif
@@ -3184,11 +3265,9 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
do_piping (pipe_in, pipe_out);
+ old_interactive = interactive;
if (async)
- {
- old_interactive = interactive;
- interactive = 0;
- }
+ interactive = 0;
subshell_environment = SUBSHELL_FORK;
@@ -3228,17 +3307,6 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
}
}
-#if !defined (HAVE_HASH_BANG_EXEC)
-/* If the operating system on which we're running does not handle
- the #! executable format, then help out. SAMPLE is the text read
- from the file, SAMPLE_LEN characters. COMMAND is the name of
- the script; it and ARGS, the arguments given by the user, will
- become arguments to the specified interpreter. ENV is the environment
- to pass to the interpreter.
-
- The word immediately following the #! is the interpreter to execute.
- A single argument to the interpreter is allowed. */
-
/* CPP defines to decide whether a particular index into the #! line
corresponds to a valid interpreter name or argument character, or
whitespace. The MSDOS define is to allow \r to be treated the same
@@ -3246,35 +3314,62 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
#if !defined (MSDOS)
# define STRINGCHAR(ind) \
- (!whitespace (sample[ind]) && sample[ind] != '\n' && ind < sample_len)
+ (ind < sample_len && !whitespace (sample[ind]) && sample[ind] != '\n')
# define WHITECHAR(ind) \
- (whitespace (sample[ind]) && sample[ind] != '\n' && ind < sample_len)
+ (ind < sample_len && whitespace (sample[ind]))
#else /* MSDOS */
# define STRINGCHAR(ind) \
- (!whitespace (sample[ind]) && sample[ind] != '\n' && sample[ind] != '\r' && ind < sample_len)
+ (ind < sample_len && !whitespace (sample[ind]) && sample[ind] != '\n' && sample[ind] != '\r')
# define WHITECHAR(ind) \
- (whitespace (sample[ind]) && sample[ind] != '\n' && sample[ind] != '\r' && ind < sample_len)
+ (ind < sample_len && whitespace (sample[ind]))
#endif /* MSDOS */
-static int
-execute_shell_script (sample, sample_len, command, args, env)
- unsigned char *sample;
- int sample_len;
- char *command;
- char **args, **env;
+static char *
+getinterp (sample, sample_len, endp)
+ char *sample;
+ int sample_len, *endp;
{
register int i;
- char *execname, *firstarg;
- int start, size_increment, larry;
+ char *execname;
+ int start;
/* Find the name of the interpreter to exec. */
- for (i = 2; whitespace (sample[i]) && i < sample_len; i++)
+ for (i = 2; i < sample_len && whitespace (sample[i]); i++)
;
for (start = i; STRINGCHAR(i); i++)
;
- execname = substring ((char *)sample, start, i);
+ execname = substring (sample, start, i);
+
+ if (endp)
+ *endp = i;
+ return execname;
+}
+
+#if !defined (HAVE_HASH_BANG_EXEC)
+/* If the operating system on which we're running does not handle
+ the #! executable format, then help out. SAMPLE is the text read
+ from the file, SAMPLE_LEN characters. COMMAND is the name of
+ the script; it and ARGS, the arguments given by the user, will
+ become arguments to the specified interpreter. ENV is the environment
+ to pass to the interpreter.
+
+ The word immediately following the #! is the interpreter to execute.
+ A single argument to the interpreter is allowed. */
+
+static int
+execute_shell_script (sample, sample_len, command, args, env)
+ char *sample;
+ int sample_len;
+ char *command;
+ char **args, **env;
+{
+ char *execname, *firstarg;
+ int i, start, size_increment, larry;
+
+ /* Find the name of the interpreter to exec. */
+ execname = getinterp (sample, sample_len, &i);
size_increment = 1;
/* Now the argument, if any. */
@@ -3371,7 +3466,7 @@ initialize_subshell ()
fd = open(file, O_RDONLY); \
if (fd >= 0) \
{ \
- len = read (fd, (char *)buf, 80); \
+ len = read (fd, buf, 80); \
close (fd); \
} \
else \
@@ -3388,7 +3483,7 @@ shell_execve (command, args, env)
{
struct stat finfo;
int larray, i, fd;
- unsigned char sample[80];
+ char sample[80];
int sample_len;
SETOSTYPE (0); /* Some systems use for USG/POSIX semantics */
@@ -3408,8 +3503,12 @@ shell_execve (command, args, env)
READ_SAMPLE_BUF (command, sample, sample_len);
if (sample_len > 2 && sample[0] == '#' && sample[1] == '!')
{
+ char *interp;
+
+ interp = getinterp (sample, sample_len, (int *)NULL);
errno = i;
- sys_error ("%s: bad interpreter", command);
+ sys_error ("%s: %s: bad interpreter", command, interp ? interp : "");
+ FREE (interp);
return (EX_NOEXEC);
}
#endif
@@ -3494,6 +3593,7 @@ shell_execve (command, args, env)
unbind_args (); /* remove the positional parameters */
longjmp (subshell_top_level, 1);
+ /*NOTREACHED*/
}
static int