+++ /dev/null
-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);
+++ /dev/null
-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;