From: Chet Ramey Date: Tue, 5 Feb 2013 21:44:34 +0000 (-0500) Subject: commit bash-20130125 snapshot X-Git-Tag: bash-4.3-alpha~16 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1a81420a36fafc5217e770e042fd39a1353a41f9;p=thirdparty%2Fbash.git commit bash-20130125 snapshot --- diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 2ac232e4d..cd35ad3df 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -4203,6 +4203,9 @@ execute_cmd.c declaration builtin subst.c + - do_assignment_internal: explicitly handle case where we are + executing in a function and we want to create a global array or + assoc variable - shell_expand_word_list: call make_internal_declare if -a option given to declaration builtin (W_ASSIGNARRAY); handle -g option with it (W_ASSNGLOBAL). Fixes inconsistency noticed by Vicente Couce @@ -4379,3 +4382,71 @@ command.h {execute_cmd,subst,variables}.c - removed all code that mentioned W_GLOBEXP - removed mention of gnu_argv_flags and code that set it + + 1/22 + ---- +subst.c + - param_expand: set W_SPLITSPACE if we expand (unquoted) $* and + IFS is unset or null so we can be sure to split this on spaces + no matter what happens with IFS later + - expand_word_internal: note that param_expand returns W_SPLITSPACE + in the returned word flags and keep track of that state with + `split_on_spaces' + + 1/23 + ---- +subst.c + - expand_word_internal: if split_on_spaces is non-zero, make sure + we split `istring' on spaces and return the resultant word. The + previous expansions should have quoted spaces in the positional + parameters where necessary. Suggested by Dan Douglas + + +execute_cmd.c + - execute_command_internal: make sure any subshell forked to run a + group command or user subshell at the end of a pipeline runs any + EXIT trap it sets. Fixes debian bash bug 698411 + http://bugs.debian.org/cgi-big/bugreport.cgi?bug=698411 + +subst.c + - shell_expand_word_list: fix code that creates args for and calls + make_internal_declare to avoid calling it twice (missing `else' + in 12/26 change) + - do_assignment_internal: fix code from 12/26 change to fix problem + where an existing assoc variable could be converted to an array + without checking `mkassoc' + + 1/24 + ---- +builtins/evalfile.c + - _evalfile: add missing `close (fd)' calls before returning to + avoid fd leaks. Bug and fix from Roman Rakus + + 1/25 + ---- +builtins/read.def + - read_builtin: don't try to play tricks with the top of the unwind- + protect stack after read gets a SIGALRM; save input_string to new + memory, run the stack, then restore input_string and assign the + variables. Part of fix for bug reported by konsolebox + ; the rest of the fix is with the changes in + trap and signal handling and doing away with interrupt_immediately + + 1/26 + ---- +redir.c + - redirection_expand, write_here_string, write_here_document: before + calling any of the word expansion functions, after setting + expanding_redir to 1 (which bypasses the temp environment in the + variable lookup functions), call sv_ifs to reset the cached IFS- + related variables set by subst.c:setifs(). This ensures that + redirections will not get any IFS values that are set in the + temporary environment, as Posix specifies. Then, after the word + expansions, after resetting expanding_redir to 0, call sv_ifs + again to make sure the cached IFS values are set from any + assignments in the temporary environment. We force executing_builtin + to 1 to `fool' the variable lookup functions into using any temp + environment, then reset it to its old value after sv_ifs returns. + This is what allows read() to use the (cached) IFS variables set + in the temp environment. Fixes inconsistency reported by Dan Douglas + diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~ index 726864b9d..7b2010f77 100644 --- a/CWRU/CWRU.chlog~ +++ b/CWRU/CWRU.chlog~ @@ -4203,6 +4203,9 @@ execute_cmd.c declaration builtin subst.c + - do_assignment_internal: explicitly handle case where we are + executing in a function and we want to create a global array or + assoc variable - shell_expand_word_list: call make_internal_declare if -a option given to declaration builtin (W_ASSIGNARRAY); handle -g option with it (W_ASSNGLOBAL). Fixes inconsistency noticed by Vicente Couce @@ -4372,9 +4375,59 @@ subst.c Suggested by Dan Douglas [TENTATIVE, needs work on IFS side effects] -command.h,subst.c +command.h - W_GLOBEXP (which was unused) is now W_SPLITSPACE (which isn't used - yet), removed all code that mentioned W_GLOBEXP + yet) {execute_cmd,subst,variables}.c - - removed mention of gnu_argv_flags + - removed all code that mentioned W_GLOBEXP + - removed mention of gnu_argv_flags and code that set it + + 1/22 + ---- +subst.c + - param_expand: set W_SPLITSPACE if we expand (unquoted) $* and + IFS is unset or null so we can be sure to split this on spaces + no matter what happens with IFS later + - expand_word_internal: note that param_expand returns W_SPLITSPACE + in the returned word flags and keep track of that state with + `split_on_spaces' + + 1/23 + ---- +subst.c + - expand_word_internal: if split_on_spaces is non-zero, make sure + we split `istring' on spaces and return the resultant word. The + previous expansions should have quoted spaces in the positional + parameters where necessary. Suggested by Dan Douglas + + +execute_cmd.c + - execute_command_internal: make sure any subshell forked to run a + group command or user subshell at the end of a pipeline runs any + EXIT trap it sets. Fixes debian bash bug 698411 + http://bugs.debian.org/cgi-big/bugreport.cgi?bug=698411 + +subst.c + - shell_expand_word_list: fix code that creates args for and calls + make_internal_declare to avoid calling it twice (missing `else' + in 12/26 change) + - do_assignment_internal: fix code from 12/26 change to fix problem + where an existing assoc variable could be converted to an array + without checking `mkassoc' + + 1/24 + ---- +builtins/evalfile.c + - _evalfile: add missing `close (fd)' calls before returning to + avoid fd leaks. Bug and fix from Roman Rakus + + 1/25 + ---- +builtins/read.def + - read_builtin: don't try to play tricks with the top of the unwind- + protect stack after read gets a SIGALRM; save input_string to new + memory, run the stack, then restore input_string and assign the + variables. Part of fix for bug reported by konsolebox + ; the rest of the fix is with the changes in + trap and signal handling and doing away with interrupt_immediately diff --git a/MANIFEST b/MANIFEST index a250b87ff..8db33895e 100644 --- a/MANIFEST +++ b/MANIFEST @@ -867,6 +867,7 @@ tests/dollar-star3.sub f tests/dollar-star4.sub f tests/dollar-star5.sub f tests/dollar-star6.sub f +tests/dollar-star7.sub f tests/dollar.right f tests/dstack.tests f tests/dstack.right f @@ -1156,6 +1157,7 @@ tests/trap1.sub f 755 tests/trap2.sub f 755 tests/trap2a.sub f 755 tests/trap3.sub f +tests/trap4.sub f tests/type.tests f tests/type.right f tests/type1.sub f @@ -1170,6 +1172,7 @@ tests/varenv1.sub f tests/varenv2.sub f tests/varenv3.sub f tests/varenv4.sub f +tests/varenv5.sub f tests/version f tests/version.mini f tests/vredir.tests f diff --git a/builtins/evalfile.c b/builtins/evalfile.c index 60f89d149..a59ce597f 100644 --- a/builtins/evalfile.c +++ b/builtins/evalfile.c @@ -114,6 +114,11 @@ _evalfile (filename, flags) if (fd < 0 || (fstat (fd, &finfo) == -1)) { + i = errno; + if (fd >= 0) + close (fd); + errno = i; + file_error_and_exit: if (((flags & FEVAL_ENOENTOK) == 0) || errno != ENOENT) file_error (filename); @@ -133,11 +138,13 @@ file_error_and_exit: if (S_ISDIR (finfo.st_mode)) { (*errfunc) (_("%s: is a directory"), filename); + close (fd); return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1); } else if ((flags & FEVAL_REGFILE) && S_ISREG (finfo.st_mode) == 0) { (*errfunc) (_("%s: not a regular file"), filename); + close (fd); return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1); } @@ -146,6 +153,7 @@ file_error_and_exit: if (file_size != finfo.st_size || file_size + 1 < file_size) { (*errfunc) (_("%s: file is too large"), filename); + close (fd); return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1); } diff --git a/builtins/read.def b/builtins/read.def index 30637fbb8..ea2667bb7 100644 --- a/builtins/read.def +++ b/builtins/read.def @@ -410,12 +410,20 @@ read_builtin (list) sigalrm_seen = 0; /* Tricky. The top of the unwind-protect stack is the free of input_string. We want to run all the rest and use input_string, - so we have to remove it from the stack. */ + so we have to save input_string temporarily, run the unwind- + protects, then restore input_string so we can use it later */ orig_input_string = 0; + input_string[i] = '\0'; /* make sure it's terminated */ + if (i == 0) + { + t = (char *)xmalloc (1); + t[0] = 0; + } + else + t = savestring (input_string); - remove_unwind_protect (); run_unwind_frame ("read_builtin"); - input_string[i] = '\0'; /* make sure it's terminated */ + input_string = t; retval = 128+SIGALRM; goto assign_vars; } diff --git a/execute_cmd.c b/execute_cmd.c index 8b405334f..0ff8a9e19 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -608,6 +608,8 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, COMMAND struct. Need to keep in mind that execute_in_subshell runs the exit trap for () subshells itself. */ s = user_subshell == 0 && command->type == cm_group && pipe_in == NO_PIPE && pipe_out == NO_PIPE && asynchronous; + /* run exit trap for : | { ...; } and : | ( ... ) */ + s += user_subshell == 0 && command->type == cm_group && pipe_in != NO_PIPE && pipe_out == NO_PIPE && asynchronous == 0; last_command_exit_value = execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close); if (s) diff --git a/jobs.c b/jobs.c index ad9b5ae82..9227638c3 100644 --- a/jobs.c +++ b/jobs.c @@ -3176,6 +3176,7 @@ waitchld (wpid, block) WAIT status; PROCESS *child; pid_t pid; + int call_set_current, last_stopped_job, job, children_exited, waitpid_flags; static int wcontinued = WCONTINUED; /* run-time fix for glibc problem */ @@ -3191,9 +3192,9 @@ waitchld (wpid, block) : 0; if (sigchld || block == 0) waitpid_flags |= WNOHANG; + /* Check for terminating signals and exit the shell if we receive one */ CHECK_TERMSIG; - /* Check for a trapped signal interrupting the wait builtin and jump out */ CHECK_WAIT_INTR; @@ -4236,8 +4237,10 @@ mark_dead_jobs_as_notified (force) } #ifdef DEBUG +# if 0 if (ndeadproc != js.c_reaped) itrace("mark_dead_jobs_as_notified: ndeadproc (%d) != js.c_reaped (%d)", ndeadproc, js.c_reaped); +# endif if (ndead != js.j_ndead) itrace("mark_dead_jobs_as_notified: ndead (%d) != js.j_ndead (%d)", ndead, js.j_ndead); #endif diff --git a/lib/sh/zread.c b/lib/sh/zread.c index 832a43c79..02a20058c 100644 --- a/lib/sh/zread.c +++ b/lib/sh/zread.c @@ -49,7 +49,7 @@ zread (fd, buf, len) ssize_t r; while ((r = read (fd, buf, len)) < 0 && errno == EINTR) - check_signals_and_traps (); /* XXX */ + check_signals_and_traps (); /* XXX - should it be check_signals()? */ return r; } diff --git a/redir.c b/redir.c index 559da1122..d7da2f3cf 100644 --- a/redir.c +++ b/redir.c @@ -63,6 +63,7 @@ int expanding_redir; extern int posixly_correct; extern int last_command_exit_value; +extern int executing_builtin; extern REDIRECT *redirection_undo_list; extern REDIRECT *exec_redirection_undo_list; @@ -275,6 +276,7 @@ redirection_expand (word) char *result; WORD_LIST *tlist1, *tlist2; WORD_DESC *w; + int old; w = copy_word (word); if (posixly_correct) @@ -282,11 +284,22 @@ redirection_expand (word) tlist1 = make_word_list (w, (WORD_LIST *)NULL); expanding_redir = 1; + /* Now that we've changed the variable search order to ignore the temp + environment, see if we need to change the cached IFS values. */ + sv_ifs ("IFS"); tlist2 = expand_words_no_vars (tlist1); expanding_redir = 0; + /* Now we need to change the variable search order back to include the temp + environment. We force the temp environment search by forcing + executing_builtin to 1. This is what makes `read' get the right values + for the IFS-related cached variables, for example. */ + old = executing_builtin; + executing_builtin = 1; + sv_ifs ("IFS"); + executing_builtin = old; dispose_words (tlist1); - if (!tlist2 || tlist2->next) + if (tlist2 == 0 || tlist2->next) { /* We expanded to no words, or to more than a single word. Dispose of the word list and return NULL. */ @@ -305,11 +318,23 @@ write_here_string (fd, redirectee) WORD_DESC *redirectee; { char *herestr; - int herelen, n, e; + int herelen, n, e, old; expanding_redir = 1; + /* Now that we've changed the variable search order to ignore the temp + environment, see if we need to change the cached IFS values. */ + sv_ifs ("IFS"); herestr = expand_string_to_string (redirectee->word, 0); expanding_redir = 0; + /* Now we need to change the variable search order back to include the temp + environment. We force the temp environment search by forcing + executing_builtin to 1. This is what makes `read' get the right values + for the IFS-related cached variables, for example. */ + old = executing_builtin; + executing_builtin = 1; + sv_ifs ("IFS"); + executing_builtin = old; + herelen = STRLEN (herestr); n = write (fd, herestr, herelen); @@ -338,7 +363,7 @@ write_here_document (fd, redirectee) WORD_DESC *redirectee; { char *document; - int document_len, fd2; + int document_len, fd2, old; FILE *fp; register WORD_LIST *t, *tlist; @@ -362,8 +387,19 @@ write_here_document (fd, redirectee) } expanding_redir = 1; + /* Now that we've changed the variable search order to ignore the temp + environment, see if we need to change the cached IFS values. */ + sv_ifs ("IFS"); tlist = expand_string (redirectee->word, Q_HERE_DOCUMENT); expanding_redir = 0; + /* Now we need to change the variable search order back to include the temp + environment. We force the temp environment search by forcing + executing_builtin to 1. This is what makes `read' get the right values + for the IFS-related cached variables, for example. */ + old = executing_builtin; + executing_builtin = 1; + sv_ifs ("IFS"); + executing_builtin = old; if (tlist) { diff --git a/redir.c~ b/redir.c~ index e7a0c0383..65d31f3dd 100644 --- a/redir.c~ +++ b/redir.c~ @@ -63,6 +63,7 @@ int expanding_redir; extern int posixly_correct; extern int last_command_exit_value; +extern int executing_builtin; extern REDIRECT *redirection_undo_list; extern REDIRECT *exec_redirection_undo_list; @@ -156,14 +157,12 @@ redirection_error (temp, error) else if (expandable_redirection_filename (temp)) { expandable_filename: + oflags = temp->redirectee.filename->flags; if (posixly_correct && interactive_shell == 0) - { - oflags = temp->redirectee.filename->flags; - temp->redirectee.filename->flags |= W_NOGLOB; - } + temp->redirectee.filename->flags |= W_NOGLOB; + temp->redirectee.filename->flags |= W_NOCOMSUB; filename = allocname = redirection_expand (temp->redirectee.filename); - if (posixly_correct && interactive_shell == 0) - temp->redirectee.filename->flags = oflags; + temp->redirectee.filename->flags = oflags; if (filename == 0) filename = temp->redirectee.filename->word; } @@ -277,6 +276,7 @@ redirection_expand (word) char *result; WORD_LIST *tlist1, *tlist2; WORD_DESC *w; + int old; w = copy_word (word); if (posixly_correct) @@ -284,8 +284,19 @@ redirection_expand (word) tlist1 = make_word_list (w, (WORD_LIST *)NULL); expanding_redir = 1; + /* Now that we've changed the variable search order to ignore the temp + environment, see if we need to change the cached IFS values. */ + sv_ifs ("IFS"); tlist2 = expand_words_no_vars (tlist1); expanding_redir = 0; + /* Now we need to change the variable search order back to include the temp + environment. We force the temp environment search by forcing + executing_builtin to 1. This is what makes `read' get the right values + for the IFS-related cached variables, for example. */ + old = executing_builtin; + executing_builtin = 1; + sv_ifs ("IFS"); + executing_builtin = old; dispose_words (tlist1); if (!tlist2 || tlist2->next) @@ -307,11 +318,23 @@ write_here_string (fd, redirectee) WORD_DESC *redirectee; { char *herestr; - int herelen, n, e; + int herelen, n, e, old; expanding_redir = 1; + /* Now that we've changed the variable search order to ignore the temp + environment, see if we need to change the cached IFS values. */ + sv_ifs ("IFS"); herestr = expand_string_to_string (redirectee->word, 0); expanding_redir = 0; + /* Now we need to change the variable search order back to include the temp + environment. We force the temp environment search by forcing + executing_builtin to 1. This is what makes `read' get the right values + for the IFS-related cached variables, for example. */ + old = executing_builtin; + executing_builtin = 1; + sv_ifs ("IFS"); + executing_builtin = old; + herelen = STRLEN (herestr); n = write (fd, herestr, herelen); @@ -340,7 +363,7 @@ write_here_document (fd, redirectee) WORD_DESC *redirectee; { char *document; - int document_len, fd2; + int document_len, fd2, old; FILE *fp; register WORD_LIST *t, *tlist; @@ -364,8 +387,19 @@ write_here_document (fd, redirectee) } expanding_redir = 1; + /* Now that we've changed the variable search order to ignore the temp + environment, see if we need to change the cached IFS values. */ + sv_ifs ("IFS"); tlist = expand_string (redirectee->word, Q_HERE_DOCUMENT); expanding_redir = 0; + /* Now we need to change the variable search order back to include the temp + environment. We force the temp environment search by forcing + executing_builtin to 1. This is what makes `read' get the right values + for the IFS-related cached variables, for example. */ + old = executing_builtin; + executing_builtin = 1; + sv_ifs ("IFS"); + executing_builtin = old; if (tlist) { diff --git a/subst.c b/subst.c index d3595b75a..5f3770223 100644 --- a/subst.c +++ b/subst.c @@ -2729,7 +2729,7 @@ do_compound_assignment (name, value, flags) v = convert_var_to_assoc (v); else if (v == 0) v = make_new_array_variable (name); - else if (v && array_p (v) == 0) + else if (v && mkassoc == 0 && array_p (v) == 0) v = convert_var_to_array (v); assign_compound_array_list (v, list, flags); } @@ -7630,11 +7630,8 @@ param_expand (string, sindex, quoted, expanded_something, else { temp = string_list_dollar_at (list, quoted); - if (ifs_is_set == 0 || ifs_is_null) -{ -itrace("param_expand: set W_SPLITSPACE flag"); + if (quoted == 0 && (ifs_is_set == 0 || ifs_is_null)) tflag |= W_SPLITSPACE; -} } if (expand_no_split_dollar_star == 0 && contains_dollar_at) @@ -8214,10 +8211,7 @@ add_string: &temp_has_dollar_at, "ed_dollar_at, &had_quoted_null, pflags); has_dollar_at += temp_has_dollar_at; - split_on_spaces += (tword->flags & W_SPLITSPACE); -if (tword->flags & W_SPLITSPACE) - itrace("expand_word_internal: param_expand return word has W_SPLITSPACE"); if (tword == &expand_wdesc_error || tword == &expand_wdesc_fatal) { @@ -8660,7 +8654,6 @@ finished_with_string: { char *ifs_chars; -itrace("expand_word_internal: splitting `%s': split_on_spaces = %d", istring, split_on_spaces); ifs_chars = (quoted_dollar_at || has_dollar_at) ? ifs_value : (char *)NULL; /* If we have $@, we need to split the results no matter what. If @@ -8668,8 +8661,13 @@ itrace("expand_word_internal: splitting `%s': split_on_spaces = %d", istring, sp positional parameters with a space, so we split on space (we have set ifs_chars to " \t\n" above if ifs is unset). If IFS is set, string_list_dollar_at has separated the positional parameters - with the first character of $IFS, so we split on $IFS. */ - if (has_dollar_at && ifs_chars) + with the first character of $IFS, so we split on $IFS. If + SPLIT_ON_SPACES is set, we expanded $* (unquoted) with IFS either + unset or null, and we want to make sure that we split on spaces + regardless of what else has happened to IFS since the expansion. */ + if (split_on_spaces) + list = list_string (istring, " ", 1); /* XXX quoted == 1? */ + else if (has_dollar_at && ifs_chars) list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1); else { @@ -9328,7 +9326,7 @@ shell_expand_word_list (tlist, eflags) make_internal_declare (tlist->word->word, "-gA"); else if (tlist->word->flags & W_ASSIGNASSOC) make_internal_declare (tlist->word->word, "-A"); - if ((tlist->word->flags & (W_ASSIGNARRAY|W_ASSNGLOBAL)) == (W_ASSIGNARRAY|W_ASSNGLOBAL)) + else if ((tlist->word->flags & (W_ASSIGNARRAY|W_ASSNGLOBAL)) == (W_ASSIGNARRAY|W_ASSNGLOBAL)) make_internal_declare (tlist->word->word, "-ga"); else if (tlist->word->flags & W_ASSIGNARRAY) make_internal_declare (tlist->word->word, "-a"); diff --git a/tests/dollar-at-star b/tests/dollar-at-star index bf95fec18..f9b9c7019 100755 --- a/tests/dollar-at-star +++ b/tests/dollar-at-star @@ -245,4 +245,8 @@ ${THIS_SH} ./dollar-at5.sub # tests for expansions of $* when $1 == ""; problem through bash-4.2 ${THIS_SH} ./dollar-star6.sub +# tests for expansions of $* (unquoted) when IFS changes (e.g., ${IFS:=-}) +# problem through bash-4.2 +${THIS_SH} ./dollar-star7.sub + exit 0 diff --git a/tests/dollar-star7.sub b/tests/dollar-star7.sub new file mode 100644 index 000000000..72d6c24f5 --- /dev/null +++ b/tests/dollar-star7.sub @@ -0,0 +1,30 @@ +# if IFS side effects in ${IFS=} assignments take place, how do you cope with +# later changes to IFS in the same set of expansions? You've already +# committed to using the first character of the (old) IFS to expand $* in +# the previous expansions, and changing it to not include ' ', for instance, +# results in the first couple of ${*} below not being split at all + +set -f -- a b c + +unset -v IFS +printf '<%s> ' ${*}${IFS=}${*}${IFS:=-}"${*}" +echo +printf "after 1: IFS " +echo "${IFS-unset}" +recho "$*" + +set -f -- a 'b c' d +unset -v IFS +printf '<%s> ' ${*}${IFS=}${*}${IFS:=-}"${*}" +echo +printf "after 2: IFS " +echo "${IFS-unset}" +recho "$*" + +unset -v IFS +recho $* +recho "$*" + +IFS=' ' +recho $* +recho "$*" diff --git a/tests/dollar.right b/tests/dollar.right index 2e5207cb0..ae0ff03c2 100644 --- a/tests/dollar.right +++ b/tests/dollar.right @@ -237,3 +237,19 @@ argv[1] = argv[1] = argv[1] = argv[1] = + +after 1: IFS - +argv[1] = + +after 2: IFS - +argv[1] = +argv[1] = +argv[2] = +argv[3] = +argv[4] = +argv[1] = +argv[1] = +argv[2] = +argv[3] = +argv[4] = +argv[1] = diff --git a/tests/exp.right b/tests/exp.right index 5ece7d39e..c027036ed 100644 --- a/tests/exp.right +++ b/tests/exp.right @@ -189,3 +189,19 @@ argv[1] = argv[1] = argv[1] = argv[1] = +argv[1] = +argv[2] = <> +argv[1] = +argv[2] = <> +argv[1] = +argv[2] = <> +argv[1] = +argv[2] = <> +argv[1] = +argv[2] = +argv[1] = +argv[2] = +argv[1] = +argv[2] = +argv[1] = +argv[2] = diff --git a/tests/exp6.sub b/tests/exp6.sub index d542f3b42..a1c9fe635 100644 --- a/tests/exp6.sub +++ b/tests/exp6.sub @@ -14,3 +14,17 @@ recho """"c"""""" recho """"""""c recho c"""""""" + +# BASH BUG: spurious DEL characters appear on empty variable interpolation. +# BASH 4.2.8(1)-release + +a='' + +recho correct "$a" # correct empty output line +recho correct "$a""$a" # correct empty output line +recho correct "$a""$a""$a" # correct empty output line +recho XwrongX "$a""$a""$a""$a" # spurious two DEL chars appear at line end +recho correct a"$a" # correct single "a" on line +recho XwrongX a"$a""$a" # spurious DEL char appears at line end +recho correct a"$a$a" # correct single "a" on line +recho correct a"$a$a$a$a" # correct single "a" on line diff --git a/tests/trap.right b/tests/trap.right index d1879a42a..c04d17260 100644 --- a/tests/trap.right +++ b/tests/trap.right @@ -75,6 +75,16 @@ command substitution trap: 8 +[9] echo 4 4 +exit subshell 1 +current shell +exit subshell 2 +current shell +current shell +current shell +outside 1 +outside 2 +outside 3 +outside 4 caught a child death caught a child death caught a child death diff --git a/tests/trap.tests b/tests/trap.tests index e9e10cc1c..e9859ec8f 100644 --- a/tests/trap.tests +++ b/tests/trap.tests @@ -68,6 +68,8 @@ trap '' USR2 ${THIS_SH} ./trap3.sub +${THIS_SH} ./trap4.sub + # # show that setting a trap on SIGCHLD is not disastrous. # diff --git a/tests/trap4.sub b/tests/trap4.sub new file mode 100644 index 000000000..6a8abdac2 --- /dev/null +++ b/tests/trap4.sub @@ -0,0 +1,17 @@ +# make sure subshells at the end of pipelines run any exit traps they set + +: | { trap 'echo exit subshell 1' EXIT; exit; }; echo current shell + +: | { trap 'echo exit subshell 2' EXIT; exit; }; echo current shell + +: | { trap 'echo exit subshell 3' EXIT; exit; } | : ; echo current shell + +: | { trap 'echo exit subshell 4' EXIT; exit; } | : ; echo current shell + +trap 'echo inherited exit trap' EXIT +: | { exit; } ; echo outside 1 +: | ( exit; ) ; echo outside 2 +: | { exit; } | : ; echo outside 3 +: | ( exit; ) | : ; echo outside 4 + +trap - EXIT diff --git a/tests/varenv.right b/tests/varenv.right index 2431d70fc..a15b3be67 100644 --- a/tests/varenv.right +++ b/tests/varenv.right @@ -60,6 +60,10 @@ FIN: asdf fdsa, asdf fdsa g: v = , w = f: v = , w = FIN: v = two, w = one +declare -Ar FOOBAR='([foo]="bar" )' +declare -Ar FOOBAR='([foo]="bar" )' +declare -ar FOOBAR2='([0]="bar")' +declare -ar FOOBAR2='([0]="bar")' a=z a=b a=z diff --git a/tests/varenv.sh b/tests/varenv.sh index b4d2a08ea..6db6f65da 100644 --- a/tests/varenv.sh +++ b/tests/varenv.sh @@ -208,5 +208,8 @@ $THIS_SH ./varenv3.sub # scoping problems with declare -g through bash-4.2 ${THIS_SH} ./varenv4.sub +# more scoping and declaration problems with -g and arrays through bash-4.2 +${THIS_SH} ./varenv5.sub + # make sure variable scoping is done right tt() { typeset a=b;echo a=$a; };a=z;echo a=$a;tt;echo a=$a diff --git a/tests/varenv5.sub b/tests/varenv5.sub new file mode 100644 index 000000000..8ebfa36dd --- /dev/null +++ b/tests/varenv5.sub @@ -0,0 +1,16 @@ +function foobar { + declare -rgA FOOBAR=([foo]=bar) + declare -p FOOBAR +} +foobar +declare -p FOOBAR + +unset -f foobar + +foobar() { + declare -rga FOOBAR2=([foo]=bar) + declare -p FOOBAR2 +} + +foobar +declare -p FOOBAR2 diff --git a/trap.c b/trap.c index f3254b18c..d60a7fb45 100644 --- a/trap.c +++ b/trap.c @@ -456,6 +456,7 @@ any_signals_trapped () return -1; } +/* Convenience functions the rest of the shell can use */ void check_signals_and_traps () { @@ -463,6 +464,12 @@ check_signals_and_traps () run_pending_traps (); } +void +check_signals () +{ + QUIT; +} + #if defined (JOB_CONTROL) && defined (SIGCHLD) #ifdef INCLUDE_UNUSED diff --git a/variables.c b/variables.c index 439e8db7d..b46eaeb1f 100644 --- a/variables.c +++ b/variables.c @@ -61,6 +61,7 @@ #include "builtins/getopt.h" #include "builtins/common.h" +#include "builtins/builtext.h" #if defined (READLINE) # include "bashline.h" @@ -1788,6 +1789,7 @@ find_variable_internal (name, force_tempenv) { SHELL_VAR *var; int search_tempenv; + VAR_CONTEXT *vc; var = (SHELL_VAR *)NULL; @@ -1801,8 +1803,22 @@ find_variable_internal (name, force_tempenv) if (search_tempenv && temporary_env) var = hash_lookup (name, temporary_env); + vc = shell_variables; +#if 0 +if (search_tempenv == 0 && /* (subshell_environment & SUBSHELL_COMSUB) && */ + expanding_redir && + (this_shell_builtin == eval_builtin || this_shell_builtin == command_builtin)) + { + itrace("find_variable_internal: search_tempenv == 0: skipping VC_BLTNENV"); + while (vc && (vc->flags & VC_BLTNENV)) + vc = vc->down; + if (vc == 0) + vc = shell_variables; + } +#endif + if (var == 0) - var = var_lookup (name, shell_variables); + var = var_lookup (name, vc); if (var == 0) return ((SHELL_VAR *)NULL); @@ -2868,11 +2884,6 @@ assign_in_env (word, flags) array_needs_making = 1; -#if 0 - if (ifsname (name)) - setifs (var); -else -#endif if (flags) stupidly_hack_special_variables (name); diff --git a/variables.c~ b/variables.c~ index b6d1ea453..1f05f005e 100644 --- a/variables.c~ +++ b/variables.c~ @@ -61,6 +61,7 @@ #include "builtins/getopt.h" #include "builtins/common.h" +#include "builtins/builtext.h" #if defined (READLINE) # include "bashline.h" @@ -1788,6 +1789,7 @@ find_variable_internal (name, force_tempenv) { SHELL_VAR *var; int search_tempenv; + VAR_CONTEXT *vc; var = (SHELL_VAR *)NULL; @@ -1801,8 +1803,22 @@ find_variable_internal (name, force_tempenv) if (search_tempenv && temporary_env) var = hash_lookup (name, temporary_env); + vc = shell_variables; +#if 0 +if (search_tempenv == 0 && /* (subshell_environment & SUBSHELL_COMSUB) && */ + expanding_redir && + (this_shell_builtin == eval_builtin || this_shell_builtin == command_builtin)) + { + itrace("find_variable_internal: search_tempenv == 0: skipping VC_BLTNENV"); + while (vc && (vc->flags & VC_BLTNENV)) + vc = vc->down; + if (vc == 0) + vc = shell_variables; + } +#endif + if (var == 0) - var = var_lookup (name, shell_variables); + var = var_lookup (name, vc); if (var == 0) return ((SHELL_VAR *)NULL); @@ -4108,33 +4124,6 @@ put_command_name_into_env (command_name) update_export_env_inplace ("_=", 2, command_name); } -#if 0 /* UNUSED -- it caused too many problems */ -void -put_gnu_argv_flags_into_env (pid, flags_string) - intmax_t pid; - char *flags_string; -{ - char *dummy, *pbuf; - int l, fl; - - pbuf = itos (pid); - l = strlen (pbuf); - - fl = strlen (flags_string); - - dummy = (char *)xmalloc (l + fl + 30); - dummy[0] = '_'; - strcpy (dummy + 1, pbuf); - strcpy (dummy + 1 + l, "_GNU_nonoption_argv_flags_"); - dummy[l + 27] = '='; - strcpy (dummy + l + 28, flags_string); - - free (pbuf); - - export_env = add_or_supercede_exported_var (dummy, 0); -} -#endif - /* **************************************************************** */ /* */ /* Managing variable contexts */