From: Michael Tremer Date: Sun, 7 Feb 2010 14:58:36 +0000 (+0100) Subject: toolchain: Copy bash's patch files into repository. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a744c44477b6f15414edcc69d6588b32c67f989f;p=ipfire-3.x.git toolchain: Copy bash's patch files into repository. --- diff --git a/pkgs/toolchain/bash/bash.nm b/pkgs/toolchain/bash/bash.nm index f55e402f3..b6e5bbe3c 100644 --- a/pkgs/toolchain/bash/bash.nm +++ b/pkgs/toolchain/bash/bash.nm @@ -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 index 000000000..57cba2944 --- /dev/null +++ b/pkgs/toolchain/bash/patches/bash-4.0-fixes-1.patch @@ -0,0 +1,794 @@ +Submitted By: Matt Burgess +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 \ 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 \ 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 index 000000000..713d2c202 --- /dev/null +++ b/pkgs/toolchain/bash/patches/bash-4.0-fixes-4.patch @@ -0,0 +1,1337 @@ +Submitted By: Matt Burgess +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 + +-#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 +-# endif ++/* Try to find the definitions of `struct winsize' and TIOGCWINSZ */ ++ ++#if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ) ++# include ++#endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */ ++ ++#if defined (STRUCT_WINSIZE_IN_TERMIOS) && !defined (STRUCT_WINSIZE_IN_SYS_IOCTL) ++# include ++#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 ++# endif /* HAVE_SYS_STREAM_H */ ++# if defined (HAVE_SYS_PTEM_H) /* SVR4.2, at least, has it here */ + # include +-# 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 ++# endif /* HAVE_SYS_PTE_H */ ++#endif /* !STRUCT_WINSIZE_IN_TERMIOS && !STRUCT_WINSIZE_IN_SYS_IOCTL */ + + #include + +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 \ 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 \ 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 index 000000000..735a3810f --- /dev/null +++ b/pkgs/toolchain/bash/patches/bash-4.0-paths-1.patch @@ -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 index 000000000..ba3344b3c --- /dev/null +++ b/pkgs/toolchain/bash/patches/bash-4.0-profile-1.patch @@ -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 index 000000000..5534466cd --- /dev/null +++ b/pkgs/toolchain/bash/patches/bash-4.0-rng.patch @@ -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 ++#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;