diff options
author | Jari Aalto <jari.aalto@cante.net> | 2002-07-17 14:10:11 +0000 |
---|---|---|
committer | Jari Aalto <jari.aalto@cante.net> | 2009-09-12 16:46:55 +0000 |
commit | 7117c2d221b2aed4ede8600f6a36b7c1454b4f55 (patch) | |
tree | b792f26ecca68813c51ed5ba2e381790758ef31b /execute_cmd.c | |
parent | f73dda092b33638d2d5e9c35375f687a607b5403 (diff) | |
download | android_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.c | 316 |
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); |