From f486d0a16bf48978ab2578cda86eba18988f4a7e Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Thu, 8 Dec 2011 20:21:31 -0500 Subject: [PATCH] commit bash-20091124 snapshot --- CWRU/CWRU.chlog | 65 ++++- CWRU/CWRU.chlog~ | 59 ++++- builtins/declare.def | 9 +- builtins/declare.def~ | 557 +++++++++++++++++++++++++++++++++++++++ builtins/evalstring.c~ | 4 +- execute_cmd.c | 28 +- execute_cmd.c~ | 29 +- general.c | 2 +- general.c~ | 2 +- jobs.c | 4 + jobs.c~ | 9 +- lib/readline/complete.c | 6 +- lib/readline/complete.c~ | 12 +- lib/readline/signals.c | 5 +- lib/readline/signals.c~ | 63 ++++- lib/readline/util.c | 3 +- lib/readline/util.c~ | 2 +- subst.c | 6 +- subst.c~ | 11 +- tests/RUN-ONE-TEST | 2 +- tests/exec.right | 2 +- 21 files changed, 828 insertions(+), 52 deletions(-) create mode 100644 builtins/declare.def~ diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index c04c53869..3501bad3c 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -5772,7 +5772,7 @@ bracecomp.c lib/readline/{rltty,signals}.c - move block_sigint and release_sigint from rltty.c to signals.c; add _rl_ prefix to make them public to the library; change callers. - From Jan Kratchovil + From Jan Kratochvil lib/readline/rlprivate.h - new extern declarations for _rl_block_sigint and _rl_release_sigint @@ -5780,7 +5780,7 @@ lib/readline/rlprivate.h lib/readline/display.c - add calls to _rl_block_sigint and _rl_release_sigint to rl_redisplay, since it maniupluates global data structures. Fix from Jan - Kratchovil + Kratochvil builtins/printf.def - change calls to asprintf and manually adding to vbuf to use calls @@ -9205,3 +9205,64 @@ configure.in,aclocal.m4 and working as C99 specifies with a zero length argument. Idea from Greg Wooledge - new macro BASH_FUNC_VSNPRINTF, does same thing for vsnprintf + + 11/25 + ----- +subst.c + - in command_substitute, only tell parse_and_execute to reset the line + number in an interactive shell if sourcelevel == 0 -- we'll use the + line numbers from the sourced file + +execute_cmd.c + - in execute_simple_command, only subtract function_line_number from + line_number if sourcelevel == 0. If sourcing, we'll use the line + numbers from the sourced file. Fixes bug reported by Hugo + Mildenberger + +builtins/declare.def + - in declare_internal, call bind_assoc_variable instead of + bind_array_variable in the case of declare -A foo=bar. Fixes bug + reported by Bernd Eggink . + + 11/27 + ----- +lib/readline/util.c + - change declaration for _rl_walphabetic to use prototype, assuming + that any system with multibyte characters has a compiler that can + handle prototypes. Fix for AIX compilation problem reported by + Nick Hillman + + 11/28 + ----- +execute_cmd.c + - make funcnest file-scope static and unwind-protect its value in + execute_function, so it can be used as a real measure of function + call nesting + +general.c + - fix off-by-one error in trim_pathname that caused it to short-circuit + when PROMPT_DIRTRIM == number of directories - 1. Fixes bug + reported by Dennis Williamson + + 11/29 + ----- +jobs.c + - when fork() returns -1/EAGAIN, call waitchld(-1, 0) so the shell can + reap any dead jobs before trying fork again. Currently disabled + until bash-4.2 development starts + +lib/readline/complete.c + - when incrementing _rl_interrupt_immediately, make sure it's greater + than 0 before decrementing it. In practice, not a problem, but + the right way to do it. Suggested by Jan Kratochvil + + +lib/readline/signals.c + - make sure rl_signal_handler doesn't set rl_caught_signal if + _rl_interrupt_immediately is set, so RL_CHECK_SIGNALS doesn't + cause it to be processed twice. Suggested by Jan Kratochvil + + - if the callback interface is being used, use the code path that + immediately handles signals. This restores the readline-5.2 + behavior. Fixes GDB readline bug reported by Jan Kratochvil + diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~ index 5c7b52622..92b2e3aae 100644 --- a/CWRU/CWRU.chlog~ +++ b/CWRU/CWRU.chlog~ @@ -5772,7 +5772,7 @@ bracecomp.c lib/readline/{rltty,signals}.c - move block_sigint and release_sigint from rltty.c to signals.c; add _rl_ prefix to make them public to the library; change callers. - From Jan Kratchovil + From Jan Kratochvil lib/readline/rlprivate.h - new extern declarations for _rl_block_sigint and _rl_release_sigint @@ -5780,7 +5780,7 @@ lib/readline/rlprivate.h lib/readline/display.c - add calls to _rl_block_sigint and _rl_release_sigint to rl_redisplay, since it maniupluates global data structures. Fix from Jan - Kratchovil + Kratochvil builtins/printf.def - change calls to asprintf and manually adding to vbuf to use calls @@ -9204,6 +9204,61 @@ configure.in,aclocal.m4 - new autoconf macro, BASH_FUNC_SNPRINTF, checks for snprintf present and working as C99 specifies with a zero length argument. Idea from Greg Wooledge + - new macro BASH_FUNC_VSNPRINTF, does same thing for vsnprintf + 11/25 + ----- +subst.c + - in command_substitute, only tell parse_and_execute to reset the line + number in an interactive shell if sourcelevel == 0 -- we'll use the + line numbers from the sourced file + +execute_cmd.c + - in execute_simple_command, only subtract function_line_number from + line_number if sourcelevel == 0. If sourcing, we'll use the line + numbers from the sourced file. Fixes bug reported by Hugo + Mildenberger + +builtins/declare.def + - in declare_internal, call bind_assoc_variable instead of + bind_array_variable in the case of declare -A foo=bar. Fixes bug + reported by Bernd Eggink . + 11/27 + ----- +lib/readline/util.c + - change declaration for _rl_walphabetic to use prototype, assuming + that any system with multibyte characters has a compiler that can + handle prototypes. Fix for AIX compilation problem reported by + Nick Hillman + 11/28 + ----- +execute_cmd.c + - make funcnest file-scope static and unwind-protect its value in + execute_function, so it can be used as a real measure of function + call nesting + +general.c + - fix off-by-one error in trim_pathname that caused it to short-circuit + when PROMPT_DIRTRIM == number of directories - 1. Fixes bug + reported by Dennis Williamson + + 11/29 + ----- +jobs.c + - when fork() returns -1/EAGAIN, call waitchld(-1, 0) so the shell can + reap any dead jobs before trying fork again. Currently disabled + until bash-4.2 development starts + +lib/readline/complete.c + - when incrementing _rl_interrupt_immediately, make sure it's greater + than 0 before decrementing it. In practice, not a problem, but + the right way to do it. Suggested by Jan Kratochvil + + +lib/readline/signals.c + - make sure rl_signal_handler doesn't set rl_caught_signal if + _rl_interrupt_immediately is set, so RL_CHECK_SIGNALS doesn't + cause it to be processed twice. Suggested by Jan Kratochvil + diff --git a/builtins/declare.def b/builtins/declare.def index bef8ec2c8..a0ce60549 100644 --- a/builtins/declare.def +++ b/builtins/declare.def @@ -509,8 +509,13 @@ declare_internal (list, local_var) *subscript_start = '\0'; } else if (simple_array_assign) - /* let bind_array_variable take care of this. */ - bind_array_variable (name, 0, value, aflags); + { + /* let bind_{array,assoc}_variable take care of this. */ + if (assoc_p (var)) + bind_assoc_variable (var, name, "0", value, aflags); + else + bind_array_variable (name, 0, value, aflags); + } else #endif /* bind_variable_value duplicates the essential internals of diff --git a/builtins/declare.def~ b/builtins/declare.def~ new file mode 100644 index 000000000..bef8ec2c8 --- /dev/null +++ b/builtins/declare.def~ @@ -0,0 +1,557 @@ +This file is declare.def, from which is created declare.c. +It implements the builtins "declare" and "local" in Bash. + +Copyright (C) 1987-2009 Free Software Foundation, Inc. + +This file is part of GNU Bash, the Bourne Again SHell. + +Bash is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Bash is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Bash. If not, see . + +$PRODUCES declare.c + +$BUILTIN declare +$FUNCTION declare_builtin +$SHORT_DOC declare [-aAfFilrtux] [-p] [name[=value] ...] +Set variable values and attributes. + +Declare variables and give them attributes. If no NAMEs are given, +display the attributes and values of all variables. + +Options: + -f restrict action or display to function names and definitions + -F restrict display to function names only (plus line number and + source file when debugging) + -p display the attributes and value of each NAME + +Options which set attributes: + -a to make NAMEs indexed arrays (if supported) + -A to make NAMEs associative arrays (if supported) + -i to make NAMEs have the `integer' attribute + -l to convert NAMEs to lower case on assignment + -r to make NAMEs readonly + -t to make NAMEs have the `trace' attribute + -u to convert NAMEs to upper case on assignment + -x to make NAMEs export + +Using `+' instead of `-' turns off the given attribute. + +Variables with the integer attribute have arithmetic evaluation (see +the `let' command) performed when the variable is assigned a value. + +When used in a function, `declare' makes NAMEs local, as with the `local' +command. + +Exit Status: +Returns success unless an invalid option is supplied or an error occurs. +$END + +$BUILTIN typeset +$FUNCTION declare_builtin +$SHORT_DOC typeset [-aAfFilrtux] [-p] name[=value] ... +Set variable values and attributes. + +Obsolete. See `help declare'. +$END + +#include + +#if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif +# include +#endif + +#include + +#include "../bashansi.h" +#include "../bashintl.h" + +#include "../shell.h" +#include "common.h" +#include "builtext.h" +#include "bashgetopt.h" + +extern int array_needs_making; +extern int posixly_correct; + +static int declare_internal __P((register WORD_LIST *, int)); + +/* Declare or change variable attributes. */ +int +declare_builtin (list) + register WORD_LIST *list; +{ + return (declare_internal (list, 0)); +} + +$BUILTIN local +$FUNCTION local_builtin +$SHORT_DOC local [option] name[=value] ... +Define local variables. + +Create a local variable called NAME, and give it VALUE. OPTION can +be any option accepted by `declare'. + +Local variables can only be used within a function; they are visible +only to the function where they are defined and its children. + +Exit Status: +Returns success unless an invalid option is supplied, an error occurs, +or the shell is not executing a function. +$END +int +local_builtin (list) + register WORD_LIST *list; +{ + if (variable_context) + return (declare_internal (list, 1)); + else + { + builtin_error (_("can only be used in a function")); + return (EXECUTION_FAILURE); + } +} + +#if defined (ARRAY_VARS) +# define DECLARE_OPTS "+acfilprtuxAF" +#else +# define DECLARE_OPTS "+cfilprtuxF" +#endif + +/* The workhorse function. */ +static int +declare_internal (list, local_var) + register WORD_LIST *list; + int local_var; +{ + int flags_on, flags_off, *flags; + int any_failed, assign_error, pflag, nodefs, opt; + char *t, *subscript_start; + SHELL_VAR *var; + FUNCTION_DEF *shell_fn; + + flags_on = flags_off = any_failed = assign_error = pflag = nodefs = 0; + reset_internal_getopt (); + while ((opt = internal_getopt (list, DECLARE_OPTS)) != EOF) + { + flags = list_opttype == '+' ? &flags_off : &flags_on; + + switch (opt) + { + case 'a': +#if defined (ARRAY_VARS) + *flags |= att_array; + break; +#else + builtin_usage (); + return (EX_USAGE); +#endif + case 'A': +#if defined (ARRAY_VARS) + *flags |= att_assoc; + break; +#else + builtin_usage (); + return (EX_USAGE); +#endif + case 'p': + if (local_var == 0) + pflag++; + break; + case 'F': + nodefs++; + *flags |= att_function; + break; + case 'f': + *flags |= att_function; + break; + case 'i': + *flags |= att_integer; + break; + case 'r': + *flags |= att_readonly; + break; + case 't': + *flags |= att_trace; + break; + case 'x': + *flags |= att_exported; + array_needs_making = 1; + break; +#if defined (CASEMOD_ATTRS) +# if defined (CASEMOD_CAPCASE) + case 'c': + *flags |= att_capcase; + if (flags == &flags_on) + flags_off |= att_uppercase|att_lowercase; + break; +# endif + case 'l': + *flags |= att_lowercase; + if (flags == &flags_on) + flags_off |= att_capcase|att_uppercase; + break; + case 'u': + *flags |= att_uppercase; + if (flags == &flags_on) + flags_off |= att_capcase|att_lowercase; + break; +#endif /* CASEMOD_ATTRS */ + default: + builtin_usage (); + return (EX_USAGE); + } + } + + list = loptend; + + /* If there are no more arguments left, then we just want to show + some variables. */ + if (list == 0) /* declare -[aAfFirtx] */ + { + /* Show local variables defined at this context level if this is + the `local' builtin. */ + if (local_var) + { + register SHELL_VAR **vlist; + register int i; + + vlist = all_local_variables (); + + if (vlist) + { + for (i = 0; vlist[i]; i++) + print_assignment (vlist[i]); + + free (vlist); + } + } + else if (pflag && (flags_on == 0 || flags_on == att_function)) + show_all_var_attributes (flags_on == 0, nodefs); + else if (flags_on == 0) + return (set_builtin ((WORD_LIST *)NULL)); + else + set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs); + + return (sh_chkwrite (EXECUTION_SUCCESS)); + } + + if (pflag) /* declare -p [-aAfFirtx] name [name...] */ + { + for (any_failed = 0; list; list = list->next) + { + pflag = show_name_attributes (list->word->word, nodefs); + if (pflag) + { + sh_notfound (list->word->word); + any_failed++; + } + } + return (sh_chkwrite (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS)); + } + +#define NEXT_VARIABLE() free (name); list = list->next; continue + + /* There are arguments left, so we are making variables. */ + while (list) /* declare [-aAfFirx] name [name ...] */ + { + char *value, *name; + int offset, aflags; +#if defined (ARRAY_VARS) + int making_array_special, compound_array_assign, simple_array_assign; +#endif + + name = savestring (list->word->word); + offset = assignment (name, 0); + aflags = 0; + + if (offset) /* declare [-aAfFirx] name=value */ + { + name[offset] = '\0'; + value = name + offset + 1; + if (name[offset - 1] == '+') + { + aflags |= ASS_APPEND; + name[offset - 1] = '\0'; + } + } + else + value = ""; + +#if defined (ARRAY_VARS) + compound_array_assign = simple_array_assign = 0; + subscript_start = (char *)NULL; + if (t = strchr (name, '[')) /* ] */ + { + /* If offset != 0 we have already validated any array reference */ + if (offset == 0 && valid_array_reference (name) == 0) + { + sh_invalidid (name); + assign_error++; + NEXT_VARIABLE (); + } + subscript_start = t; + *t = '\0'; + making_array_special = 1; + } + else + making_array_special = 0; +#endif + + /* If we're in posix mode or not looking for a shell function (since + shell function names don't have to be valid identifiers when the + shell's not in posix mode), check whether or not the argument is a + valid, well-formed shell identifier. */ + if ((posixly_correct || (flags_on & att_function) == 0) && legal_identifier (name) == 0) + { + sh_invalidid (name); + assign_error++; + NEXT_VARIABLE (); + } + + /* If VARIABLE_CONTEXT has a non-zero value, then we are executing + inside of a function. This means we should make local variables, + not global ones. */ + + /* XXX - this has consequences when we're making a local copy of a + variable that was in the temporary environment. Watch out + for this. */ + if (variable_context && ((flags_on & att_function) == 0)) + { +#if defined (ARRAY_VARS) + if (flags_on & att_assoc) + var = make_local_assoc_variable (name); + else if ((flags_on & att_array) || making_array_special) + var = make_local_array_variable (name); + else +#endif + var = make_local_variable (name); + if (var == 0) + { + any_failed++; + NEXT_VARIABLE (); + } + } + else + var = (SHELL_VAR *)NULL; + + /* If we are declaring a function, then complain about it in some way. + We don't let people make functions by saying `typeset -f foo=bar'. */ + + /* There should be a way, however, to let people look at a particular + function definition by saying `typeset -f foo'. */ + + if (flags_on & att_function) + { + if (offset) /* declare -f [-rix] foo=bar */ + { + builtin_error (_("cannot use `-f' to make functions")); + free (name); + return (EXECUTION_FAILURE); + } + else /* declare -f [-rx] name [name...] */ + { + var = find_function (name); + + if (var) + { + if (readonly_p (var) && (flags_off & att_readonly)) + { + builtin_error (_("%s: readonly function"), name); + any_failed++; + NEXT_VARIABLE (); + } + + /* declare -[Ff] name [name...] */ + if (flags_on == att_function && flags_off == 0) + { +#if defined (DEBUGGER) + if (nodefs && debugging_mode) + { + shell_fn = find_function_def (var->name); + if (shell_fn) + printf ("%s %d %s\n", var->name, shell_fn->line, shell_fn->source_file); + else + printf ("%s\n", var->name); + } + else +#endif /* DEBUGGER */ + { + t = nodefs ? var->name + : named_function_string (name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL); + printf ("%s\n", t); + any_failed = sh_chkwrite (any_failed); + } + } + else /* declare -[fF] -[rx] name [name...] */ + { + VSETATTR (var, flags_on); + VUNSETATTR (var, flags_off); + } + } + else + any_failed++; + NEXT_VARIABLE (); + } + } + else /* declare -[aAirx] name [name...] */ + { + /* Non-null if we just created or fetched a local variable. */ + if (var == 0) + var = find_variable (name); + + if (var == 0) + { +#if defined (ARRAY_VARS) + if (flags_on & att_assoc) + var = make_new_assoc_variable (name); + else if ((flags_on & att_array) || making_array_special) + var = make_new_array_variable (name); + else +#endif + + if (offset) + var = bind_variable (name, "", 0); + else + { + var = bind_variable (name, (char *)NULL, 0); + VSETATTR (var, att_invisible); + } + } + + /* Cannot use declare +r to turn off readonly attribute. */ + if (readonly_p (var) && (flags_off & att_readonly)) + { + sh_readonly (name); + any_failed++; + NEXT_VARIABLE (); + } + + /* Cannot use declare to assign value to readonly or noassign + variable. */ + if ((readonly_p (var) || noassign_p (var)) && offset) + { + if (readonly_p (var)) + sh_readonly (name); + assign_error++; + NEXT_VARIABLE (); + } + +#if defined (ARRAY_VARS) + if ((making_array_special || (flags_on & (att_array|att_assoc)) || array_p (var) || assoc_p (var)) && offset) + { + int vlen; + vlen = STRLEN (value); + + if (value[0] == '(' && value[vlen-1] == ')') + compound_array_assign = 1; + else + simple_array_assign = 1; + } + + /* Cannot use declare +a name or declare +A name to remove an + array variable. */ + if (((flags_off & att_array) && array_p (var)) || ((flags_off & att_assoc) && assoc_p (var))) + { + builtin_error (_("%s: cannot destroy array variables in this way"), name); + any_failed++; + NEXT_VARIABLE (); + } + + if ((flags_on & att_array) && assoc_p (var)) + { + builtin_error (_("%s: cannot convert associative to indexed array"), name); + any_failed++; + NEXT_VARIABLE (); + } + if ((flags_on & att_assoc) && array_p (var)) + { + builtin_error (_("%s: cannot convert indexed to associative array"), name); + any_failed++; + NEXT_VARIABLE (); + } + + /* declare -A name[[n]] makes name an associative array variable. */ + if (flags_on & att_assoc) + { + if (assoc_p (var) == 0) + var = convert_var_to_assoc (var); + } + /* declare -a name[[n]] or declare name[n] makes name an indexed + array variable. */ + else if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0 && assoc_p (var) == 0) + var = convert_var_to_array (var); +#endif /* ARRAY_VARS */ + + VSETATTR (var, flags_on); + VUNSETATTR (var, flags_off); + +#if defined (ARRAY_VARS) + if (offset && compound_array_assign) + assign_array_var_from_string (var, value, aflags); + else if (simple_array_assign && subscript_start) + { + /* declare [-aA] name[N]=value */ + *subscript_start = '['; /* ] */ + var = assign_array_element (name, value, 0); /* XXX - not aflags */ + *subscript_start = '\0'; + } + else if (simple_array_assign) + /* let bind_array_variable take care of this. */ + bind_array_variable (name, 0, value, aflags); + else +#endif + /* bind_variable_value duplicates the essential internals of + bind_variable() */ + if (offset) + bind_variable_value (var, value, aflags); + + /* If we found this variable in the temporary environment, as with + `var=value declare -x var', make sure it is treated identically + to `var=value export var'. Do the same for `declare -r' and + `readonly'. Preserve the attributes, except for att_tempvar. */ + /* XXX -- should this create a variable in the global scope, or + modify the local variable flags? ksh93 has it modify the + global scope. + Need to handle case like in set_var_attribute where a temporary + variable is in the same table as the function local vars. */ + if ((flags_on & (att_exported|att_readonly)) && tempvar_p (var)) + { + SHELL_VAR *tv; + char *tvalue; + + tv = find_tempenv_variable (var->name); + if (tv) + { + tvalue = var_isset (var) ? savestring (value_cell (var)) : savestring (""); + tv = bind_variable (var->name, tvalue, 0); + tv->attributes |= var->attributes & ~att_tempvar; + if (tv->context > 0) + VSETATTR (tv, att_propagate); + free (tvalue); + } + VSETATTR (var, att_propagate); + } + } + + stupidly_hack_special_variables (name); + + NEXT_VARIABLE (); + } + + return (assign_error ? EX_BADASSIGN + : ((any_failed == 0) ? EXECUTION_SUCCESS + : EXECUTION_FAILURE)); +} diff --git a/builtins/evalstring.c~ b/builtins/evalstring.c~ index 598129fde..c705ecc8c 100644 --- a/builtins/evalstring.c~ +++ b/builtins/evalstring.c~ @@ -181,7 +181,7 @@ parse_and_execute (string, from_file, flags) parse_and_execute_level++; lreset = flags & SEVAL_RESETLINE; - +itrace("parse_and_execute: lreset = %d", lreset); /* Reset the line number if the caller wants us to. If we don't reset the line number, we have to subtract one, because we will add one just before executing the next command (resetting the line number sets it to @@ -331,7 +331,7 @@ parse_and_execute (string, from_file, flags) (this_shell_builtin == source_builtin || this_shell_builtin == eval_builtin) && last_command_exit_value == EX_BADSYNTAX && posixly_correct) { -#if 1 /* XXX - for bash-4.2 */ +#if 0 /* XXX - for bash-4.2 */ should_jump_to_top_level = 1; code = ERREXIT; last_command_exit_value = EX_BADUSAGE; diff --git a/execute_cmd.c b/execute_cmd.c index 6fdcb6f33..c6dc29e92 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -100,7 +100,7 @@ extern int posixly_correct; extern int expand_aliases; extern int autocd; extern int breaking, continuing, loop_level; -extern int parse_and_execute_level, running_trap; +extern int parse_and_execute_level, running_trap, sourcelevel; extern int command_string_index, line_number; extern int dot_found_in_search; extern int already_making_children; @@ -267,6 +267,10 @@ static int showing_function_line; static int line_number_for_err_trap; +/* A sort of function nesting level counter */ +static int funcnest = 0; +int funcnest_max = 0; /* XXX - for bash-4.2 */ + struct fd_bitmap *current_fds_to_close = (struct fd_bitmap *)NULL; #define FD_BITMAP_DEFAULT_SIZE 32 @@ -3215,8 +3219,10 @@ execute_cond_node (cond) ignore = (cond->flags & CMD_IGNORE_RETURN); if (ignore) { - cond->left->flags |= CMD_IGNORE_RETURN; - cond->right->flags |= CMD_IGNORE_RETURN; + if (cond->left) + cond->left->flags |= CMD_IGNORE_RETURN; + if (cond->right) + cond->right->flags |= CMD_IGNORE_RETURN; } if (cond->type == COND_EXPR) @@ -3331,7 +3337,6 @@ execute_cond_command (cond_command) /* If we're in a function, update the line number information. */ if (variable_context && interactive_shell) line_number -= function_line_number; - command_string_index = 0; print_cond_command (cond_command); @@ -3532,7 +3537,7 @@ 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 && interactive_shell) + if (variable_context && interactive_shell && sourcelevel == 0) line_number -= function_line_number; /* Remember what this command line looks like at invocation. */ @@ -4001,10 +4006,17 @@ execute_function (var, words, flags, fds_to_close, async, subshell) #endif FUNCTION_DEF *shell_fn; char *sfile, *t; - static int funcnest = 0; USE_VAR(fc); +#if 0 /* for bash-4.2 */ + if (funcnest_max > 0 && funcnest >= funcnest_max) + { + internal_error ("%s: maximum function nesting level exceeded (%d)", var->name, funcnest); + jump_to_top_level (DISCARD); + } +#endif + #if defined (ARRAY_VARS) GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v, funcname_a); GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v, bash_source_a); @@ -4026,6 +4038,7 @@ execute_function (var, words, flags, fds_to_close, async, subshell) add_unwind_protect (dispose_command, (char *)tc); unwind_protect_pointer (this_shell_function); unwind_protect_int (loop_level); + unwind_protect_int (funcnest); } else push_context (var->name, subshell, temporary_env); /* don't unwind-protect for subshells */ @@ -4167,7 +4180,6 @@ execute_function (var, words, flags, fds_to_close, async, subshell) if (subshell == 0) run_unwind_frame ("function_calling"); - funcnest--; #if defined (ARRAY_VARS) /* These two variables cannot be unset, and cannot be affected by the function. */ @@ -4725,7 +4737,7 @@ initialize_subshell () parse_and_execute_level = 0; /* nothing left to restore it */ /* We're no longer inside a shell function. */ - variable_context = return_catch_flag = 0; + variable_context = return_catch_flag = funcnest = 0; executing_list = 0; /* XXX */ diff --git a/execute_cmd.c~ b/execute_cmd.c~ index 97c6932f2..58eab4e96 100644 --- a/execute_cmd.c~ +++ b/execute_cmd.c~ @@ -100,7 +100,7 @@ extern int posixly_correct; extern int expand_aliases; extern int autocd; extern int breaking, continuing, loop_level; -extern int parse_and_execute_level, running_trap; +extern int parse_and_execute_level, running_trap, sourcelevel; extern int command_string_index, line_number; extern int dot_found_in_search; extern int already_making_children; @@ -267,6 +267,10 @@ static int showing_function_line; static int line_number_for_err_trap; +/* A sort of function nesting level counter */ +static int funcnest = 0; +int funcnest_max = 256; + struct fd_bitmap *current_fds_to_close = (struct fd_bitmap *)NULL; #define FD_BITMAP_DEFAULT_SIZE 32 @@ -3213,7 +3217,14 @@ execute_cond_node (cond) invert = (cond->flags & CMD_INVERT_RETURN); ignore = (cond->flags & CMD_IGNORE_RETURN); - + if (ignore) + { + if (cond->left) + cond->left->flags |= CMD_IGNORE_RETURN; + if (cond->right) + cond->right->flags |= CMD_IGNORE_RETURN; + } + if (cond->type == COND_EXPR) result = execute_cond_node (cond->left); else if (cond->type == COND_OR) @@ -3326,7 +3337,6 @@ execute_cond_command (cond_command) /* If we're in a function, update the line number information. */ if (variable_context && interactive_shell) line_number -= function_line_number; - command_string_index = 0; print_cond_command (cond_command); @@ -3527,7 +3537,7 @@ 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 && interactive_shell) + if (variable_context && interactive_shell && sourcelevel == 0) line_number -= function_line_number; /* Remember what this command line looks like at invocation. */ @@ -3996,10 +4006,15 @@ execute_function (var, words, flags, fds_to_close, async, subshell) #endif FUNCTION_DEF *shell_fn; char *sfile, *t; - static int funcnest = 0; USE_VAR(fc); + if (funcnest_max > 0 && funcnest >= funcnest_max) + { + internal_error ("%s: maximum function nesting level exceeded (%d)", var->name, funcnest); + jump_to_top_level (DISCARD); + } + #if defined (ARRAY_VARS) GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v, funcname_a); GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v, bash_source_a); @@ -4021,6 +4036,7 @@ execute_function (var, words, flags, fds_to_close, async, subshell) add_unwind_protect (dispose_command, (char *)tc); unwind_protect_pointer (this_shell_function); unwind_protect_int (loop_level); + unwind_protect_int (funcnest); } else push_context (var->name, subshell, temporary_env); /* don't unwind-protect for subshells */ @@ -4162,7 +4178,6 @@ execute_function (var, words, flags, fds_to_close, async, subshell) if (subshell == 0) run_unwind_frame ("function_calling"); - funcnest--; #if defined (ARRAY_VARS) /* These two variables cannot be unset, and cannot be affected by the function. */ @@ -4720,7 +4735,7 @@ initialize_subshell () parse_and_execute_level = 0; /* nothing left to restore it */ /* We're no longer inside a shell function. */ - variable_context = return_catch_flag = 0; + variable_context = return_catch_flag = funcnest = 0; executing_list = 0; /* XXX */ diff --git a/general.c b/general.c index 36b2f5b3a..26c7d3db6 100644 --- a/general.c +++ b/general.c @@ -717,7 +717,7 @@ trim_pathname (name, maxlen) for (ndirs = 0, ntail = nbeg; *ntail; ntail++) if (*ntail == '/') ndirs++; - if (ndirs <= nskip) + if (ndirs < nskip) return name; for (ntail = (*nend == '/') ? nend : nend - 1; ntail > nbeg; ntail--) diff --git a/general.c~ b/general.c~ index 7fc71187f..36b2f5b3a 100644 --- a/general.c~ +++ b/general.c~ @@ -98,7 +98,7 @@ string_to_rlimtype (s) neg = 0; while (s && *s && whitespace (*s)) s++; - if (*s == '-' || *s == '+') + if (s && (*s == '-' || *s == '+')) { neg = *s == '-'; s++; diff --git a/jobs.c b/jobs.c index 6958b3a4a..df13ad9e9 100644 --- a/jobs.c +++ b/jobs.c @@ -1708,6 +1708,10 @@ make_child (command, async_p) /* Create the child, handle severe errors. Retry on EAGAIN. */ while ((pid = fork ()) < 0 && errno == EAGAIN && forksleep < FORKSLEEP_MAX) { +#if 0 /* for bash-4.2 */ + /* If we can't create any children, try to reap some dead ones. */ + waitchld (-1, 0); +#endif sys_error ("fork: retry"); if (sleep (forksleep) != 0) break; diff --git a/jobs.c~ b/jobs.c~ index 2bbfb8f6a..33211139f 100644 --- a/jobs.c~ +++ b/jobs.c~ @@ -481,7 +481,6 @@ stop_pipeline (async, deferred) JOB *newjob; sigset_t set, oset; -itrace("stop_pipeline"); BLOCK_CHILD (set, oset); #if defined (PGRP_PIPE) @@ -702,8 +701,7 @@ bgp_delete (pid) for (prev = p = bgpids.list; p; prev = p, p = p->next) if (p->pid == pid) { - if (p != prev) - prev->next = p->next; /* remove from list */ + prev->next = p->next; /* remove from list */ break; } @@ -1102,7 +1100,6 @@ add_process (name, pid) { PROCESS *t, *p; -itrace("add_process; %s (%d)", name, pid); #if defined (RECYCLES_PIDS) int j; p = find_process (pid, 0, &j); @@ -1711,6 +1708,10 @@ make_child (command, async_p) /* Create the child, handle severe errors. Retry on EAGAIN. */ while ((pid = fork ()) < 0 && errno == EAGAIN && forksleep < FORKSLEEP_MAX) { +#if 0 /* for bash-4.2 */ + /* If we can't create any children, try to wait for some dead ones. */ + waitchld (-1, 0); +#endif sys_error ("fork: retry"); if (sleep (forksleep) != 0) break; diff --git a/lib/readline/complete.c b/lib/readline/complete.c index 9ba54268b..ad9ca0515 100644 --- a/lib/readline/complete.c +++ b/lib/readline/complete.c @@ -1038,7 +1038,8 @@ gen_completion_matches (text, start, end, our_func, found_quote, quote_char) { _rl_interrupt_immediately++; matches = (*rl_attempted_completion_function) (text, start, end); - _rl_interrupt_immediately--; + if (_rl_interrupt_immediately > 0) + _rl_interrupt_immediately--; if (matches || rl_attempted_completion_over) { @@ -1929,7 +1930,8 @@ rl_completion_matches (text, entry_function) match_list[++matches] = string; match_list[matches + 1] = (char *)NULL; } - _rl_interrupt_immediately--; + if (_rl_interrupt_immediately > 0) + _rl_interrupt_immediately--; /* If there were any matches, then look through them finding out the lowest common denominator. That then becomes match_list[0]. */ diff --git a/lib/readline/complete.c~ b/lib/readline/complete.c~ index 913c8dec1..d9af5cf1e 100644 --- a/lib/readline/complete.c~ +++ b/lib/readline/complete.c~ @@ -1038,7 +1038,8 @@ gen_completion_matches (text, start, end, our_func, found_quote, quote_char) { _rl_interrupt_immediately++; matches = (*rl_attempted_completion_function) (text, start, end); - _rl_interrupt_immediately--; + if (_rl_interrupt_immediately) + _rl_interrupt_immediately--; if (matches || rl_attempted_completion_over) { @@ -1570,7 +1571,7 @@ insert_match (match, start, mtype, qc) { char *replacement, *r; char oqc; - int end; + int end, rlen; oqc = qc ? *qc : '\0'; replacement = make_quoted_replacement (match, mtype, qc); @@ -1578,6 +1579,7 @@ insert_match (match, start, mtype, qc) /* Now insert the match. */ if (replacement) { + rlen = strlen (replacement); /* Don't double an opening quote character. */ if (qc && *qc && start && rl_line_buffer[start - 1] == *qc && replacement[0] == *qc) @@ -1588,6 +1590,9 @@ insert_match (match, start, mtype, qc) replacement[0] != oqc) start--; end = rl_point - 1; + /* Don't double a closing quote character */ + if (qc && *qc && end && rl_line_buffer[rl_point] == *qc && replacement[rlen - 1] == *qc) + end++; if (_rl_skip_completed_text) { r = replacement; @@ -1925,7 +1930,8 @@ rl_completion_matches (text, entry_function) match_list[++matches] = string; match_list[matches + 1] = (char *)NULL; } - _rl_interrupt_immediately--; + if (_rl_interrupt_immediately) + _rl_interrupt_immediately--; /* If there were any matches, then look through them finding out the lowest common denominator. That then becomes match_list[0]. */ diff --git a/lib/readline/signals.c b/lib/readline/signals.c index 11c92d2c2..4fbc019e6 100644 --- a/lib/readline/signals.c +++ b/lib/readline/signals.c @@ -142,13 +142,14 @@ static RETSIGTYPE rl_signal_handler (sig) int sig; { - if (_rl_interrupt_immediately) + if (_rl_interrupt_immediately || RL_ISSTATE(RL_STATE_CALLBACK)) { _rl_interrupt_immediately = 0; _rl_handle_signal (sig); } + else + _rl_caught_signal = sig; - _rl_caught_signal = sig; SIGHANDLER_RETURN; } diff --git a/lib/readline/signals.c~ b/lib/readline/signals.c~ index 325ae8cce..71bd2fd6f 100644 --- a/lib/readline/signals.c~ +++ b/lib/readline/signals.c~ @@ -101,7 +101,8 @@ int rl_catch_sigwinch = 0; /* for the readline state struct in readline.c */ int _rl_interrupt_immediately = 0; int volatile _rl_caught_signal = 0; /* should be sig_atomic_t, but that requires including everywhere */ -/* If non-zero, print characters corresponding to received signals. */ +/* If non-zero, print characters corresponding to received signals as long as + the user has indicated his desire to do so (_rl_echo_control_chars). */ int _rl_echoctl = 0; int _rl_intr_char = 0; @@ -146,8 +147,9 @@ rl_signal_handler (sig) _rl_interrupt_immediately = 0; _rl_handle_signal (sig); } + else + _rl_caught_signal = sig; - _rl_caught_signal = sig; SIGHANDLER_RETURN; } @@ -518,13 +520,16 @@ rl_free_line_state () #if defined (HAVE_POSIX_SIGNALS) static sigset_t sigint_set, sigint_oset; +static sigset_t sigwinch_set, sigwinch_oset; #else /* !HAVE_POSIX_SIGNALS */ # if defined (HAVE_BSD_SIGNALS) static int sigint_oldmask; +static int sigwinch_oldmask; # endif /* HAVE_BSD_SIGNALS */ #endif /* !HAVE_POSIX_SIGNALS */ static int sigint_blocked; +static int sigwinch_blocked; /* Cause SIGINT to not be delivered until the corresponding call to release_sigint(). */ @@ -574,6 +579,54 @@ _rl_release_sigint () sigint_blocked = 0; } +/* Cause SIGWINCH to not be delivered until the corresponding call to + release_sigwinch(). */ +void +_rl_block_sigwinch () +{ + if (sigwinch_blocked) + return; + +#if defined (HAVE_POSIX_SIGNALS) + sigemptyset (&sigwinch_set); + sigemptyset (&sigwinch_oset); + sigaddset (&sigwinch_set, SIGWINCH); + sigprocmask (SIG_BLOCK, &sigwinch_set, &sigwinch_oset); +#else /* !HAVE_POSIX_SIGNALS */ +# if defined (HAVE_BSD_SIGNALS) + sigwinch_oldmask = sigblock (sigmask (SIGWINCH)); +# else /* !HAVE_BSD_SIGNALS */ +# if defined (HAVE_USG_SIGHOLD) + sighold (SIGWINCH); +# endif /* HAVE_USG_SIGHOLD */ +# endif /* !HAVE_BSD_SIGNALS */ +#endif /* !HAVE_POSIX_SIGNALS */ + + sigwinch_blocked = 1; +} + +/* Allow SIGWINCH to be delivered. */ +void +_rl_release_sigwinch () +{ + if (sigwinch_blocked == 0) + return; + +#if defined (HAVE_POSIX_SIGNALS) + sigprocmask (SIG_SETMASK, &sigwinch_oset, (sigset_t *)NULL); +#else +# if defined (HAVE_BSD_SIGNALS) + sigsetmask (sigwinch_oldmask); +# else /* !HAVE_BSD_SIGNALS */ +# if defined (HAVE_USG_SIGHOLD) + sigrelse (SIGWINCH); +# endif /* HAVE_USG_SIGHOLD */ +# endif /* !HAVE_BSD_SIGNALS */ +#endif /* !HAVE_POSIX_SIGNALS */ + + sigwinch_blocked = 0; +} + /* **************************************************************** */ /* */ /* Echoing special control characters */ @@ -586,14 +639,18 @@ rl_echo_signal_char (sig) char cstr[3]; int cslen, c; - if (_rl_echoctl == 0) + if (_rl_echoctl == 0 || _rl_echo_control_chars == 0) return; switch (sig) { case SIGINT: c = _rl_intr_char; break; +#if defined (SIGQUIT) case SIGQUIT: c = _rl_quit_char; break; +#endif +#if defined (SIGTSTP) case SIGTSTP: c = _rl_susp_char; break; +#endif default: return; } diff --git a/lib/readline/util.c b/lib/readline/util.c index a07cb1043..6bb64c296 100644 --- a/lib/readline/util.c +++ b/lib/readline/util.c @@ -81,8 +81,7 @@ rl_alphabetic (c) #if defined (HANDLE_MULTIBYTE) int -_rl_walphabetic (wc) - wchar_t wc; +_rl_walphabetic (wchar_t wc) { int c; diff --git a/lib/readline/util.c~ b/lib/readline/util.c~ index 991af24f7..a07cb1043 100644 --- a/lib/readline/util.c~ +++ b/lib/readline/util.c~ @@ -121,7 +121,7 @@ rl_abort (count, key) } int -_rl_null_func (count, key) +_rl_null_function (count, key) int count, key; { return 0; diff --git a/subst.c b/subst.c index 8bccf9392..6072413b6 100644 --- a/subst.c +++ b/subst.c @@ -152,8 +152,8 @@ WORD_LIST *subst_assign_varlist = (WORD_LIST *)NULL; /* Extern functions and variables from different files. */ extern int last_command_exit_value, last_command_exit_signal; -extern int subshell_environment; -extern int subshell_level, parse_and_execute_level; +extern int subshell_environment, line_number; +extern int subshell_level, parse_and_execute_level, sourcelevel; extern int eof_encountered; extern int return_catch_flag, return_catch_value; extern pid_t dollar_dollar_pid; @@ -5043,7 +5043,7 @@ command_substitute (string, quoted) maybe_make_export_env (); /* XXX */ /* Flags to pass to parse_and_execute() */ - pflags = interactive ? SEVAL_RESETLINE : 0; + pflags = (interactive && sourcelevel == 0) ? SEVAL_RESETLINE : 0; /* Pipe the output of executing STRING into the current shell. */ if (pipe (fildes) < 0) diff --git a/subst.c~ b/subst.c~ index 550902877..6c3bc7858 100644 --- a/subst.c~ +++ b/subst.c~ @@ -152,8 +152,8 @@ WORD_LIST *subst_assign_varlist = (WORD_LIST *)NULL; /* Extern functions and variables from different files. */ extern int last_command_exit_value, last_command_exit_signal; -extern int subshell_environment; -extern int subshell_level, parse_and_execute_level; +extern int subshell_environment, line_number; +extern int subshell_level, parse_and_execute_level, sourcelevel; extern int eof_encountered; extern int return_catch_flag, return_catch_value; extern pid_t dollar_dollar_pid; @@ -5042,8 +5042,9 @@ command_substitute (string, quoted) if (subst_assign_varlist == 0 || garglist == 0) maybe_make_export_env (); /* XXX */ +itrace("command_substitute: line_number = %d sourcelevel = %d", line_number, sourcelevel); /* Flags to pass to parse_and_execute() */ - pflags = interactive ? SEVAL_RESETLINE : 0; + pflags = (interactive && sourcelevel == 0) ? SEVAL_RESETLINE : 0; /* Pipe the output of executing STRING into the current shell. */ if (pipe (fildes) < 0) @@ -7283,7 +7284,7 @@ param_expand (string, sindex, quoted, expanded_something, if (contains_dollar_at) *contains_dollar_at = 1; -#if 1 +#if 0 if (pflags & PF_NOSPLIT2) temp = string_list_internal (quoted ? quote_list (list) : list, " "); else @@ -7981,7 +7982,7 @@ add_twochars: { if (list->next) { -#if 1 +#if 0 if (quoted_dollar_at && word->flags & W_NOSPLIT2) temp = string_list_internal (quote_list (list), " "); else diff --git a/tests/RUN-ONE-TEST b/tests/RUN-ONE-TEST index 3efcf32d6..72ec06a2c 100755 --- a/tests/RUN-ONE-TEST +++ b/tests/RUN-ONE-TEST @@ -1,4 +1,4 @@ -BUILD_DIR=/usr/local/build/chet/bash/bash-current +BUILD_DIR=/usr/local/build/bash/bash-current THIS_SH=$BUILD_DIR/bash PATH=$PATH:$BUILD_DIR diff --git a/tests/exec.right b/tests/exec.right index 2146d4720..86a099c20 100644 --- a/tests/exec.right +++ b/tests/exec.right @@ -26,7 +26,7 @@ this is bashenv 127 ./execscript: line 73: notthere: No such file or directory 127 -./execscript: line 76: notthere: No such file or directory +./execscript: line 76: notthere: command not found 127 this is sh this is sh -- 2.47.2