]> git.ipfire.org Git - ipfire-3.x.git/commitdiff
toolchain: Copy bash's patch files into repository.
authorMichael Tremer <michael.tremer@ipfire.org>
Sun, 7 Feb 2010 14:58:36 +0000 (15:58 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Sun, 7 Feb 2010 14:58:36 +0000 (15:58 +0100)
pkgs/toolchain/bash/bash.nm
pkgs/toolchain/bash/patches/bash-4.0-fixes-1.patch [new file with mode: 0644]
pkgs/toolchain/bash/patches/bash-4.0-fixes-4.patch [new file with mode: 0644]
pkgs/toolchain/bash/patches/bash-4.0-paths-1.patch [new file with mode: 0644]
pkgs/toolchain/bash/patches/bash-4.0-profile-1.patch [new file with mode: 0644]
pkgs/toolchain/bash/patches/bash-4.0-rng.patch [new file with mode: 0644]

index f55e402f3c7b89c2a89c821d85fda636492d7709..b6e5bbe3cf3db7b03ace3ecb8ef51428ba1ac1b8 100644 (file)
@@ -3,8 +3,6 @@ PKG_TOOLCHAIN_DEPS += gcc glibc
 
 include ../../core/bash/bash.nm
 
-PKG_PATCHES =
-
 define STAGE_BUILD
        cd $(DIR_APP) && \
                ac_cv_func_working_mktime=yes \
diff --git a/pkgs/toolchain/bash/patches/bash-4.0-fixes-1.patch b/pkgs/toolchain/bash/patches/bash-4.0-fixes-1.patch
new file mode 100644 (file)
index 0000000..57cba29
--- /dev/null
@@ -0,0 +1,794 @@
+Submitted By:            Matt Burgess <matthew_at_linuxfromscratch_dot_org>
+Date:                    2009-04-18
+Initial Package Version: 4.0
+Upstream Status:         Already in upstream patch repo
+Origin:                  Upstream
+Description:             This patch contains upstream patch numbers 1 thru 17.
+
+diff -Naur bash-4.0.orig/arrayfunc.c bash-4.0/arrayfunc.c
+--- bash-4.0.orig/arrayfunc.c  2009-01-04 19:32:21.000000000 +0000
++++ bash-4.0/arrayfunc.c       2009-04-18 10:10:40.000000000 +0100
+@@ -604,64 +604,7 @@
+     }
+ }
+-/* This function assumes s[i] == '['; returns with s[ret] == ']' if
+-   an array subscript is correctly parsed. */
+-int
+-skipsubscript (s, i)
+-     const char *s;
+-     int i;
+-{
+-  int count, c;
+-#if defined (HANDLE_MULTIBYTE)
+-  mbstate_t state, state_bak;
+-  size_t slength, mblength;
+-#endif
+-
+-#if defined (HANDLE_MULTIBYTE)
+-  memset (&state, '\0', sizeof (mbstate_t));
+-  slength = strlen (s + i);
+-#endif
+-  
+-  count = 1;
+-  while (count)
+-    {
+-      /* Advance one (possibly multibyte) character in S starting at I. */
+-#if defined (HANDLE_MULTIBYTE)
+-      if (MB_CUR_MAX > 1)
+-      {
+-        state_bak = state;
+-        mblength = mbrlen (s + i, slength, &state);
+-
+-        if (MB_INVALIDCH (mblength))
+-          {
+-            state = state_bak;
+-            i++;
+-            slength--;
+-          }
+-        else if (MB_NULLWCH (mblength))
+-          return i;
+-        else
+-          {
+-            i += mblength;
+-            slength -= mblength;
+-          }
+-      }
+-      else
+-#endif
+-      ++i;
+-
+-      c = s[i];
+-
+-      if (c == 0)
+-      break;
+-      else if (c == '[')
+-      count++;
+-      else if (c == ']')
+-      count--;
+-    }
+-
+-  return i;
+-}
++/* skipsubscript moved to subst.c to use private functions. 2009/02/24. */
+ /* This function is called with SUB pointing to just after the beginning
+    `[' of an array subscript and removes the array element to which SUB
+diff -Naur bash-4.0.orig/builtins/declare.def bash-4.0/builtins/declare.def
+--- bash-4.0.orig/builtins/declare.def 2009-01-04 19:32:22.000000000 +0000
++++ bash-4.0/builtins/declare.def      2009-04-18 10:10:40.000000000 +0100
+@@ -295,6 +295,13 @@
+       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;
+@@ -484,7 +491,7 @@
+           }
+         /* 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)
++        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 */
+diff -Naur bash-4.0.orig/builtins/exit.def bash-4.0/builtins/exit.def
+--- bash-4.0.orig/builtins/exit.def    2009-01-04 19:32:22.000000000 +0000
++++ bash-4.0/builtins/exit.def 2009-04-18 10:10:40.000000000 +0100
+@@ -113,7 +113,7 @@
+       for (i = stopmsg = 0; i < js.j_jobslots; i++)
+       if (jobs[i] && STOPPED (i))
+         stopmsg = JSTOPPED;
+-      else if (check_jobs_at_exit && stopmsg == 0 && RUNNING (i))
++      else if (check_jobs_at_exit && stopmsg == 0 && jobs[i] && RUNNING (i))
+         stopmsg = JRUNNING;
+       if (stopmsg == JSTOPPED)
+diff -Naur bash-4.0.orig/builtins/fc.def bash-4.0/builtins/fc.def
+--- bash-4.0.orig/builtins/fc.def      2009-01-04 19:32:22.000000000 +0000
++++ bash-4.0/builtins/fc.def   2009-04-18 10:10:40.000000000 +0100
+@@ -88,6 +88,7 @@
+ extern int current_command_line_count;
+ extern int literal_history;
+ extern int posixly_correct;
++extern int subshell_environment, interactive_shell;
+ extern int unlink __P((const char *));
+@@ -172,7 +173,7 @@
+   register int i;
+   register char *sep;
+   int numbering, reverse, listing, execute;
+-  int histbeg, histend, last_hist, retval, opt;
++  int histbeg, histend, last_hist, retval, opt, rh;
+   FILE *stream;
+   REPL *rlist, *rl;
+   char *ename, *command, *newcom, *fcedit;
+@@ -275,6 +276,8 @@
+       fprintf (stderr, "%s\n", command);
+       fc_replhist (command);  /* replace `fc -s' with command */
++      /* Posix says that the re-executed commands should be entered into the
++       history. */
+       return (parse_and_execute (command, "fc", SEVAL_NOHIST));
+     }
+@@ -293,7 +296,12 @@
+      line was actually added (HISTIGNORE may have caused it to not be),
+      so we check hist_last_line_added. */
+-  last_hist = i - remember_on_history - hist_last_line_added;
++  /* Even though command substitution through parse_and_execute turns off
++     remember_on_history, command substitution in a shell when set -o history
++     has been enabled (interactive or not) should use it in the last_hist
++     calculation as if it were on. */
++  rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list);
++  last_hist = i - rh - hist_last_line_added;
+   if (list)
+     {
+@@ -456,7 +464,7 @@
+      char *command;
+      HIST_ENTRY **hlist;
+ {
+-  int sign, n, clen;
++  int sign, n, clen, rh;
+   register int i, j;
+   register char *s;
+@@ -472,7 +480,12 @@
+      line was actually added (HISTIGNORE may have caused it to not be),
+      so we check hist_last_line_added.  This needs to agree with the
+      calculation of last_hist in fc_builtin above. */
+-  i -= remember_on_history + hist_last_line_added;
++  /* Even though command substitution through parse_and_execute turns off
++     remember_on_history, command substitution in a shell when set -o history
++     has been enabled (interactive or not) should use it in the last_hist
++     calculation as if it were on. */
++  rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list);
++  i -= rh + hist_last_line_added;
+   /* No specification defaults to most recent command. */
+   if (command == NULL)
+diff -Naur bash-4.0.orig/builtins/read.def bash-4.0/builtins/read.def
+--- bash-4.0.orig/builtins/read.def    2009-01-16 04:11:21.000000000 +0000
++++ bash-4.0/builtins/read.def 2009-04-18 10:10:40.000000000 +0100
+@@ -369,14 +369,14 @@
+       code = setjmp (alrmbuf);
+       if (code)
+       {
+-#if 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. */
++        remove_unwind_protect ();
+         run_unwind_frame ("read_builtin");
+-        return (EXECUTION_FAILURE);
+-#else
+         input_string[i] = '\0';       /* make sure it's terminated */
+-        retval = 128+SIGALRM;;
++        retval = 128+SIGALRM;
+         goto assign_vars;
+-#endif
+       }
+       old_alrm = set_signal_handler (SIGALRM, sigalrm);
+       add_unwind_protect (reset_alarm, (char *)NULL);
+diff -Naur bash-4.0.orig/execute_cmd.c bash-4.0/execute_cmd.c
+--- bash-4.0.orig/execute_cmd.c        2009-02-13 21:41:41.000000000 +0000
++++ bash-4.0/execute_cmd.c     2009-04-18 10:10:41.000000000 +0100
+@@ -568,6 +568,7 @@
+       /* Fork a subshell, turn off the subshell bit, turn off job
+        control and call execute_command () on the command again. */
++      line_number_for_err_trap = line_number;
+       paren_pid = make_child (savestring (make_command_string (command)),
+                             asynchronous);
+       if (paren_pid == 0)
+@@ -610,7 +611,10 @@
+             if (user_subshell && was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)
+               {
+                 last_command_exit_value = exec_result;
++                save_line_number = line_number;
++                line_number = line_number_for_err_trap;
+                 run_error_trap ();
++                line_number = save_line_number;
+               }
+             if (user_subshell && ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS)
+@@ -766,7 +770,9 @@
+       if (was_error_trap && ignore_return == 0 && invert == 0 && pipe_in == NO_PIPE && pipe_out == NO_PIPE && exec_result != EXECUTION_SUCCESS)
+       {
+         last_command_exit_value = exec_result;
++        line_number = line_number_for_err_trap;
+         run_error_trap ();
++        line_number = save_line_number;
+       }
+       if (ignore_return == 0 && invert == 0 &&
+@@ -2105,6 +2111,7 @@
+   REDIRECT *rp;
+   COMMAND *tc, *second;
+   int ignore_return, exec_result, was_error_trap, invert;
++  volatile int save_line_number;
+   ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
+@@ -2174,12 +2181,16 @@
+       invert = (command->flags & CMD_INVERT_RETURN) != 0;
+       ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
++      line_number_for_err_trap = line_number;
+       exec_result = execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close);
+       if (was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)
+       {
+         last_command_exit_value = exec_result;
++        save_line_number = line_number;
++        line_number = line_number_for_err_trap;
+         run_error_trap ();
++        line_number = save_line_number;
+       }
+       if (ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS)
+@@ -2930,7 +2941,7 @@
+                 retval = execute_command (clauses->action);
+               }
+             while ((clauses->flags & CASEPAT_FALLTHROUGH) && (clauses = clauses->next));
+-            if ((clauses->flags & CASEPAT_TESTNEXT) == 0)
++            if (clauses == 0 || (clauses->flags & CASEPAT_TESTNEXT) == 0)
+               EXIT_CASE ();
+             else
+               break;
+diff -Naur bash-4.0.orig/parse.y bash-4.0/parse.y
+--- bash-4.0.orig/parse.y      2009-01-08 13:29:12.000000000 +0000
++++ bash-4.0/parse.y   2009-04-18 10:10:41.000000000 +0100
+@@ -1122,7 +1122,7 @@
+                         REDIRECTEE rd;
+                         REDIRECT *r;
+-                        tc = $1;
++                        tc = $1->type == cm_simple ? (COMMAND *)$1->value.Simple : $1;
+                         rd.dest = 1;
+                         r = make_redirection (2, r_duplicating_output, rd);
+                         if (tc->redirects)
+@@ -1615,10 +1615,11 @@
+ {
+   int *ret;
+-  ret = (int *)xmalloc (3 * sizeof (int));
++  ret = (int *)xmalloc (4 * sizeof (int));
+   ret[0] = last_read_token;
+   ret[1] = token_before_that;
+   ret[2] = two_tokens_ago;
++  ret[3] = current_token;
+   return ret;
+ }
+@@ -1631,6 +1632,7 @@
+   last_read_token = ts[0];
+   token_before_that = ts[1];
+   two_tokens_ago = ts[2];
++  current_token = ts[3];
+ }
+ /*
+@@ -1877,7 +1879,7 @@
+     prompt_again ();
+   ret = read_a_line (remove_quoted_newline);
+ #if defined (HISTORY)
+-  if (remember_on_history && (parser_state & PST_HEREDOC))
++  if (ret && remember_on_history && (parser_state & PST_HEREDOC))
+     {
+       /* To make adding the the here-document body right, we need to rely
+        on history_delimiting_chars() returning \n for the first line of
+@@ -2668,6 +2670,7 @@
+   FREE (word_desc_to_read);
+   word_desc_to_read = (WORD_DESC *)NULL;
++  current_token = '\n';               /* XXX */
+   last_read_token = '\n';
+   token_to_read = '\n';
+ }
+@@ -2915,6 +2918,7 @@
+ #define P_DQUOTE      0x04
+ #define P_COMMAND     0x08    /* parsing a command, so look for comments */
+ #define P_BACKQUOTE   0x10    /* parsing a backquoted command substitution */
++#define P_ARRAYSUB    0x20    /* parsing a [...] array subscript for assignment */
+ /* Lexical state while parsing a grouping construct or $(...). */
+ #define LEX_WASDOL    0x001
+@@ -2927,6 +2931,7 @@
+ #define LEX_INHEREDOC 0x080
+ #define LEX_HEREDELIM 0x100           /* reading here-doc delimiter */
+ #define LEX_STRIPDOC  0x200           /* <<- strip tabs from here doc delim */
++#define LEX_INWORD    0x400
+ #define COMSUB_META(ch)               ((ch) == ';' || (ch) == '&' || (ch) == '|')
+@@ -3129,6 +3134,8 @@
+             APPEND_NESTRET ();
+             FREE (nestret);
+           }
++        else if ((flags & P_ARRAYSUB) && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '['))      /* ) } ] */
++          goto parse_dollar_word;
+       }
+       /* Parse an old-style command substitution within double quotes as a
+        single word. */
+@@ -3145,6 +3152,7 @@
+       else if MBTEST(open != '`' && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '['))   /* ) } ] */
+       /* check for $(), $[], or ${} inside quoted string. */
+       {
++parse_dollar_word:
+         if (open == ch)       /* undo previous increment */
+           count--;
+         if (ch == '(')                /* ) */
+@@ -3179,7 +3187,7 @@
+      int open, close;
+      int *lenp, flags;
+ {
+-  int count, ch, peekc, tflags, lex_rwlen, lex_firstind;
++  int count, ch, peekc, tflags, lex_rwlen, lex_wlen, lex_firstind;
+   int nestlen, ttranslen, start_lineno;
+   char *ret, *nestret, *ttrans, *heredelim;
+   int retind, retsize, rflags, hdlen;
+@@ -3200,7 +3208,7 @@
+   retind = 0;
+   start_lineno = line_number;
+-  lex_rwlen = 0;
++  lex_rwlen = lex_wlen = 0;
+   heredelim = 0;
+   lex_firstind = -1;
+@@ -3267,6 +3275,46 @@
+         continue;
+       }
++      if (tflags & LEX_PASSNEXT)              /* last char was backslash */
++      {
++/*itrace("parse_comsub:%d: lex_passnext -> 0 ch = `%c' (%d)", line_number, ch, __LINE__);*/
++        tflags &= ~LEX_PASSNEXT;
++        if (qc != '\'' && ch == '\n') /* double-quoted \<newline> disappears. */
++          {
++            if (retind > 0)
++              retind--;       /* swallow previously-added backslash */
++            continue;
++          }
++
++        RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
++        if MBTEST(ch == CTLESC || ch == CTLNUL)
++          ret[retind++] = CTLESC;
++        ret[retind++] = ch;
++        continue;
++      }
++
++      /* If this is a shell break character, we are not in a word.  If not,
++       we either start or continue a word. */
++      if MBTEST(shellbreak (ch))
++      {
++        tflags &= ~LEX_INWORD;
++/*itrace("parse_comsub:%d: lex_inword -> 0 ch = `%c' (%d)", line_number, ch, __LINE__);*/
++      }
++      else
++      {
++        if (tflags & LEX_INWORD)
++          {
++            lex_wlen++;
++/*itrace("parse_comsub:%d: lex_inword == 1 ch = `%c' lex_wlen = %d (%d)", line_number, ch, lex_wlen, __LINE__);*/
++          }         
++        else
++          {
++/*itrace("parse_comsub:%d: lex_inword -> 1 ch = `%c' (%d)", line_number, ch, __LINE__);*/
++            tflags |= LEX_INWORD;
++            lex_wlen = 0;
++          }
++      }
++
+       /* Skip whitespace */
+       if MBTEST(shellblank (ch) && lex_rwlen == 0)
+         {
+@@ -3364,9 +3412,21 @@
+ }             
+             tflags &= ~LEX_RESWDOK;
+           }
+-        else if (shellbreak (ch) == 0)
++        else if MBTEST((tflags & LEX_CKCOMMENT) && ch == '#' && (lex_rwlen == 0 || ((tflags & LEX_INWORD) && lex_wlen == 0)))
++          ;   /* don't modify LEX_RESWDOK if we're starting a comment */
++        else if MBTEST((tflags & LEX_INCASE) && ch != '\n')
++          /* If we can read a reserved word and we're in case, we're at the
++             point where we can read a new pattern list or an esac.  We
++             handle the esac case above.  If we read a newline, we want to
++             leave LEX_RESWDOK alone.  If we read anything else, we want to
++             turn off LEX_RESWDOK, since we're going to read a pattern list. */
+ {
+-            tflags &= ~LEX_RESWDOK;
++          tflags &= ~LEX_RESWDOK;
++/*itrace("parse_comsub:%d: lex_incase == 1 found `%c', lex_reswordok -> 0", line_number, ch);*/
++}
++        else if MBTEST(shellbreak (ch) == 0)
++{
++          tflags &= ~LEX_RESWDOK;
+ /*itrace("parse_comsub:%d: found `%c', lex_reswordok -> 0", line_number, ch);*/
+ }
+       }
+@@ -3394,36 +3454,23 @@
+               }
+             else
+               shell_ungetc (peekc);
+-            tflags |= LEX_HEREDELIM;
+-            lex_firstind = -1;
++            if (peekc != '<')
++              {
++                tflags |= LEX_HEREDELIM;
++                lex_firstind = -1;
++              }
+             continue;
+           }
+         else
+-          ch = peekc;         /* fall through and continue XXX - this skips comments if peekc == '#' */
++          ch = peekc;         /* fall through and continue XXX */
+       }
+-      /* Not exactly right yet, should handle shell metacharacters, too.  If
+-       any changes are made to this test, make analogous changes to subst.c:
+-       extract_delimited_string(). */
+-      else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || shellblank (ret[retind - 1])))
++      else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (((tflags & LEX_RESWDOK) && lex_rwlen == 0) || ((tflags & LEX_INWORD) && lex_wlen == 0)))
++{
++/*itrace("parse_comsub:%d: lex_incomment -> 1 (%d)", line_number, __LINE__);*/
+       tflags |= LEX_INCOMMENT;
++}
+-      if (tflags & LEX_PASSNEXT)              /* last char was backslash */
+-      {
+-        tflags &= ~LEX_PASSNEXT;
+-        if (qc != '\'' && ch == '\n') /* double-quoted \<newline> disappears. */
+-          {
+-            if (retind > 0)
+-              retind--;       /* swallow previously-added backslash */
+-            continue;
+-          }
+-
+-        RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
+-        if MBTEST(ch == CTLESC || ch == CTLNUL)
+-          ret[retind++] = CTLESC;
+-        ret[retind++] = ch;
+-        continue;
+-      }
+-      else if MBTEST(ch == CTLESC || ch == CTLNUL)    /* special shell escapes */
++      if MBTEST(ch == CTLESC || ch == CTLNUL) /* special shell escapes */
+       {
+         RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
+         ret[retind++] = CTLESC;
+@@ -4248,7 +4295,7 @@
+                    ((token_index > 0 && assignment_acceptable (last_read_token) && token_is_ident (token, token_index)) ||
+                     (token_index == 0 && (parser_state&PST_COMPASSIGN))))
+         {
+-        ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
++        ttok = parse_matched_pair (cd, '[', ']', &ttoklen, P_ARRAYSUB);
+         if (ttok == &matched_pair_error)
+           return -1;          /* Bail immediately. */
+         RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
+@@ -4449,6 +4496,7 @@
+     case '}':         /* XXX */
+     case AND_AND:
+     case BANG:
++    case BAR_AND:
+     case DO:
+     case DONE:
+     case ELIF:
+diff -Naur bash-4.0.orig/patchlevel.h bash-4.0/patchlevel.h
+--- bash-4.0.orig/patchlevel.h 2009-01-04 19:32:40.000000000 +0000
++++ bash-4.0/patchlevel.h      2009-04-18 10:10:41.000000000 +0100
+@@ -25,6 +25,6 @@
+    regexp `^#define[  ]*PATCHLEVEL', since that's what support/mkversion.sh
+    looks for to find the patch level (for the sccs version string). */
+-#define PATCHLEVEL 0
++#define PATCHLEVEL 17
+ #endif /* _PATCHLEVEL_H_ */
+diff -Naur bash-4.0.orig/pcomplete.c bash-4.0/pcomplete.c
+--- bash-4.0.orig/pcomplete.c  2009-02-01 22:12:31.000000000 +0000
++++ bash-4.0/pcomplete.c       2009-04-18 10:10:40.000000000 +0100
+@@ -1032,6 +1032,7 @@
+   cmdlist = build_arg_list (funcname, text, lwords, cw);
+   pps = &ps;
++  save_parser_state (pps);
+   begin_unwind_frame ("gen-shell-function-matches");
+   add_unwind_protect (restore_parser_state, (char *)pps);
+   add_unwind_protect (dispose_words, (char *)cmdlist);
+diff -Naur bash-4.0.orig/sig.c bash-4.0/sig.c
+--- bash-4.0.orig/sig.c        2009-01-04 19:32:41.000000000 +0000
++++ bash-4.0/sig.c     2009-04-18 10:10:40.000000000 +0100
+@@ -448,6 +448,48 @@
+ termsig_sighandler (sig)
+      int sig;
+ {
++  /* If we get called twice with the same signal before handling it,
++     terminate right away. */
++  if (
++#ifdef SIGHUP
++    sig != SIGHUP &&
++#endif
++#ifdef SIGINT
++    sig != SIGINT &&
++#endif
++#ifdef SIGDANGER
++    sig != SIGDANGER &&
++#endif
++#ifdef SIGPIPE
++    sig != SIGPIPE &&
++#endif
++#ifdef SIGALRM
++    sig != SIGALRM &&
++#endif
++#ifdef SIGTERM
++    sig != SIGTERM &&
++#endif
++#ifdef SIGXCPU
++    sig != SIGXCPU &&
++#endif
++#ifdef SIGXFSZ
++    sig != SIGXFSZ &&
++#endif
++#ifdef SIGVTALRM
++    sig != SIGVTALRM &&
++#endif
++#ifdef SIGLOST
++    sig != SIGLOST &&
++#endif
++#ifdef SIGUSR1
++    sig != SIGUSR1 &&
++#endif
++#ifdef SIGUSR2
++   sig != SIGUSR2 &&
++#endif
++   sig == terminating_signal)
++    terminate_immediately = 1;
++
+   terminating_signal = sig;
+   /* XXX - should this also trigger when interrupt_immediately is set? */
+diff -Naur bash-4.0.orig/subst.c bash-4.0/subst.c
+--- bash-4.0.orig/subst.c      2009-01-28 19:34:12.000000000 +0000
++++ bash-4.0/subst.c   2009-04-18 10:10:40.000000000 +0100
+@@ -85,6 +85,7 @@
+ /* Flags for the `pflags' argument to param_expand() */
+ #define PF_NOCOMSUB   0x01    /* Do not perform command substitution */
++#define PF_IGNUNBOUND 0x02    /* ignore unbound vars even if -u set */
+ /* These defs make it easier to use the editor. */
+ #define LBRACE                '{'
+@@ -222,6 +223,7 @@
+ static int skip_double_quoted __P((char *, size_t, int));
+ static char *extract_delimited_string __P((char *, int *, char *, char *, char *, int));
+ static char *extract_dollar_brace_string __P((char *, int *, int, int));
++static int skip_matched_pair __P((const char *, int, int, int, int));
+ static char *pos_params __P((char *, int, int, int));
+@@ -262,7 +264,7 @@
+ static int chk_atstar __P((char *, int, int *, int *));
+ static int chk_arithsub __P((const char *, int));
+-static WORD_DESC *parameter_brace_expand_word __P((char *, int, int));
++static WORD_DESC *parameter_brace_expand_word __P((char *, int, int, int));
+ static WORD_DESC *parameter_brace_expand_indir __P((char *, int, int, int *, int *));
+ static WORD_DESC *parameter_brace_expand_rhs __P((char *, char *, int, int, int *, int *));
+ static void parameter_brace_expand_error __P((char *, char *));
+@@ -1374,6 +1376,107 @@
+ #define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
++/* This function assumes s[i] == open; returns with s[ret] == close; used to
++   parse array subscripts.  FLAGS currently unused. */
++static int
++skip_matched_pair (string, start, open, close, flags)
++     const char *string;
++     int start, open, close, flags;
++{
++  int i, pass_next, backq, si, c, count;
++  size_t slen;
++  char *temp, *ss;
++  DECLARE_MBSTATE;
++
++  slen = strlen (string + start) + start;
++  no_longjmp_on_fatal_error = 1;
++
++  i = start + 1;              /* skip over leading bracket */
++  count = 1;
++  pass_next = backq = 0;
++  ss = (char *)string;
++  while (c = string[i])
++    {
++      if (pass_next)
++      {
++        pass_next = 0;
++        if (c == 0)
++          CQ_RETURN(i);
++        ADVANCE_CHAR (string, slen, i);
++        continue;
++      }
++      else if (c == '\\')
++      {
++        pass_next = 1;
++        i++;
++        continue;
++      }
++      else if (backq)
++      {
++        if (c == '`')
++          backq = 0;
++        ADVANCE_CHAR (string, slen, i);
++        continue;
++      }
++      else if (c == '`')
++      {
++        backq = 1;
++        i++;
++        continue;
++      }
++      else if (c == open)
++      {
++        count++;
++        i++;
++        continue;
++      }
++      else if (c == close)
++      {
++        count--;
++        if (count == 0)
++          break;
++        i++;
++        continue;
++      }
++      else if (c == '\'' || c == '"')
++      {
++        i = (c == '\'') ? skip_single_quoted (ss, slen, ++i)
++                        : skip_double_quoted (ss, slen, ++i);
++        /* no increment, the skip functions increment past the closing quote. */
++      }
++      else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
++      {
++        si = i + 2;
++        if (string[si] == '\0')
++          CQ_RETURN(si);
++
++        if (string[i+1] == LPAREN)
++          temp = extract_delimited_string (ss, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
++        else
++          temp = extract_dollar_brace_string (ss, &si, 0, SX_NOALLOC);
++        i = si;
++        if (string[i] == '\0')        /* don't increment i past EOS in loop */
++          break;
++        i++;
++        continue;
++      }
++      else
++      ADVANCE_CHAR (string, slen, i);
++    }
++
++  CQ_RETURN(i);
++}
++
++#if defined (ARRAY_VARS)
++int
++skipsubscript (string, start)
++     const char *string;
++     int start;
++{
++  return (skip_matched_pair (string, start, '[', ']', 0));
++}
++#endif
++
+ /* Skip characters in STRING until we find a character in DELIMS, and return
+    the index of that character.  START is the index into string at which we
+    begin.  This is similar in spirit to strpbrk, but it returns an index into
+@@ -5093,9 +5196,9 @@
+    the shell, e.g., "@", "$", "*", etc.  QUOTED, if non-zero, means that
+    NAME was found inside of a double-quoted expression. */
+ static WORD_DESC *
+-parameter_brace_expand_word (name, var_is_special, quoted)
++parameter_brace_expand_word (name, var_is_special, quoted, pflags)
+      char *name;
+-     int var_is_special, quoted;
++     int var_is_special, quoted, pflags;
+ {
+   WORD_DESC *ret;
+   char *temp, *tt;
+@@ -5127,7 +5230,7 @@
+       strcpy (tt + 1, name);
+       ret = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL,
+-                        (int *)NULL, (int *)NULL, 0);
++                        (int *)NULL, (int *)NULL, pflags);
+       free (tt);
+     }
+ #if defined (ARRAY_VARS)
+@@ -5188,7 +5291,7 @@
+   char *temp, *t;
+   WORD_DESC *w;
+-  w = parameter_brace_expand_word (name, var_is_special, quoted);
++  w = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND);
+   t = w->word;
+   /* Have to dequote here if necessary */
+   if (t)
+@@ -5205,7 +5308,7 @@
+   if (t == 0)
+     return (WORD_DESC *)NULL;
+-  w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted);
++  w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted, 0);
+   free (t);
+   return w;
+@@ -6556,7 +6659,7 @@
+   if (want_indir)
+     tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at);
+   else
+-    tdesc = parameter_brace_expand_word (name, var_is_special, quoted);
++    tdesc = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND);
+   if (tdesc)
+     {
+@@ -6887,7 +6990,7 @@
+     case '*':         /* `$*' */
+       list = list_rest_of_args ();
+-      if (list == 0 && unbound_vars_is_error)
++      if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
+       {
+         uerror[0] = '$';
+         uerror[1] = '*';
+@@ -6949,7 +7052,7 @@
+     case '@':         /* `$@' */
+       list = list_rest_of_args ();
+-      if (list == 0 && unbound_vars_is_error)
++      if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
+       {
+         uerror[0] = '$';
+         uerror[1] = '@';
+diff -Naur bash-4.0.orig/trap.c bash-4.0/trap.c
+--- bash-4.0.orig/trap.c       2009-01-16 22:07:53.000000000 +0000
++++ bash-4.0/trap.c    2009-04-18 10:10:41.000000000 +0100
+@@ -755,7 +755,7 @@
+       }
+       flags = SEVAL_NONINT|SEVAL_NOHIST;
+-      if (sig != DEBUG_TRAP && sig != RETURN_TRAP)
++      if (sig != DEBUG_TRAP && sig != RETURN_TRAP && sig != ERROR_TRAP)
+       flags |= SEVAL_RESETLINE;
+       if (function_code == 0)
+       parse_and_execute (trap_command, tag, flags);
diff --git a/pkgs/toolchain/bash/patches/bash-4.0-fixes-4.patch b/pkgs/toolchain/bash/patches/bash-4.0-fixes-4.patch
new file mode 100644 (file)
index 0000000..713d2c2
--- /dev/null
@@ -0,0 +1,1337 @@
+Submitted By:            Matt Burgess <matthew_at_linuxfromscratch_dot_org>
+Date:                    2009-09-10
+Initial Package Version: 4.0
+Upstream Status:         Already in upstream patch repo
+Origin:                  Upstream
+Description:             This patch contains upstream patch numbers 1 thru 33.
+
+diff -Naur bash-4.0.orig/arrayfunc.c bash-4.0/arrayfunc.c
+--- bash-4.0.orig/arrayfunc.c  2009-01-04 19:32:21.000000000 +0000
++++ bash-4.0/arrayfunc.c       2009-09-10 19:40:05.000000000 +0100
+@@ -98,7 +98,7 @@
+   oldval = value_cell (var);
+   hash = assoc_create (0);
+   if (oldval)
+-    assoc_insert (hash, "0", oldval);
++    assoc_insert (hash, savestring ("0"), oldval);
+   FREE (value_cell (var));
+   var_setassoc (var, hash);
+@@ -604,64 +604,7 @@
+     }
+ }
+-/* This function assumes s[i] == '['; returns with s[ret] == ']' if
+-   an array subscript is correctly parsed. */
+-int
+-skipsubscript (s, i)
+-     const char *s;
+-     int i;
+-{
+-  int count, c;
+-#if defined (HANDLE_MULTIBYTE)
+-  mbstate_t state, state_bak;
+-  size_t slength, mblength;
+-#endif
+-
+-#if defined (HANDLE_MULTIBYTE)
+-  memset (&state, '\0', sizeof (mbstate_t));
+-  slength = strlen (s + i);
+-#endif
+-  
+-  count = 1;
+-  while (count)
+-    {
+-      /* Advance one (possibly multibyte) character in S starting at I. */
+-#if defined (HANDLE_MULTIBYTE)
+-      if (MB_CUR_MAX > 1)
+-      {
+-        state_bak = state;
+-        mblength = mbrlen (s + i, slength, &state);
+-
+-        if (MB_INVALIDCH (mblength))
+-          {
+-            state = state_bak;
+-            i++;
+-            slength--;
+-          }
+-        else if (MB_NULLWCH (mblength))
+-          return i;
+-        else
+-          {
+-            i += mblength;
+-            slength -= mblength;
+-          }
+-      }
+-      else
+-#endif
+-      ++i;
+-
+-      c = s[i];
+-
+-      if (c == 0)
+-      break;
+-      else if (c == '[')
+-      count++;
+-      else if (c == ']')
+-      count--;
+-    }
+-
+-  return i;
+-}
++/* skipsubscript moved to subst.c to use private functions. 2009/02/24. */
+ /* This function is called with SUB pointing to just after the beginning
+    `[' of an array subscript and removes the array element to which SUB
+diff -Naur bash-4.0.orig/bashline.c bash-4.0/bashline.c
+--- bash-4.0.orig/bashline.c   2009-01-08 14:29:24.000000000 +0000
++++ bash-4.0/bashline.c        2009-09-10 19:40:05.000000000 +0100
+@@ -3388,7 +3388,6 @@
+   Keymap xkmap;               /* unix command executing keymap */
+   register int i;
+   intmax_t mi;
+-  int save_point;
+   sh_parser_state_t ps;
+   char *cmd, *value, *l;
+   SHELL_VAR *v;
+@@ -3432,7 +3431,6 @@
+   if (v)
+     VSETATTR (v, att_exported);
+   l = value_cell (v);
+-  save_point = rl_point;
+   value = inttostr (rl_point, ibuf, sizeof (ibuf));
+   v = bind_int_variable ("READLINE_POINT", value);
+   if (v)
+@@ -3450,7 +3448,7 @@
+   if (v && legal_number (value_cell (v), &mi))
+     {
+       i = mi;
+-      if (i != save_point)
++      if (i != rl_point)
+       {
+         rl_point = i;
+         if (rl_point > rl_end)
+diff -Naur bash-4.0.orig/builtins/declare.def bash-4.0/builtins/declare.def
+--- bash-4.0.orig/builtins/declare.def 2009-01-04 19:32:22.000000000 +0000
++++ bash-4.0/builtins/declare.def      2009-09-10 19:40:04.000000000 +0100
+@@ -295,6 +295,13 @@
+       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;
+@@ -484,7 +491,7 @@
+           }
+         /* 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)
++        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 */
+diff -Naur bash-4.0.orig/builtins/exit.def bash-4.0/builtins/exit.def
+--- bash-4.0.orig/builtins/exit.def    2009-01-04 19:32:22.000000000 +0000
++++ bash-4.0/builtins/exit.def 2009-09-10 19:40:04.000000000 +0100
+@@ -113,7 +113,7 @@
+       for (i = stopmsg = 0; i < js.j_jobslots; i++)
+       if (jobs[i] && STOPPED (i))
+         stopmsg = JSTOPPED;
+-      else if (check_jobs_at_exit && stopmsg == 0 && RUNNING (i))
++      else if (check_jobs_at_exit && stopmsg == 0 && jobs[i] && RUNNING (i))
+         stopmsg = JRUNNING;
+       if (stopmsg == JSTOPPED)
+diff -Naur bash-4.0.orig/builtins/fc.def bash-4.0/builtins/fc.def
+--- bash-4.0.orig/builtins/fc.def      2009-01-04 19:32:22.000000000 +0000
++++ bash-4.0/builtins/fc.def   2009-09-10 19:40:05.000000000 +0100
+@@ -88,6 +88,7 @@
+ extern int current_command_line_count;
+ extern int literal_history;
+ extern int posixly_correct;
++extern int subshell_environment, interactive_shell;
+ extern int unlink __P((const char *));
+@@ -172,7 +173,7 @@
+   register int i;
+   register char *sep;
+   int numbering, reverse, listing, execute;
+-  int histbeg, histend, last_hist, retval, opt;
++  int histbeg, histend, last_hist, retval, opt, rh;
+   FILE *stream;
+   REPL *rlist, *rl;
+   char *ename, *command, *newcom, *fcedit;
+@@ -275,6 +276,8 @@
+       fprintf (stderr, "%s\n", command);
+       fc_replhist (command);  /* replace `fc -s' with command */
++      /* Posix says that the re-executed commands should be entered into the
++       history. */
+       return (parse_and_execute (command, "fc", SEVAL_NOHIST));
+     }
+@@ -293,7 +296,12 @@
+      line was actually added (HISTIGNORE may have caused it to not be),
+      so we check hist_last_line_added. */
+-  last_hist = i - remember_on_history - hist_last_line_added;
++  /* Even though command substitution through parse_and_execute turns off
++     remember_on_history, command substitution in a shell when set -o history
++     has been enabled (interactive or not) should use it in the last_hist
++     calculation as if it were on. */
++  rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list);
++  last_hist = i - rh - hist_last_line_added;
+   if (list)
+     {
+@@ -456,7 +464,7 @@
+      char *command;
+      HIST_ENTRY **hlist;
+ {
+-  int sign, n, clen;
++  int sign, n, clen, rh;
+   register int i, j;
+   register char *s;
+@@ -472,7 +480,12 @@
+      line was actually added (HISTIGNORE may have caused it to not be),
+      so we check hist_last_line_added.  This needs to agree with the
+      calculation of last_hist in fc_builtin above. */
+-  i -= remember_on_history + hist_last_line_added;
++  /* Even though command substitution through parse_and_execute turns off
++     remember_on_history, command substitution in a shell when set -o history
++     has been enabled (interactive or not) should use it in the last_hist
++     calculation as if it were on. */
++  rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list);
++  i -= rh + hist_last_line_added;
+   /* No specification defaults to most recent command. */
+   if (command == NULL)
+diff -Naur bash-4.0.orig/builtins/read.def bash-4.0/builtins/read.def
+--- bash-4.0.orig/builtins/read.def    2009-01-16 04:11:21.000000000 +0000
++++ bash-4.0/builtins/read.def 2009-09-10 19:40:05.000000000 +0100
+@@ -369,14 +369,14 @@
+       code = setjmp (alrmbuf);
+       if (code)
+       {
+-#if 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. */
++        remove_unwind_protect ();
+         run_unwind_frame ("read_builtin");
+-        return (EXECUTION_FAILURE);
+-#else
+         input_string[i] = '\0';       /* make sure it's terminated */
+-        retval = 128+SIGALRM;;
++        retval = 128+SIGALRM;
+         goto assign_vars;
+-#endif
+       }
+       old_alrm = set_signal_handler (SIGALRM, sigalrm);
+       add_unwind_protect (reset_alarm, (char *)NULL);
+@@ -763,7 +763,10 @@
+       if (*input_string == 0)
+       tofree = input_string = t;
+       else
+-      input_string = strip_trailing_ifs_whitespace (t1, ifs_chars, saw_escape);
++      {
++        input_string = strip_trailing_ifs_whitespace (t1, ifs_chars, saw_escape);
++        tofree = t;
++      }
+     }
+ #endif
+diff -Naur bash-4.0.orig/doc/bash.1 bash-4.0/doc/bash.1
+--- bash-4.0.orig/doc/bash.1   2009-02-18 20:13:56.000000000 +0000
++++ bash-4.0/doc/bash.1        2009-09-10 19:40:05.000000000 +0100
+@@ -8257,9 +8257,10 @@
+ Exit after reading and executing one command.
+ .TP 8
+ .B \-u
+-Treat unset variables as an error when performing
++Treat unset variables and parameters other than the special
++parameters "@" and "*" as an error when performing
+ parameter expansion.  If expansion is attempted on an
+-unset variable, the shell prints an error message, and,
++unset variable or parameter, the shell prints an error message, and,
+ if not interactive, exits with a non-zero status.
+ .TP 8
+ .B \-v
+diff -Naur bash-4.0.orig/doc/bashref.texi bash-4.0/doc/bashref.texi
+--- bash-4.0.orig/doc/bashref.texi     2009-02-18 20:14:43.000000000 +0000
++++ bash-4.0/doc/bashref.texi  2009-09-10 19:40:05.000000000 +0100
+@@ -4138,7 +4138,8 @@
+ Exit after reading and executing one command.
+ @item -u
+-Treat unset variables as an error when performing parameter expansion.
++Treat unset variables and parameters other than the special parameters
++@samp{@@} or @samp{*} as an error when performing parameter expansion.
+ An error message will be written to the standard error, and a non-interactive
+ shell will exit.
+diff -Naur bash-4.0.orig/execute_cmd.c bash-4.0/execute_cmd.c
+--- bash-4.0.orig/execute_cmd.c        2009-02-13 21:41:41.000000000 +0000
++++ bash-4.0/execute_cmd.c     2009-09-10 19:40:05.000000000 +0100
+@@ -568,6 +568,7 @@
+       /* Fork a subshell, turn off the subshell bit, turn off job
+        control and call execute_command () on the command again. */
++      line_number_for_err_trap = line_number;
+       paren_pid = make_child (savestring (make_command_string (command)),
+                             asynchronous);
+       if (paren_pid == 0)
+@@ -610,7 +611,10 @@
+             if (user_subshell && was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)
+               {
+                 last_command_exit_value = exec_result;
++                save_line_number = line_number;
++                line_number = line_number_for_err_trap;
+                 run_error_trap ();
++                line_number = save_line_number;
+               }
+             if (user_subshell && ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS)
+@@ -766,7 +770,9 @@
+       if (was_error_trap && ignore_return == 0 && invert == 0 && pipe_in == NO_PIPE && pipe_out == NO_PIPE && exec_result != EXECUTION_SUCCESS)
+       {
+         last_command_exit_value = exec_result;
++        line_number = line_number_for_err_trap;
+         run_error_trap ();
++        line_number = save_line_number;
+       }
+       if (ignore_return == 0 && invert == 0 &&
+@@ -2105,6 +2111,7 @@
+   REDIRECT *rp;
+   COMMAND *tc, *second;
+   int ignore_return, exec_result, was_error_trap, invert;
++  volatile int save_line_number;
+   ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
+@@ -2174,12 +2181,16 @@
+       invert = (command->flags & CMD_INVERT_RETURN) != 0;
+       ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
++      line_number_for_err_trap = line_number;
+       exec_result = execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close);
+       if (was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)
+       {
+         last_command_exit_value = exec_result;
++        save_line_number = line_number;
++        line_number = line_number_for_err_trap;
+         run_error_trap ();
++        line_number = save_line_number;
+       }
+       if (ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS)
+@@ -2930,7 +2941,7 @@
+                 retval = execute_command (clauses->action);
+               }
+             while ((clauses->flags & CASEPAT_FALLTHROUGH) && (clauses = clauses->next));
+-            if ((clauses->flags & CASEPAT_TESTNEXT) == 0)
++            if (clauses == 0 || (clauses->flags & CASEPAT_TESTNEXT) == 0)
+               EXIT_CASE ();
+             else
+               break;
+diff -Naur bash-4.0.orig/externs.h bash-4.0/externs.h
+--- bash-4.0.orig/externs.h    2009-01-18 23:29:29.000000000 +0000
++++ bash-4.0/externs.h 2009-09-10 19:40:05.000000000 +0100
+@@ -192,6 +192,8 @@
+ extern char *fmtumax __P((uintmax_t, int, char *, size_t, int));
+ /* Declarations for functions defined in lib/sh/fpurge.c */
++
++#if defined NEED_FPURGE_DECL
+ #if !HAVE_DECL_FPURGE
+ #if HAVE_FPURGE
+@@ -200,7 +202,7 @@
+ extern int fpurge __P((FILE *stream));
+ #endif /* HAVE_DECL_FPURGE */
+-
++#endif /* NEED_FPURGE_DECL */
+ /* Declarations for functions defined in lib/sh/getcwd.c */
+ #if !defined (HAVE_GETCWD)
+diff -Naur bash-4.0.orig/jobs.c bash-4.0/jobs.c
+--- bash-4.0.orig/jobs.c       2009-01-29 22:09:49.000000000 +0000
++++ bash-4.0/jobs.c    2009-09-10 19:40:05.000000000 +0100
+@@ -442,7 +442,7 @@
+   old_pipeline = the_pipeline;
+   the_pipeline = saved_pipeline;
+   already_making_children = saved_already_making_children;
+-  if (discard)
++  if (discard && old_pipeline)
+     discard_pipeline (old_pipeline);
+ }
+@@ -4202,4 +4202,23 @@
+   sh_closepipe (pgrp_pipe);
+ }
++void
++save_pgrp_pipe (p, clear)
++     int *p;
++     int clear;
++{
++  p[0] = pgrp_pipe[0];
++  p[1] = pgrp_pipe[1];
++  if (clear)
++    pgrp_pipe[0] = pgrp_pipe[1] = -1;
++}
++
++void
++restore_pgrp_pipe (p)
++     int *p;
++{
++  pgrp_pipe[0] = p[0];
++  pgrp_pipe[1] = p[1];
++}
++
+ #endif /* PGRP_PIPE */
+diff -Naur bash-4.0.orig/jobs.h bash-4.0/jobs.h
+--- bash-4.0.orig/jobs.h       2009-01-04 19:32:29.000000000 +0000
++++ bash-4.0/jobs.h    2009-09-10 19:40:05.000000000 +0100
+@@ -235,6 +235,8 @@
+ extern void init_job_stats __P((void));
+ extern void close_pgrp_pipe __P((void));
++extern void save_pgrp_pipe __P((int *, int));
++extern void restore_pgrp_pipe __P((int *));
+ #if defined (JOB_CONTROL)
+ extern int job_control;
+diff -Naur bash-4.0.orig/lib/glob/glob.c bash-4.0/lib/glob/glob.c
+--- bash-4.0.orig/lib/glob/glob.c      2009-01-04 19:32:30.000000000 +0000
++++ bash-4.0/lib/glob/glob.c   2009-09-10 19:40:05.000000000 +0100
+@@ -356,7 +356,7 @@
+       *np = 0;
+       if (ep)
+         *ep = 0;
+-      if (r)
++      if (r && r != &glob_error_return)
+       free (r);
+       return (struct globval *)0;
+     }
+@@ -665,7 +665,9 @@
+       (void) closedir (d);
+     }
+-  /* compat: if GX_ALLDIRS, add the passed directory also */
++  /* compat: if GX_ADDCURDIR, add the passed directory also.  Add an empty
++     directory name as a placeholder if GX_NULLDIR (in which case the passed
++     directory name is "."). */
+   if (add_current)
+     {
+       sdlen = strlen (dir);
+@@ -942,7 +944,12 @@
+             char **array;
+             register unsigned int l;
+-            array = glob_dir_to_array (directories[i], temp_results, flags);
++            /* If we're expanding **, we don't need to glue the directory
++               name to the results; we've already done it in glob_vector */
++            if ((dflags & GX_ALLDIRS) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0')
++              array = temp_results;
++            else
++              array = glob_dir_to_array (directories[i], temp_results, flags);
+             l = 0;
+             while (array[l] != NULL)
+               ++l;
+@@ -959,7 +966,8 @@
+             result[result_size - 1] = NULL;
+             /* Note that the elements of ARRAY are not freed.  */
+-            free ((char *) array);
++            if (array != temp_results)
++              free ((char *) array);
+           }
+       }
+       /* Free the directories.  */
+@@ -1003,11 +1011,24 @@
+       /* Just return what glob_vector () returns appended to the
+        directory name. */
++      /* If flags & GX_ALLDIRS, we're called recursively */
+       dflags = flags & ~GX_MARKDIRS;
+       if (directory_len == 0)
+       dflags |= GX_NULLDIR;
+       if ((flags & GX_GLOBSTAR) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0')
+-      dflags |= GX_ALLDIRS|GX_ADDCURDIR;
++      {
++        dflags |= GX_ALLDIRS|GX_ADDCURDIR;
++#if 0
++        /* If we want all directories (dflags & GX_ALLDIRS) and we're not
++           being called recursively as something like `echo **/*.o'
++           ((flags & GX_ALLDIRS) == 0), we want to prevent glob_vector from
++           adding a null directory name to the front of the temp_results
++           array.  We turn off ADDCURDIR if not called recursively and
++           dlen == 0 */
++#endif
++        if (directory_len == 0 && (flags & GX_ALLDIRS) == 0)
++          dflags &= ~GX_ADDCURDIR;
++      }
+       temp_results = glob_vector (filename,
+                                 (directory_len == 0 ? "." : directory_name),
+                                 dflags);
+diff -Naur bash-4.0.orig/lib/readline/display.c bash-4.0/lib/readline/display.c
+--- bash-4.0.orig/lib/readline/display.c       2009-01-04 19:32:32.000000000 +0000
++++ bash-4.0/lib/readline/display.c    2009-09-10 19:40:05.000000000 +0100
+@@ -512,6 +512,7 @@
+   /* Block keyboard interrupts because this function manipulates global
+      data structures. */
+   _rl_block_sigint ();  
++  RL_SETSTATE (RL_STATE_REDISPLAYING);
+   if (!rl_display_prompt)
+     rl_display_prompt = "";
+@@ -1188,9 +1189,11 @@
+       if (t < out)
+       line[t - 1] = '>';
+-      if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
++      if (rl_display_fixed == 0 || forced_display || lmargin != last_lmargin)
+       {
+         forced_display = 0;
++        o_cpos = _rl_last_c_pos;
++        cpos_adjusted = 0;
+         update_line (&visible_line[last_lmargin],
+                      &invisible_line[lmargin],
+                      0,
+@@ -1198,6 +1201,13 @@
+                      _rl_screenwidth + (lmargin ? 0 : wrap_offset),
+                      0);
++        if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
++            cpos_adjusted == 0 &&
++            _rl_last_c_pos != o_cpos &&
++            _rl_last_c_pos > wrap_offset &&
++            o_cpos < prompt_last_invisible)
++              _rl_last_c_pos -= prompt_invis_chars_first_line;        /* XXX - was wrap_offset */
++
+         /* If the visible new line is shorter than the old, but the number
+            of invisible characters is greater, and we are at the end of
+            the new line, we need to clear to eol. */
+@@ -1236,6 +1246,7 @@
+       visible_wrap_offset = wrap_offset;
+   }
++  RL_UNSETSTATE (RL_STATE_REDISPLAYING);
+   _rl_release_sigint ();
+ }
+@@ -1772,7 +1783,7 @@
+            space_to_eol will insert too many spaces.  XXX - maybe we should
+            adjust col_lendiff based on the difference between _rl_last_c_pos
+            and _rl_screenwidth */
+-        if (col_lendiff && (_rl_last_c_pos < _rl_screenwidth))
++        if (col_lendiff && ((MB_CUR_MAX == 1 || rl_byte_oriented) || (_rl_last_c_pos < _rl_screenwidth)))
+ #endif
+           {     
+             if (_rl_term_autowrap && current_line < inv_botlin)
+@@ -1892,6 +1903,10 @@
+   woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset);
+   cpos = _rl_last_c_pos;
++
++  if (cpos == 0 && cpos == new)
++    return;
++
+ #if defined (HANDLE_MULTIBYTE)
+   /* If we have multibyte characters, NEW is indexed by the buffer point in
+      a multibyte string, but _rl_last_c_pos is the display position.  In
+@@ -1905,9 +1920,9 @@
+        prompt string, since they're both buffer indices and DPOS is a
+        desired display position. */
+       if ((new > prompt_last_invisible) ||            /* XXX - don't use woff here */
+-        (prompt_physical_chars > _rl_screenwidth &&
++        (prompt_physical_chars >= _rl_screenwidth &&
+          _rl_last_v_pos == prompt_last_screen_line &&
+-         wrap_offset >= woff &&
++         wrap_offset >= woff && dpos >= woff &&
+          new > (prompt_last_invisible-(_rl_screenwidth*_rl_last_v_pos)-wrap_offset)))
+          /* XXX last comparison might need to be >= */
+       {
+diff -Naur bash-4.0.orig/lib/readline/readline.h bash-4.0/lib/readline/readline.h
+--- bash-4.0.orig/lib/readline/readline.h      2009-01-04 19:32:33.000000000 +0000
++++ bash-4.0/lib/readline/readline.h   2009-09-10 19:40:05.000000000 +0100
+@@ -814,8 +814,9 @@
+ #define RL_STATE_VIMOTION     0x100000        /* reading vi motion arg */
+ #define RL_STATE_MULTIKEY     0x200000        /* reading multiple-key command */
+ #define RL_STATE_VICMDONCE    0x400000        /* entered vi command mode at least once */
++#define RL_STATE_REDISPLAYING 0x800000        /* updating terminal display */
+-#define RL_STATE_DONE         0x800000        /* done; accepted line */
++#define RL_STATE_DONE         0x1000000       /* done; accepted line */
+ #define RL_SETSTATE(x)                (rl_readline_state |= (x))
+ #define RL_UNSETSTATE(x)      (rl_readline_state &= ~(x))
+diff -Naur bash-4.0.orig/lib/readline/terminal.c bash-4.0/lib/readline/terminal.c
+--- bash-4.0.orig/lib/readline/terminal.c      2009-01-04 19:32:34.000000000 +0000
++++ bash-4.0/lib/readline/terminal.c   2009-09-10 19:40:05.000000000 +0100
+@@ -355,7 +355,7 @@
+       _rl_get_screen_size (fileno (rl_instream), 1);
+       if (CUSTOM_REDISPLAY_FUNC ())
+       rl_forced_update_display ();
+-      else
++      else if (RL_ISSTATE(RL_STATE_REDISPLAYING) == 0)
+       _rl_redisplay_after_sigwinch ();
+     }
+ }
+diff -Naur bash-4.0.orig/lib/sh/winsize.c bash-4.0/lib/sh/winsize.c
+--- bash-4.0.orig/lib/sh/winsize.c     2008-08-12 18:53:51.000000000 +0100
++++ bash-4.0/lib/sh/winsize.c  2009-09-10 19:40:05.000000000 +0100
+@@ -30,16 +30,29 @@
+ #include <sys/ioctl.h>
+-#if !defined (STRUCT_WINSIZE_IN_SYS_IOCTL)
+-/* For struct winsize on SCO */
+-/*   sys/ptem.h has winsize but needs mblk_t from sys/stream.h */
+-#  if defined (HAVE_SYS_PTEM_H) && defined (TIOCGWINSZ) && defined (SIGWINCH)
+-#    if defined (HAVE_SYS_STREAM_H)
+-#      include <sys/stream.h>
+-#    endif
++/* Try to find the definitions of `struct winsize' and TIOGCWINSZ */
++
++#if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ)
++#  include <sys/ioctl.h>
++#endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */
++
++#if defined (STRUCT_WINSIZE_IN_TERMIOS) && !defined (STRUCT_WINSIZE_IN_SYS_IOCTL)
++#  include <termios.h>
++#endif /* STRUCT_WINSIZE_IN_TERMIOS && !STRUCT_WINSIZE_IN_SYS_IOCTL */
++
++/* Not in either of the standard places, look around. */
++#if !defined (STRUCT_WINSIZE_IN_TERMIOS) && !defined (STRUCT_WINSIZE_IN_SYS_IOCTL)
++#  if defined (HAVE_SYS_STREAM_H)
++#    include <sys/stream.h>
++#  endif /* HAVE_SYS_STREAM_H */
++#  if defined (HAVE_SYS_PTEM_H) /* SVR4.2, at least, has it here */
+ #    include <sys/ptem.h>
+-#  endif /* HAVE_SYS_PTEM_H && TIOCGWINSZ && SIGWINCH */
+-#endif /* !STRUCT_WINSIZE_IN_SYS_IOCTL */
++#    define _IO_PTEM_H          /* work around SVR4.2 1.1.4 bug */
++#  endif /* HAVE_SYS_PTEM_H */
++#  if defined (HAVE_SYS_PTE_H)  /* ??? */
++#    include <sys/pte.h>
++#  endif /* HAVE_SYS_PTE_H */
++#endif /* !STRUCT_WINSIZE_IN_TERMIOS && !STRUCT_WINSIZE_IN_SYS_IOCTL */
+ #include <stdio.h>
+diff -Naur bash-4.0.orig/parse.y bash-4.0/parse.y
+--- bash-4.0.orig/parse.y      2009-01-08 13:29:12.000000000 +0000
++++ bash-4.0/parse.y   2009-09-10 19:40:05.000000000 +0100
+@@ -1122,7 +1122,7 @@
+                         REDIRECTEE rd;
+                         REDIRECT *r;
+-                        tc = $1;
++                        tc = $1->type == cm_simple ? (COMMAND *)$1->value.Simple : $1;
+                         rd.dest = 1;
+                         r = make_redirection (2, r_duplicating_output, rd);
+                         if (tc->redirects)
+@@ -1615,10 +1615,11 @@
+ {
+   int *ret;
+-  ret = (int *)xmalloc (3 * sizeof (int));
++  ret = (int *)xmalloc (4 * sizeof (int));
+   ret[0] = last_read_token;
+   ret[1] = token_before_that;
+   ret[2] = two_tokens_ago;
++  ret[3] = current_token;
+   return ret;
+ }
+@@ -1631,6 +1632,7 @@
+   last_read_token = ts[0];
+   token_before_that = ts[1];
+   two_tokens_ago = ts[2];
++  current_token = ts[3];
+ }
+ /*
+@@ -1877,7 +1879,7 @@
+     prompt_again ();
+   ret = read_a_line (remove_quoted_newline);
+ #if defined (HISTORY)
+-  if (remember_on_history && (parser_state & PST_HEREDOC))
++  if (ret && remember_on_history && (parser_state & PST_HEREDOC))
+     {
+       /* To make adding the the here-document body right, we need to rely
+        on history_delimiting_chars() returning \n for the first line of
+@@ -2668,6 +2670,7 @@
+   FREE (word_desc_to_read);
+   word_desc_to_read = (WORD_DESC *)NULL;
++  current_token = '\n';               /* XXX */
+   last_read_token = '\n';
+   token_to_read = '\n';
+ }
+@@ -2915,6 +2918,7 @@
+ #define P_DQUOTE      0x04
+ #define P_COMMAND     0x08    /* parsing a command, so look for comments */
+ #define P_BACKQUOTE   0x10    /* parsing a backquoted command substitution */
++#define P_ARRAYSUB    0x20    /* parsing a [...] array subscript for assignment */
+ /* Lexical state while parsing a grouping construct or $(...). */
+ #define LEX_WASDOL    0x001
+@@ -2927,6 +2931,7 @@
+ #define LEX_INHEREDOC 0x080
+ #define LEX_HEREDELIM 0x100           /* reading here-doc delimiter */
+ #define LEX_STRIPDOC  0x200           /* <<- strip tabs from here doc delim */
++#define LEX_INWORD    0x400
+ #define COMSUB_META(ch)               ((ch) == ';' || (ch) == '&' || (ch) == '|')
+@@ -3129,6 +3134,8 @@
+             APPEND_NESTRET ();
+             FREE (nestret);
+           }
++        else if ((flags & P_ARRAYSUB) && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '['))      /* ) } ] */
++          goto parse_dollar_word;
+       }
+       /* Parse an old-style command substitution within double quotes as a
+        single word. */
+@@ -3145,6 +3152,7 @@
+       else if MBTEST(open != '`' && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '['))   /* ) } ] */
+       /* check for $(), $[], or ${} inside quoted string. */
+       {
++parse_dollar_word:
+         if (open == ch)       /* undo previous increment */
+           count--;
+         if (ch == '(')                /* ) */
+@@ -3179,7 +3187,7 @@
+      int open, close;
+      int *lenp, flags;
+ {
+-  int count, ch, peekc, tflags, lex_rwlen, lex_firstind;
++  int count, ch, peekc, tflags, lex_rwlen, lex_wlen, lex_firstind;
+   int nestlen, ttranslen, start_lineno;
+   char *ret, *nestret, *ttrans, *heredelim;
+   int retind, retsize, rflags, hdlen;
+@@ -3200,7 +3208,7 @@
+   retind = 0;
+   start_lineno = line_number;
+-  lex_rwlen = 0;
++  lex_rwlen = lex_wlen = 0;
+   heredelim = 0;
+   lex_firstind = -1;
+@@ -3267,6 +3275,46 @@
+         continue;
+       }
++      if (tflags & LEX_PASSNEXT)              /* last char was backslash */
++      {
++/*itrace("parse_comsub:%d: lex_passnext -> 0 ch = `%c' (%d)", line_number, ch, __LINE__);*/
++        tflags &= ~LEX_PASSNEXT;
++        if (qc != '\'' && ch == '\n') /* double-quoted \<newline> disappears. */
++          {
++            if (retind > 0)
++              retind--;       /* swallow previously-added backslash */
++            continue;
++          }
++
++        RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
++        if MBTEST(ch == CTLESC || ch == CTLNUL)
++          ret[retind++] = CTLESC;
++        ret[retind++] = ch;
++        continue;
++      }
++
++      /* If this is a shell break character, we are not in a word.  If not,
++       we either start or continue a word. */
++      if MBTEST(shellbreak (ch))
++      {
++        tflags &= ~LEX_INWORD;
++/*itrace("parse_comsub:%d: lex_inword -> 0 ch = `%c' (%d)", line_number, ch, __LINE__);*/
++      }
++      else
++      {
++        if (tflags & LEX_INWORD)
++          {
++            lex_wlen++;
++/*itrace("parse_comsub:%d: lex_inword == 1 ch = `%c' lex_wlen = %d (%d)", line_number, ch, lex_wlen, __LINE__);*/
++          }         
++        else
++          {
++/*itrace("parse_comsub:%d: lex_inword -> 1 ch = `%c' (%d)", line_number, ch, __LINE__);*/
++            tflags |= LEX_INWORD;
++            lex_wlen = 0;
++          }
++      }
++
+       /* Skip whitespace */
+       if MBTEST(shellblank (ch) && lex_rwlen == 0)
+         {
+@@ -3306,7 +3354,7 @@
+       }
+       /* Meta-characters that can introduce a reserved word.  Not perfect yet. */
+-      if MBTEST((tflags & LEX_RESWDOK) == 0 && (tflags & LEX_CKCASE) && (tflags & LEX_INCOMMENT) == 0 && shellmeta(ch))
++      if MBTEST((tflags & LEX_RESWDOK) == 0 && (tflags & LEX_CKCASE) && (tflags & LEX_INCOMMENT) == 0 && (shellmeta(ch) || ch == '\n'))
+       {
+         /* Add this character. */
+         RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
+@@ -3364,9 +3412,21 @@
+ }             
+             tflags &= ~LEX_RESWDOK;
+           }
+-        else if (shellbreak (ch) == 0)
++        else if MBTEST((tflags & LEX_CKCOMMENT) && ch == '#' && (lex_rwlen == 0 || ((tflags & LEX_INWORD) && lex_wlen == 0)))
++          ;   /* don't modify LEX_RESWDOK if we're starting a comment */
++        else if MBTEST((tflags & LEX_INCASE) && ch != '\n')
++          /* If we can read a reserved word and we're in case, we're at the
++             point where we can read a new pattern list or an esac.  We
++             handle the esac case above.  If we read a newline, we want to
++             leave LEX_RESWDOK alone.  If we read anything else, we want to
++             turn off LEX_RESWDOK, since we're going to read a pattern list. */
+ {
+-            tflags &= ~LEX_RESWDOK;
++          tflags &= ~LEX_RESWDOK;
++/*itrace("parse_comsub:%d: lex_incase == 1 found `%c', lex_reswordok -> 0", line_number, ch);*/
++}
++        else if MBTEST(shellbreak (ch) == 0)
++{
++          tflags &= ~LEX_RESWDOK;
+ /*itrace("parse_comsub:%d: found `%c', lex_reswordok -> 0", line_number, ch);*/
+ }
+       }
+@@ -3394,36 +3454,23 @@
+               }
+             else
+               shell_ungetc (peekc);
+-            tflags |= LEX_HEREDELIM;
+-            lex_firstind = -1;
++            if (peekc != '<')
++              {
++                tflags |= LEX_HEREDELIM;
++                lex_firstind = -1;
++              }
+             continue;
+           }
+         else
+-          ch = peekc;         /* fall through and continue XXX - this skips comments if peekc == '#' */
++          ch = peekc;         /* fall through and continue XXX */
+       }
+-      /* Not exactly right yet, should handle shell metacharacters, too.  If
+-       any changes are made to this test, make analogous changes to subst.c:
+-       extract_delimited_string(). */
+-      else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || shellblank (ret[retind - 1])))
++      else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (((tflags & LEX_RESWDOK) && lex_rwlen == 0) || ((tflags & LEX_INWORD) && lex_wlen == 0)))
++{
++/*itrace("parse_comsub:%d: lex_incomment -> 1 (%d)", line_number, __LINE__);*/
+       tflags |= LEX_INCOMMENT;
++}
+-      if (tflags & LEX_PASSNEXT)              /* last char was backslash */
+-      {
+-        tflags &= ~LEX_PASSNEXT;
+-        if (qc != '\'' && ch == '\n') /* double-quoted \<newline> disappears. */
+-          {
+-            if (retind > 0)
+-              retind--;       /* swallow previously-added backslash */
+-            continue;
+-          }
+-
+-        RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
+-        if MBTEST(ch == CTLESC || ch == CTLNUL)
+-          ret[retind++] = CTLESC;
+-        ret[retind++] = ch;
+-        continue;
+-      }
+-      else if MBTEST(ch == CTLESC || ch == CTLNUL)    /* special shell escapes */
++      if MBTEST(ch == CTLESC || ch == CTLNUL) /* special shell escapes */
+       {
+         RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
+         ret[retind++] = CTLESC;
+@@ -4248,7 +4295,7 @@
+                    ((token_index > 0 && assignment_acceptable (last_read_token) && token_is_ident (token, token_index)) ||
+                     (token_index == 0 && (parser_state&PST_COMPASSIGN))))
+         {
+-        ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
++        ttok = parse_matched_pair (cd, '[', ']', &ttoklen, P_ARRAYSUB);
+         if (ttok == &matched_pair_error)
+           return -1;          /* Bail immediately. */
+         RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
+@@ -4449,6 +4496,7 @@
+     case '}':         /* XXX */
+     case AND_AND:
+     case BANG:
++    case BAR_AND:
+     case DO:
+     case DONE:
+     case ELIF:
+diff -Naur bash-4.0.orig/patchlevel.h bash-4.0/patchlevel.h
+--- bash-4.0.orig/patchlevel.h 2009-01-04 19:32:40.000000000 +0000
++++ bash-4.0/patchlevel.h      2009-09-10 19:40:05.000000000 +0100
+@@ -25,6 +25,6 @@
+    regexp `^#define[  ]*PATCHLEVEL', since that's what support/mkversion.sh
+    looks for to find the patch level (for the sccs version string). */
+-#define PATCHLEVEL 0
++#define PATCHLEVEL 33
+ #endif /* _PATCHLEVEL_H_ */
+diff -Naur bash-4.0.orig/pcomplete.c bash-4.0/pcomplete.c
+--- bash-4.0.orig/pcomplete.c  2009-02-01 22:12:31.000000000 +0000
++++ bash-4.0/pcomplete.c       2009-09-10 19:40:04.000000000 +0100
+@@ -1032,6 +1032,7 @@
+   cmdlist = build_arg_list (funcname, text, lwords, cw);
+   pps = &ps;
++  save_parser_state (pps);
+   begin_unwind_frame ("gen-shell-function-matches");
+   add_unwind_protect (restore_parser_state, (char *)pps);
+   add_unwind_protect (dispose_words, (char *)cmdlist);
+diff -Naur bash-4.0.orig/sig.c bash-4.0/sig.c
+--- bash-4.0.orig/sig.c        2009-01-04 19:32:41.000000000 +0000
++++ bash-4.0/sig.c     2009-09-10 19:40:05.000000000 +0100
+@@ -448,6 +448,48 @@
+ termsig_sighandler (sig)
+      int sig;
+ {
++  /* If we get called twice with the same signal before handling it,
++     terminate right away. */
++  if (
++#ifdef SIGHUP
++    sig != SIGHUP &&
++#endif
++#ifdef SIGINT
++    sig != SIGINT &&
++#endif
++#ifdef SIGDANGER
++    sig != SIGDANGER &&
++#endif
++#ifdef SIGPIPE
++    sig != SIGPIPE &&
++#endif
++#ifdef SIGALRM
++    sig != SIGALRM &&
++#endif
++#ifdef SIGTERM
++    sig != SIGTERM &&
++#endif
++#ifdef SIGXCPU
++    sig != SIGXCPU &&
++#endif
++#ifdef SIGXFSZ
++    sig != SIGXFSZ &&
++#endif
++#ifdef SIGVTALRM
++    sig != SIGVTALRM &&
++#endif
++#ifdef SIGLOST
++    sig != SIGLOST &&
++#endif
++#ifdef SIGUSR1
++    sig != SIGUSR1 &&
++#endif
++#ifdef SIGUSR2
++   sig != SIGUSR2 &&
++#endif
++   sig == terminating_signal)
++    terminate_immediately = 1;
++
+   terminating_signal = sig;
+   /* XXX - should this also trigger when interrupt_immediately is set? */
+diff -Naur bash-4.0.orig/subst.c bash-4.0/subst.c
+--- bash-4.0.orig/subst.c      2009-01-28 19:34:12.000000000 +0000
++++ bash-4.0/subst.c   2009-09-10 19:40:05.000000000 +0100
+@@ -85,6 +85,7 @@
+ /* Flags for the `pflags' argument to param_expand() */
+ #define PF_NOCOMSUB   0x01    /* Do not perform command substitution */
++#define PF_IGNUNBOUND 0x02    /* ignore unbound vars even if -u set */
+ /* These defs make it easier to use the editor. */
+ #define LBRACE                '{'
+@@ -222,6 +223,7 @@
+ static int skip_double_quoted __P((char *, size_t, int));
+ static char *extract_delimited_string __P((char *, int *, char *, char *, char *, int));
+ static char *extract_dollar_brace_string __P((char *, int *, int, int));
++static int skip_matched_pair __P((const char *, int, int, int, int));
+ static char *pos_params __P((char *, int, int, int));
+@@ -262,7 +264,7 @@
+ static int chk_atstar __P((char *, int, int *, int *));
+ static int chk_arithsub __P((const char *, int));
+-static WORD_DESC *parameter_brace_expand_word __P((char *, int, int));
++static WORD_DESC *parameter_brace_expand_word __P((char *, int, int, int));
+ static WORD_DESC *parameter_brace_expand_indir __P((char *, int, int, int *, int *));
+ static WORD_DESC *parameter_brace_expand_rhs __P((char *, char *, int, int, int *, int *));
+ static void parameter_brace_expand_error __P((char *, char *));
+@@ -1374,6 +1376,107 @@
+ #define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
++/* This function assumes s[i] == open; returns with s[ret] == close; used to
++   parse array subscripts.  FLAGS currently unused. */
++static int
++skip_matched_pair (string, start, open, close, flags)
++     const char *string;
++     int start, open, close, flags;
++{
++  int i, pass_next, backq, si, c, count;
++  size_t slen;
++  char *temp, *ss;
++  DECLARE_MBSTATE;
++
++  slen = strlen (string + start) + start;
++  no_longjmp_on_fatal_error = 1;
++
++  i = start + 1;              /* skip over leading bracket */
++  count = 1;
++  pass_next = backq = 0;
++  ss = (char *)string;
++  while (c = string[i])
++    {
++      if (pass_next)
++      {
++        pass_next = 0;
++        if (c == 0)
++          CQ_RETURN(i);
++        ADVANCE_CHAR (string, slen, i);
++        continue;
++      }
++      else if (c == '\\')
++      {
++        pass_next = 1;
++        i++;
++        continue;
++      }
++      else if (backq)
++      {
++        if (c == '`')
++          backq = 0;
++        ADVANCE_CHAR (string, slen, i);
++        continue;
++      }
++      else if (c == '`')
++      {
++        backq = 1;
++        i++;
++        continue;
++      }
++      else if (c == open)
++      {
++        count++;
++        i++;
++        continue;
++      }
++      else if (c == close)
++      {
++        count--;
++        if (count == 0)
++          break;
++        i++;
++        continue;
++      }
++      else if (c == '\'' || c == '"')
++      {
++        i = (c == '\'') ? skip_single_quoted (ss, slen, ++i)
++                        : skip_double_quoted (ss, slen, ++i);
++        /* no increment, the skip functions increment past the closing quote. */
++      }
++      else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
++      {
++        si = i + 2;
++        if (string[si] == '\0')
++          CQ_RETURN(si);
++
++        if (string[i+1] == LPAREN)
++          temp = extract_delimited_string (ss, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
++        else
++          temp = extract_dollar_brace_string (ss, &si, 0, SX_NOALLOC);
++        i = si;
++        if (string[i] == '\0')        /* don't increment i past EOS in loop */
++          break;
++        i++;
++        continue;
++      }
++      else
++      ADVANCE_CHAR (string, slen, i);
++    }
++
++  CQ_RETURN(i);
++}
++
++#if defined (ARRAY_VARS)
++int
++skipsubscript (string, start)
++     const char *string;
++     int start;
++{
++  return (skip_matched_pair (string, start, '[', ']', 0));
++}
++#endif
++
+ /* Skip characters in STRING until we find a character in DELIMS, and return
+    the index of that character.  START is the index into string at which we
+    begin.  This is similar in spirit to strpbrk, but it returns an index into
+@@ -5093,9 +5196,9 @@
+    the shell, e.g., "@", "$", "*", etc.  QUOTED, if non-zero, means that
+    NAME was found inside of a double-quoted expression. */
+ static WORD_DESC *
+-parameter_brace_expand_word (name, var_is_special, quoted)
++parameter_brace_expand_word (name, var_is_special, quoted, pflags)
+      char *name;
+-     int var_is_special, quoted;
++     int var_is_special, quoted, pflags;
+ {
+   WORD_DESC *ret;
+   char *temp, *tt;
+@@ -5127,7 +5230,7 @@
+       strcpy (tt + 1, name);
+       ret = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL,
+-                        (int *)NULL, (int *)NULL, 0);
++                        (int *)NULL, (int *)NULL, pflags);
+       free (tt);
+     }
+ #if defined (ARRAY_VARS)
+@@ -5188,7 +5291,7 @@
+   char *temp, *t;
+   WORD_DESC *w;
+-  w = parameter_brace_expand_word (name, var_is_special, quoted);
++  w = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND);
+   t = w->word;
+   /* Have to dequote here if necessary */
+   if (t)
+@@ -5205,7 +5308,7 @@
+   if (t == 0)
+     return (WORD_DESC *)NULL;
+-  w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted);
++  w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted, 0);
+   free (t);
+   return w;
+@@ -6503,7 +6606,7 @@
+           *contains_dollar_at = 1;
+       }
+       free (x);
+-      free (xlist);
++      dispose_words (xlist);
+       free (temp1);
+       *indexp = sindex;
+@@ -6556,7 +6659,7 @@
+   if (want_indir)
+     tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at);
+   else
+-    tdesc = parameter_brace_expand_word (name, var_is_special, quoted);
++    tdesc = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND);
+   if (tdesc)
+     {
+@@ -6664,13 +6767,13 @@
+       return &expand_wdesc_error;
+     case RBRACE:
+-      if (var_is_set == 0 && unbound_vars_is_error)
++      if (var_is_set == 0 && unbound_vars_is_error && ((name[0] != '@' && name[0] != '*') || name[1]))
+       {
++        last_command_exit_value = EXECUTION_FAILURE;
+         err_unboundvar (name);
+         FREE (value);
+         FREE (temp);
+         free (name);
+-        last_command_exit_value = EXECUTION_FAILURE;
+         return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
+       }
+       break;
+@@ -6887,15 +6990,25 @@
+     case '*':         /* `$*' */
+       list = list_rest_of_args ();
+-      if (list == 0 && unbound_vars_is_error)
++#if 0
++      /* According to austin-group posix proposal by Geoff Clare in
++       <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
++
++      "The shell shall write a message to standard error and
++       immediately exit when it tries to expand an unset parameter
++       other than the '@' and '*' special parameters."
++      */
++
++      if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
+       {
+         uerror[0] = '$';
+         uerror[1] = '*';
+         uerror[2] = '\0';
+-        err_unboundvar (uerror);
+         last_command_exit_value = EXECUTION_FAILURE;
++        err_unboundvar (uerror);
+         return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
+       }
++#endif
+       /* If there are no command-line arguments, this should just
+        disappear if there are other characters in the expansion,
+@@ -6949,15 +7062,25 @@
+     case '@':         /* `$@' */
+       list = list_rest_of_args ();
+-      if (list == 0 && unbound_vars_is_error)
++#if 0
++      /* According to austin-group posix proposal by Geoff Clare in
++       <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
++
++      "The shell shall write a message to standard error and
++       immediately exit when it tries to expand an unset parameter
++       other than the '@' and '*' special parameters."
++      */
++
++      if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
+       {
+         uerror[0] = '$';
+         uerror[1] = '@';
+         uerror[2] = '\0';
+-        err_unboundvar (uerror);
+         last_command_exit_value = EXECUTION_FAILURE;
++        err_unboundvar (uerror);
+         return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
+       }
++#endif
+       /* We want to flag the fact that we saw this.  We can't turn
+        off quoting entirely, because other characters in the
+diff -Naur bash-4.0.orig/trap.c bash-4.0/trap.c
+--- bash-4.0.orig/trap.c       2009-01-16 22:07:53.000000000 +0000
++++ bash-4.0/trap.c    2009-09-10 19:40:05.000000000 +0100
+@@ -755,7 +755,7 @@
+       }
+       flags = SEVAL_NONINT|SEVAL_NOHIST;
+-      if (sig != DEBUG_TRAP && sig != RETURN_TRAP)
++      if (sig != DEBUG_TRAP && sig != RETURN_TRAP && sig != ERROR_TRAP)
+       flags |= SEVAL_RESETLINE;
+       if (function_code == 0)
+       parse_and_execute (trap_command, tag, flags);
+@@ -798,12 +798,36 @@
+ run_debug_trap ()
+ {
+   int trap_exit_value;
++  pid_t save_pgrp;
++  int save_pipe[2];
+   /* XXX - question:  should the DEBUG trap inherit the RETURN trap? */
+   trap_exit_value = 0;
+   if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && ((sigmodes[DEBUG_TRAP] & SIG_IGNORED) == 0) && ((sigmodes[DEBUG_TRAP] & SIG_INPROGRESS) == 0))
+     {
++#if defined (JOB_CONTROL)
++      save_pgrp = pipeline_pgrp;
++      pipeline_pgrp = 0;
++      save_pipeline (1);
++#  if defined (PGRP_PIPE)
++      save_pgrp_pipe (save_pipe, 1);
++#  endif
++      stop_making_children ();
++#endif
++
+       trap_exit_value = _run_trap_internal (DEBUG_TRAP, "debug trap");
++
++#if defined (JOB_CONTROL)
++      pipeline_pgrp = save_pgrp;
++      restore_pipeline (1);
++#  if defined (PGRP_PIPE)
++      close_pgrp_pipe ();
++      restore_pgrp_pipe (save_pipe);
++#  endif
++      if (pipeline_pgrp > 0)
++      give_terminal_to (pipeline_pgrp, 1);
++      notify_and_cleanup ();
++#endif
+       
+ #if defined (DEBUGGER)
+       /* If we're in the debugger and the DEBUG trap returns 2 while we're in
+diff -Naur bash-4.0.orig/variables.c bash-4.0/variables.c
+--- bash-4.0.orig/variables.c  2009-01-04 19:32:46.000000000 +0000
++++ bash-4.0/variables.c       2009-09-10 19:40:05.000000000 +0100
+@@ -252,6 +252,7 @@
+ static int visible_var __P((SHELL_VAR *));
+ static int visible_and_exported __P((SHELL_VAR *));
++static int export_environment_candidate __P((SHELL_VAR *));
+ static int local_and_exported __P((SHELL_VAR *));
+ static int variable_in_context __P((SHELL_VAR *));
+ #if defined (ARRAY_VARS)
+@@ -375,10 +376,17 @@
+       }
+ #  endif
+ #endif
++#if 0
+       else if (legal_identifier (name))
++#else
++      else
++#endif
+       {
+         temp_var = bind_variable (name, string, 0);
+-        VSETATTR (temp_var, (att_exported | att_imported));
++        if (legal_identifier (name))
++          VSETATTR (temp_var, (att_exported | att_imported));
++        else
++          VSETATTR (temp_var, (att_exported | att_imported | att_invisible));
+         array_needs_making = 1;
+       }
+@@ -2209,7 +2217,7 @@
+       }
+       else if (assoc_p (entry))
+       {
+-        assoc_insert (assoc_cell (entry), "0", newval);
++        assoc_insert (assoc_cell (entry), savestring ("0"), newval);
+         free (newval);
+       }
+       else
+@@ -3082,6 +3090,16 @@
+   return (invisible_p (var) == 0 && exported_p (var));
+ }
++/* Candidate variables for the export environment are either valid variables
++   with the export attribute or invalid variables inherited from the initial
++   environment and simply passed through. */
++static int
++export_environment_candidate (var)
++     SHELL_VAR *var;
++{
++  return (exported_p (var) && (invisible_p (var) == 0 || imported_p (var)));
++}
++
+ /* Return non-zero if VAR is a local variable in the current context and
+    is exported. */
+ static int
+@@ -3438,7 +3456,11 @@
+   char **list;
+   SHELL_VAR **vars;
++#if 0
+   vars = map_over (visible_and_exported, vcxt);
++#else
++  vars = map_over (export_environment_candidate, vcxt);
++#endif
+   if (vars == 0)
+     return (char **)NULL;
diff --git a/pkgs/toolchain/bash/patches/bash-4.0-paths-1.patch b/pkgs/toolchain/bash/patches/bash-4.0-paths-1.patch
new file mode 100644 (file)
index 0000000..735a381
--- /dev/null
@@ -0,0 +1,30 @@
+--- bash-3.0/config.h.in.paths 2004-07-21 21:08:31.000000000 +0100
++++ bash-3.0/config.h.in       2004-07-28 09:16:27.257884999 +0100
+@@ -197,7 +197,7 @@
+ /* System paths */
+-#define DEFAULT_MAIL_DIRECTORY "/usr/spool/mail"
++#define DEFAULT_MAIL_DIRECTORY "/var/spool/mail"
+ /* Characteristics of the system's header files and libraries that affect
+    the compilation environment. */
+--- bash-3.0/config-top.h.paths        2003-08-05 15:36:12.000000000 +0100
++++ bash-3.0/config-top.h      2004-07-28 09:36:27.117205637 +0100
+@@ -52,14 +52,14 @@
+ /* The default value of the PATH variable. */
+ #ifndef DEFAULT_PATH_VALUE
+ #define DEFAULT_PATH_VALUE \
+-  "/usr/gnu/bin:/usr/local/bin:/bin:/usr/bin:."
++  "/usr/local/bin:/bin:/usr/bin"
+ #endif
+ /* The value for PATH when invoking `command -p'.  This is only used when
+    the Posix.2 confstr () function, or CS_PATH define are not present. */
+ #ifndef STANDARD_UTILS_PATH
+ #define STANDARD_UTILS_PATH \
+-  "/bin:/usr/bin:/sbin:/usr/sbin:/etc:/usr/etc"
++  "/bin:/usr/bin:/usr/sbin:/sbin"
+ #endif
+ /* Default primary and secondary prompt strings. */
diff --git a/pkgs/toolchain/bash/patches/bash-4.0-profile-1.patch b/pkgs/toolchain/bash/patches/bash-4.0-profile-1.patch
new file mode 100644 (file)
index 0000000..ba3344b
--- /dev/null
@@ -0,0 +1,12 @@
+diff -up bash-3.2/config-top.h.profile bash-3.2/config-top.h
+--- bash-3.2/config-top.h.profile      2008-07-17 13:35:39.000000000 +0200
++++ bash-3.2/config-top.h      2008-07-17 13:42:18.000000000 +0200
+@@ -26,6 +26,8 @@
+    what POSIX.2 specifies. */
+ #define CONTINUE_AFTER_KILL_ERROR
++#define NON_INTERACTIVE_LOGIN_SHELLS
++
+ /* Define BREAK_COMPLAINS if you want the non-standard, but useful
+    error messages about `break' and `continue' out of context. */
+ #define BREAK_COMPLAINS
diff --git a/pkgs/toolchain/bash/patches/bash-4.0-rng.patch b/pkgs/toolchain/bash/patches/bash-4.0-rng.patch
new file mode 100644 (file)
index 0000000..5534466
--- /dev/null
@@ -0,0 +1,149 @@
+This patch is from:
+       http://cvs.fedoraproject.org/viewvc/devel/bash/bash-3.2-rng.patch
+       http://cvs.fedoraproject.org/viewvc/devel/bash/bash-3.2-344411.patch
+
+The second patch (bash-3.2-344411.patch) was integrated in bash-4.0, to provide
+$RANDOM in sub shells.
+
+Use /dev/urandom for $RANDOM. This patch does not break the Korn shell
+behaviour, where we can initialize $RANDOM ourselves and get the same results
+each time. /dev/urandom is only opened when $RANDOM is called.
+
+I pulled out all the autoconf stuff. This patch depends on random(3) and
+srandom(3) in libc, and /dev/urandom. getpid(3) and gettimeofday(3) are used
+if /dev/urandom isn't available at run time (like in a chroot).
+
+Test case:
+( echo $RANDOM; ( echo $RANDOM ); ( echo $RANDOM ) )
+
+robert
+
+diff -Naur bash-4.0.orig/variables.c bash-4.0/variables.c
+--- bash-4.0.orig/variables.c  2009-01-04 19:32:46.000000000 +0000
++++ bash-4.0/variables.c       2009-02-22 20:15:50.000000000 +0000
+@@ -44,6 +44,12 @@
+ #include "bashansi.h"
+ #include "bashintl.h"
++#include <errno.h>
++#include "filecntl.h"
++#ifndef RANDOMDEV
++#define RANDOMDEV "/dev/urandom"
++#endif
++
+ #include "shell.h"
+ #include "flags.h"
+ #include "execute_cmd.h"
+@@ -188,7 +194,7 @@
+ static SHELL_VAR *init_seconds_var __P((void));
+ static int brand __P((void));
+-static void sbrand __P((unsigned long));              /* set bash random number generator. */
++static void sbrand __P((unsigned int));                       /* set bash random number generator. */
+ static void seedrand __P((void));                     /* seed generator randomly */
+ static SHELL_VAR *assign_random __P((SHELL_VAR *, char *, arrayind_t, char *));
+ static SHELL_VAR *get_random __P((SHELL_VAR *));
+@@ -518,9 +524,6 @@
+     }
+ #endif /* HISTORY */
+-  /* Seed the random number generator. */
+-  seedrand ();
+-
+   /* Handle some "special" variables that we may have inherited from a
+      parent shell. */
+   if (interactive_shell)
+@@ -1204,9 +1207,8 @@
+ }
+      
+ /* The random number seed.  You can change this by setting RANDOM. */
+-static unsigned long rseed = 1;
+ static int last_random_value;
+-static int seeded_subshell = 0;
++static int seeded_subshell = -1;
+ /* A linear congruential random number generator based on the example
+    one in the ANSI C standard.  This one isn't very good, but a more
+@@ -1216,44 +1218,36 @@
+ static int
+ brand ()
+ {
+-#if 0
+-  rseed = rseed * 1103515245 + 12345;
+-  return ((unsigned int)((rseed >> 16) & 32767));     /* was % 32768 */
+-#else
+-  /* From "Random number generators: good ones are hard to find",
+-     Park and Miller, Communications of the ACM, vol. 31, no. 10,
+-     October 1988, p. 1195. filtered through FreeBSD */
+-  long h, l;
+-
+-  if (rseed == 0)
+-    seedrand ();
+-  h = rseed / 127773;
+-  l = rseed % 127773;
+-  rseed = 16807 * l - 2836 * h;
+-#if 0
+-  if (rseed < 0)
+-    rseed += 0x7fffffff;
+-#endif
++  unsigned int rseed;
++  rseed = random();
+   return ((unsigned int)(rseed & 32767));     /* was % 32768 */
+-#endif
+ }
+ /* Set the random number generator seed to SEED. */
+ static void
+ sbrand (seed)
+-     unsigned long seed;
++     unsigned int seed;
+ {
+-  rseed = seed;
++  srandom((unsigned int)seed);
+   last_random_value = 0;
+ }
+ static void
+ seedrand ()
+ {
+-  struct timeval tv;
+-
+-  gettimeofday (&tv, NULL);
+-  sbrand (tv.tv_sec ^ tv.tv_usec ^ getpid ());
++  unsigned int seed;
++  int fd;
++  int rv;
++  if ((rv = fd = open (RANDOMDEV, O_RDONLY)) != -1) {
++    while ((rv = read(fd, &seed, sizeof(seed))) != sizeof(seed) && errno == EINTR);
++    close (fd);
++  }
++  if (rv != sizeof(seed)) {
++    struct timeval tv;
++    gettimeofday (&tv, NULL);
++    seed = (unsigned int)tv.tv_sec + (unsigned int)tv.tv_usec + getpid();
++  }
++  sbrand (seed);
+ }
+ static SHELL_VAR *
+@@ -1263,9 +1257,8 @@
+      arrayind_t unused;
+      char *key;
+ {
+-  sbrand (strtoul (value, (char **)NULL, 10));
+-  if (subshell_environment)
+-    seeded_subshell = getpid ();
++  sbrand ((unsigned int)strtoul (value, (char **)NULL, 10));
++  seeded_subshell = getpid ();
+   return (self);
+ }
+@@ -1276,7 +1269,7 @@
+   /* Reset for command and process substitution. */
+   pid = getpid ();
+-  if (subshell_environment && seeded_subshell != pid)
++  if (seeded_subshell != pid)
+     {
+       seedrand ();
+       seeded_subshell = pid;