]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
commit bash-20130125 snapshot
authorChet Ramey <chet@caleb.ins.cwru.edu>
Tue, 5 Feb 2013 21:44:34 +0000 (16:44 -0500)
committerChet Ramey <chet@caleb.ins.cwru.edu>
Tue, 5 Feb 2013 21:44:34 +0000 (16:44 -0500)
25 files changed:
CWRU/CWRU.chlog
CWRU/CWRU.chlog~
MANIFEST
builtins/evalfile.c
builtins/read.def
execute_cmd.c
jobs.c
lib/sh/zread.c
redir.c
redir.c~
subst.c
tests/dollar-at-star
tests/dollar-star7.sub [new file with mode: 0644]
tests/dollar.right
tests/exp.right
tests/exp6.sub
tests/trap.right
tests/trap.tests
tests/trap4.sub [new file with mode: 0644]
tests/varenv.right
tests/varenv.sh
tests/varenv5.sub [new file with mode: 0644]
trap.c
variables.c
variables.c~

index 2ac232e4d2893bb7bdf4fc4ed0d39cbf14cd4046..cd35ad3df386dc2a1ee56adbd2636a850026125a 100644 (file)
@@ -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
+         <ormaaj@gmail.com>
+
+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 <rrakus@redhat.com>
+
+                                  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
+         <konsolebox@gmail.com>; 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
+         <ormaaj@gmail.com>
index 726864b9d8496f3b8815d66efe2c2c0c77b0436b..7b2010f773194f813a9717db99b24e4cf51767b9 100644 (file)
@@ -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 <ormaaj@gmail.com> [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
+         <ormaaj@gmail.com>
+
+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 <rrakus@redhat.com>
+
+                                  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
+         <konsolebox@gmail.com>; the rest of the fix is with the changes in
+         trap and signal handling and doing away with interrupt_immediately
index a250b87ffa29427a22362b410bc62f35ee3e0fc9..8db33895e4f5f0b590ac5ac80cbd0fff9d9b7c59 100644 (file)
--- 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
index 60f89d1495e558df4bf3e6565ac450f5f176f299..a59ce597fd8f3acdddd211ff77856da98f9806b6 100644 (file)
@@ -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);
     }      
 
index 30637fbb8e5f2f2fd9be6546f85c1c61c55612d6..ea2667bb7ecd134ad39ae8326c0da6ac61870699 100644 (file)
@@ -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;
        }
index 8b405334f8cba27c081d2d6e914d2345f6001a67..0ff8a9e19b0eca3a7f9c601e7f6c0e84c6106277 100644 (file)
@@ -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 ad9b5ae827d4a565d4298c6ce1757835577f0581..9227638c3c3eb56f1e1fe0394ab7db2a35911a4b 100644 (file)
--- 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
index 832a43c79a156452949c6862eaa4c6e216f729e3..02a20058c1989037837fd3ea716ac2e22a228fb8 100644 (file)
@@ -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 559da1122bb5cd8520f5b4587d9da0b97cab0084..d7da2f3cf339c1fd8363eac0381dfe0dc1f8d763 100644 (file)
--- 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)
     {
index e7a0c0383619afc2626d1177e32ae2966f5fe5b7..65d31f3dd3818947b5f381b6b105643b73aa55ff 100644 (file)
--- 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 d3595b75a3020d309f70ba01a58a54fb0164e350..5f377022366c141e0b025a46d7b9e82f213e5a57 100644 (file)
--- 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, &quoted_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");
index bf95fec1867a039b64fd09b6eb24dd028290551d..f9b9c7019682481ddc538b4749324ac1c910b08d 100755 (executable)
@@ -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 (file)
index 0000000..72d6c24
--- /dev/null
@@ -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 "$*"
index 2e5207cb0fd232f2d0750f6cdb72c2ce30adb0f9..ae0ff03c242b4692911874c5d6ffc86dcaf35e9c 100644 (file)
@@ -237,3 +237,19 @@ argv[1] = <A^?R>
 argv[1] = <AwR>
 argv[1] = <AwR>
 argv[1] = <A^?R>
+<a> <b> <ca> <b> <c-a-b-c> 
+after 1: IFS -
+argv[1] = <a-b-c>
+<a> <b> <c> <da> <b c> <d-a-b c-d> 
+after 2: IFS -
+argv[1] = <a-b c-d>
+argv[1] = <a>
+argv[2] = <b>
+argv[3] = <c>
+argv[4] = <d>
+argv[1] = <a b c d>
+argv[1] = <a>
+argv[2] = <b>
+argv[3] = <c>
+argv[4] = <d>
+argv[1] = <a b c d>
index 5ece7d39e7975961de1658efc64c0e19bf118d18..c027036ed60416af4c8b950031895a2a0f1231cc 100644 (file)
@@ -189,3 +189,19 @@ argv[1] = <c>
 argv[1] = <c>
 argv[1] = <c>
 argv[1] = <c>
+argv[1] = <correct>
+argv[2] = <>
+argv[1] = <correct>
+argv[2] = <>
+argv[1] = <correct>
+argv[2] = <>
+argv[1] = <XwrongX>
+argv[2] = <>
+argv[1] = <correct>
+argv[2] = <a>
+argv[1] = <XwrongX>
+argv[2] = <a>
+argv[1] = <correct>
+argv[2] = <a>
+argv[1] = <correct>
+argv[2] = <a>
index d542f3b42647e335a3249272d51b50c280a2cace..a1c9fe6352305fdf5586d150c852498ee340cddc 100644 (file)
@@ -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
index d1879a42a9af60d35a49ede1d8bcd07df2bacfbf..c04d17260c5ee66816de5213b8852e8ded742652 100644 (file)
@@ -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
index e9e10cc1cb1d0b943b13b15f894cc922a3aee94c..e9859ec8f1d0fb9a4521d356e118d475a259f185 100644 (file)
@@ -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 (file)
index 0000000..6a8abda
--- /dev/null
@@ -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
index 2431d70fc9d57120125f8cece26439976a3d264a..a15b3be67b03a346799355360d2fe598b0eef279 100644 (file)
@@ -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
index b4d2a08eaaf8671549f255f7a762ce7e147ea818..6db6f65dae4ffde3c1bc4e465ed01761be850727 100644 (file)
@@ -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 (file)
index 0000000..8ebfa36
--- /dev/null
@@ -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 f3254b18c11f8210684db9cda42280a2029bbb5d..d60a7fb45e71f484cbe105d6c14f02f4932695fd 100644 (file)
--- 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
index 439e8db7d30eac6e86ddc05accf392c44ae7f5ad..b46eaeb1f32cd2c43aa68d3e8a8d6e8c4d2b4945 100644 (file)
@@ -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);
 
index b6d1ea453561bd354951e61a3e07876f0f70792c..1f05f005e8eacc2adb78ab2f7610746527bab727 100644 (file)
@@ -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                    */