Submitted By:            Matt Burgess <matthew_at_linuxfromscratch_dot_org>
Date:                    2011-03-08
Initial Package Version: 4.2
Upstream Status:         Already in upstream patch repo
Origin:                  Upstream
Description:             This patch contains upstream patch numbers 1 thru 7.

diff -Naur bash-4.2.orig/builtins/printf.def bash-4.2/builtins/printf.def
--- bash-4.2.orig/builtins/printf.def	2010-11-23 15:02:55.000000000 +0000
+++ bash-4.2/builtins/printf.def	2011-03-08 22:14:38.000000000 +0000
@@ -465,6 +465,9 @@
 		  secs = shell_start_time;	/* roughly $SECONDS */
 		else
 		  secs = arg;
+#if defined (HAVE_TZSET)
+		sv_tz ("TZ");		/* XXX -- just make sure */
+#endif
 		tm = localtime (&secs);
 		n = strftime (timebuf, sizeof (timebuf), timefmt, tm);
 		free (timefmt);
diff -Naur bash-4.2.orig/lib/glob/gmisc.c bash-4.2/lib/glob/gmisc.c
--- bash-4.2.orig/lib/glob/gmisc.c	2011-02-05 21:11:17.000000000 +0000
+++ bash-4.2/lib/glob/gmisc.c	2011-03-08 22:14:38.000000000 +0000
@@ -77,8 +77,8 @@
      wchar_t *wpat;
      size_t wmax;
 {
-  wchar_t wc, *wbrack;
-  int matlen, t, in_cclass, in_collsym, in_equiv;
+  wchar_t wc;
+  int matlen, bracklen, t, in_cclass, in_collsym, in_equiv;
 
   if (*wpat == 0)
     return (0);
@@ -118,58 +118,80 @@
 	  break;
 	case L'[':
 	  /* scan for ending `]', skipping over embedded [:...:] */
-	  wbrack = wpat;
+	  bracklen = 1;
 	  wc = *wpat++;
 	  do
 	    {
 	      if (wc == 0)
 		{
-	          matlen += wpat - wbrack - 1;	/* incremented below */
-	          break;
+		  wpat--;			/* back up to NUL */
+	          matlen += bracklen;
+	          goto bad_bracket;
 	        }
 	      else if (wc == L'\\')
 		{
-		  wc = *wpat++;
-		  if (*wpat == 0)
-		    break;
+		  /* *wpat == backslash-escaped character */
+		  bracklen++;
+		  /* If the backslash or backslash-escape ends the string,
+		     bail.  The ++wpat skips over the backslash escape */
+		  if (*wpat == 0 || *++wpat == 0)
+		    {
+		      matlen += bracklen;
+		      goto bad_bracket;
+		    }
 		}
 	      else if (wc == L'[' && *wpat == L':')	/* character class */
 		{
 		  wpat++;
+		  bracklen++;
 		  in_cclass = 1;
 		}
 	      else if (in_cclass && wc == L':' && *wpat == L']')
 		{
 		  wpat++;
+		  bracklen++;
 		  in_cclass = 0;
 		}
 	      else if (wc == L'[' && *wpat == L'.')	/* collating symbol */
 		{
 		  wpat++;
+		  bracklen++;
 		  if (*wpat == L']')	/* right bracket can appear as collating symbol */
-		    wpat++;
+		    {
+		      wpat++;
+		      bracklen++;
+		    }
 		  in_collsym = 1;
 		}
 	      else if (in_collsym && wc == L'.' && *wpat == L']')
 		{
 		  wpat++;
+		  bracklen++;
 		  in_collsym = 0;
 		}
 	      else if (wc == L'[' && *wpat == L'=')	/* equivalence class */
 		{
 		  wpat++;
+		  bracklen++;
 		  if (*wpat == L']')	/* right bracket can appear as equivalence class */
-		    wpat++;
+		    {
+		      wpat++;
+		      bracklen++;
+		    }
 		  in_equiv = 1;
 		}
 	      else if (in_equiv && wc == L'=' && *wpat == L']')
 		{
 		  wpat++;
+		  bracklen++;
 		  in_equiv = 0;
 		}
+	      else
+		bracklen++;
 	    }
 	  while ((wc = *wpat++) != L']');
 	  matlen++;		/* bracket expression can only match one char */
+bad_bracket:
 	  break;
 	}
     }
@@ -213,8 +235,8 @@
      char *pat;
      size_t max;
 {
-  char c, *brack;
-  int matlen, t, in_cclass, in_collsym, in_equiv;
+  char c;
+  int matlen, bracklen, t, in_cclass, in_collsym, in_equiv;
 
   if (*pat == 0)
     return (0);
@@ -254,58 +276,80 @@
 	  break;
 	case '[':
 	  /* scan for ending `]', skipping over embedded [:...:] */
-	  brack = pat;
+	  bracklen = 1;
 	  c = *pat++;
 	  do
 	    {
 	      if (c == 0)
 		{
-	          matlen += pat - brack - 1;	/* incremented below */
-	          break;
+		  pat--;			/* back up to NUL */
+		  matlen += bracklen;
+		  goto bad_bracket;
 	        }
 	      else if (c == '\\')
 		{
-		  c = *pat++;
-		  if (*pat == 0)
-		    break;
+		  /* *pat == backslash-escaped character */
+		  bracklen++;
+		  /* If the backslash or backslash-escape ends the string,
+		     bail.  The ++pat skips over the backslash escape */
+		  if (*pat == 0 || *++pat == 0)
+		    {
+		      matlen += bracklen;
+		      goto bad_bracket;
+		    }
 		}
 	      else if (c == '[' && *pat == ':')	/* character class */
 		{
 		  pat++;
+		  bracklen++;
 		  in_cclass = 1;
 		}
 	      else if (in_cclass && c == ':' && *pat == ']')
 		{
 		  pat++;
+		  bracklen++;
 		  in_cclass = 0;
 		}
 	      else if (c == '[' && *pat == '.')	/* collating symbol */
 		{
 		  pat++;
+		  bracklen++;
 		  if (*pat == ']')	/* right bracket can appear as collating symbol */
-		    pat++;
+		    {
+		      pat++;
+		      bracklen++;
+		    }
 		  in_collsym = 1;
 		}
 	      else if (in_collsym && c == '.' && *pat == ']')
 		{
 		  pat++;
+		  bracklen++;
 		  in_collsym = 0;
 		}
 	      else if (c == '[' && *pat == '=')	/* equivalence class */
 		{
 		  pat++;
+		  bracklen++;
 		  if (*pat == ']')	/* right bracket can appear as equivalence class */
-		    pat++;
+		    {
+		      pat++;
+		      bracklen++;
+		    }
 		  in_equiv = 1;
 		}
 	      else if (in_equiv && c == '=' && *pat == ']')
 		{
 		  pat++;
+		  bracklen++;
 		  in_equiv = 0;
 		}
+	      else
+		bracklen++;
 	    }
 	  while ((c = *pat++) != ']');
 	  matlen++;		/* bracket expression can only match one char */
+bad_bracket:
 	  break;
 	}
     }
diff -Naur bash-4.2.orig/lib/readline/callback.c bash-4.2/lib/readline/callback.c
--- bash-4.2.orig/lib/readline/callback.c	2010-06-06 16:18:58.000000000 +0000
+++ bash-4.2/lib/readline/callback.c	2011-03-08 22:14:38.000000000 +0000
@@ -148,6 +148,9 @@
 	  eof = _rl_vi_domove_callback (_rl_vimvcxt);
 	  /* Should handle everything, including cleanup, numeric arguments,
 	     and turning off RL_STATE_VIMOTION */
+	  if (RL_ISSTATE (RL_STATE_NUMERICARG) == 0)
+	    _rl_internal_char_cleanup ();
+
 	  return;
 	}
 #endif
diff -Naur bash-4.2.orig/lib/readline/vi_mode.c bash-4.2/lib/readline/vi_mode.c
--- bash-4.2.orig/lib/readline/vi_mode.c	2010-11-21 00:51:39.000000000 +0000
+++ bash-4.2/lib/readline/vi_mode.c	2011-03-08 22:14:38.000000000 +0000
@@ -1114,7 +1114,7 @@
       rl_beg_of_line (1, c);
       _rl_vi_last_motion = c;
       RL_UNSETSTATE (RL_STATE_VIMOTION);
-      return (0);
+      return (vidomove_dispatch (m));
     }
 #if defined (READLINE_CALLBACKS)
   /* XXX - these need to handle rl_universal_argument bindings */
diff -Naur bash-4.2.orig/parse.y bash-4.2/parse.y
--- bash-4.2.orig/parse.y	2011-01-02 20:48:11.000000000 +0000
+++ bash-4.2/parse.y	2011-03-08 22:14:38.000000000 +0000
@@ -5135,6 +5135,9 @@
 	    case 'A':
 	      /* Make the current time/date into a string. */
 	      (void) time (&the_time);
+#if defined (HAVE_TZSET)
+	      sv_tz ("TZ");		/* XXX -- just make sure */
+#endif
 	      tm = localtime (&the_time);
 
 	      if (c == 'd')
diff -Naur bash-4.2.orig/patchlevel.h bash-4.2/patchlevel.h
--- bash-4.2.orig/patchlevel.h	2010-06-13 00:14:48.000000000 +0000
+++ bash-4.2/patchlevel.h	2011-03-08 22:14:38.000000000 +0000
@@ -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 7
 
 #endif /* _PATCHLEVEL_H_ */
diff -Naur bash-4.2.orig/subst.c bash-4.2/subst.c
--- bash-4.2.orig/subst.c	2011-01-02 21:12:51.000000000 +0000
+++ bash-4.2/subst.c	2011-03-08 22:14:38.000000000 +0000
@@ -1379,10 +1379,12 @@
   slen = strlen (string + *sindex) + *sindex;
 
   /* The handling of dolbrace_state needs to agree with the code in parse.y:
-     parse_matched_pair() */
-  dolbrace_state = 0;
-  if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
-    dolbrace_state = (flags & SX_POSIXEXP) ? DOLBRACE_QUOTE : DOLBRACE_PARAM;
+     parse_matched_pair().  The different initial value is to handle the
+     case where this function is called to parse the word in
+     ${param op word} (SX_WORD). */
+  dolbrace_state = (flags & SX_WORD) ? DOLBRACE_WORD : DOLBRACE_PARAM;
+  if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && (flags & SX_POSIXEXP))
+    dolbrace_state = DOLBRACE_QUOTE;
 
   i = *sindex;
   while (c = string[i])
@@ -3371,7 +3373,7 @@
   if (string == 0 || *string == '\0')
     return (WORD_LIST *)NULL;
 
-  td.flags = 0;
+  td.flags = W_NOSPLIT2;		/* no splitting, remove "" and '' */
   td.word = string;
   tresult = call_expand_word_internal (&td, quoted, 1, dollar_at_p, has_dollar_at);
   return (tresult);
@@ -4607,6 +4609,7 @@
   if (ifs_firstc == 0)
 #endif
     word->flags |= W_NOSPLIT;
+  word->flags |= W_NOSPLIT2;
   result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
   expand_no_split_dollar_star = 0;
 
@@ -7176,7 +7179,7 @@
     {
       /* Extract the contents of the ${ ... } expansion
 	 according to the Posix.2 rules. */
-      value = extract_dollar_brace_string (string, &sindex, quoted, (c == '%' || c == '#') ? SX_POSIXEXP : 0);
+      value = extract_dollar_brace_string (string, &sindex, quoted, (c == '%' || c == '#' || c =='/' || c == '^' || c == ',' || c ==':') ? SX_POSIXEXP|SX_WORD : SX_WORD);
       if (string[sindex] == RBRACE)
 	sindex++;
       else
diff -Naur bash-4.2.orig/subst.h bash-4.2/subst.h
--- bash-4.2.orig/subst.h	2010-12-03 01:21:29.000000000 +0000
+++ bash-4.2/subst.h	2011-03-08 22:14:38.000000000 +0000
@@ -56,6 +56,7 @@
 #define SX_NOLONGJMP	0x0040	/* don't longjmp on fatal error */
 #define SX_ARITHSUB	0x0080	/* extracting $(( ... )) (currently unused) */
 #define SX_POSIXEXP	0x0100	/* extracting new Posix pattern removal expansions in extract_dollar_brace_string */
+#define SX_WORD		0x0200	/* extracting word in ${param op word} */
 
 /* Remove backslashes which are quoting backquotes from STRING.  Modifies
    STRING, and returns a pointer to it. */
diff -Naur bash-4.2.orig/variables.c bash-4.2/variables.c
--- bash-4.2.orig/variables.c	2011-01-25 01:07:48.000000000 +0000
+++ bash-4.2/variables.c	2011-03-08 22:14:38.000000000 +0000
@@ -3653,6 +3653,22 @@
   return n;
 }
 
+int
+chkexport (name)
+     char *name;
+{
+  SHELL_VAR *v;
+
+  v = find_variable (name);
+  if (v && exported_p (v))
+    {
+      array_needs_making = 1;
+      maybe_make_export_env ();
+      return 1;
+    }
+  return 0;
+}
+
 void
 maybe_make_export_env ()
 {
@@ -4214,7 +4230,7 @@
   { "TEXTDOMAIN", sv_locale },
   { "TEXTDOMAINDIR", sv_locale },
 
-#if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
+#if defined (HAVE_TZSET)
   { "TZ", sv_tz },
 #endif
 
@@ -4558,12 +4574,13 @@
 }
 #endif /* HISTORY */
 
-#if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
+#if defined (HAVE_TZSET)
 void
 sv_tz (name)
      char *name;
 {
-  tzset ();
+  if (chkexport (name))
+    tzset ();
 }
 #endif
 
diff -Naur bash-4.2.orig/variables.h bash-4.2/variables.h
--- bash-4.2.orig/variables.h	2010-12-03 01:22:01.000000000 +0000
+++ bash-4.2/variables.h	2011-03-08 22:14:38.000000000 +0000
@@ -313,6 +313,7 @@
 
 extern void sort_variables __P((SHELL_VAR **));
 
+extern int chkexport __P((char *));
 extern void maybe_make_export_env __P((void));
 extern void update_export_env_inplace __P((char *, int, char *));
 extern void put_command_name_into_env __P((char *));
