diff options
author | Jari Aalto <jari.aalto@cante.net> | 2001-11-13 17:56:06 +0000 |
---|---|---|
committer | Jari Aalto <jari.aalto@cante.net> | 2009-09-12 16:46:54 +0000 |
commit | f73dda092b33638d2d5e9c35375f687a607b5403 (patch) | |
tree | f21584e70a444d6a1ecba0fb5e2cf79e8cce91db /execute_cmd.c | |
parent | 28ef6c316f1aff914bb95ac09787a3c83c1815fd (diff) | |
download | android_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.c | 408 |
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 |