]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
commit bash-20180406 snapshot
authorChet Ramey <chet.ramey@case.edu>
Thu, 12 Apr 2018 19:09:21 +0000 (15:09 -0400)
committerChet Ramey <chet.ramey@case.edu>
Thu, 12 Apr 2018 19:09:21 +0000 (15:09 -0400)
20 files changed:
CWRU/CWRU.chlog
MANIFEST
execute_cmd.c
execute_cmd.h
jobs.c
lib/glob/smatch.c
lib/readline/doc/readline.3
parse.y
pathexp.h
subst.c
tests/RUN-ONE-TEST
tests/case.right
tests/case.tests
tests/case3.sub [new file with mode: 0644]
tests/heredoc.right
tests/heredoc.tests
tests/heredoc4.sub [new file with mode: 0644]
tests/jobs.right
tests/trap.right
tests/trap2.sub

index fbc27678ab596fabc5a0f67b8d1afbf66a5807e2..dfe2bd8caf418632c646f019c26edd09f124976c 100644 (file)
@@ -15137,3 +15137,63 @@ lib/readline/bind.c
          to accommodate symbolic key sequences; should be a no-op for `raw'
          key sequences such as the arrow key seqeunces from terminfo. Change
          from Koichi Murase <myoga.murase@gmail.com>
+
+                                   4/2
+                                   ---
+jobs.c
+       - wait_for: when setting the SIGINT signal handler to wait_sigint_handler
+         make sure we're not setting old_sigint_handler recursively, as we
+         can when running an external command in a trap we took after a
+         command exited due to SIGINT. We don't want to overwrite
+         old_sigint_handler here. Fixes bug reported by Dr. Werner Fink
+         <werner@suse.de>
+
+execute_cmd.c
+       - execute_disk_command: when there is a command_not_found_hook, make
+         sure the subshell turns off job control before running it, in case
+         it runs processes. We don't want it to manipulate process groups.
+         Fixes bug reported by ÐиÑиллов Ðима <dk.1997-fast@yandex.ru>
+       - execute_command_internal: make sure the command run by the `command'
+         builtin doesn't cause the ERR trap to be executed; wait for the
+         status to be returned by the command builtin. Fixes bug reported by
+         Martijn Dekker <martijn@inlv.org>
+
+                                   4/4
+                                   ---
+subst.c
+       - process_substitute: handle longjmp back to top_level and function
+         returns (return_catch) in the child process, like command
+         substitution, so we don't longjmp back to some arbitrary spot from
+         the `exit' or `return' builtins, or on an expansion error, like
+         the command timing code. Fixes bug reported by Basin Ilya
+         <basinilya@gmail.com>
+
+                                   4/6
+                                   ---
+parse.y
+       - read_token_word: when reading a matched pair of backquotes as part
+         of a word, treat it as quoted so the characters are read as a single
+         word, but do not let the presence of the backquote mark the word as
+         quoted. Fixes here-document delimiter bug reported by Denys Vlasenko
+         <dvlasenk@redhat.com>
+
+                                   4/7
+                                   ---
+execute_cmd.c
+       - execute_case_command: call quote_string_for_globbing with the
+         QGLOB_CTLESC flag for both quoted and unquoted words, so it will
+         remove CTLESC/CTLESC in all cases while converting other quoted
+         characters to use a preceding backslash. Bug reported by
+         Martijn Dekker <martijn@inlv.org>
+
+                                   4/9
+                                   ---
+smatch.c
+       - posix_cclass_only: helper function that checks whether a pattern has
+         only posix single-byte character classes ([:alpha:], etc.) or has
+         none at all
+       - xstrmatch: if running in a multibyte locale, make sure to short-
+         circuit to the single-byte matching code only if there are no
+         unrecognized character class names, since the wide character ctype
+         functions allow locales to define their own character class names
+         (e.g., "hyphen"). Fixes issue reported by yangyajing <yyj_cqu@163.com>
index 235bd9e4177ace05c3c383b00b94d3c7799d89e4..00a577938ef7d30159846f6b19714c504c553227 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -903,6 +903,7 @@ tests/case.tests    f
 tests/case.right       f
 tests/case1.sub                f
 tests/case2.sub                f
+tests/case3.sub                f
 tests/casemod.tests    f
 tests/casemod.right    f
 tests/comsub.tests     f
@@ -1058,6 +1059,7 @@ tests/heredoc.right       f
 tests/heredoc1.sub     f
 tests/heredoc2.sub     f
 tests/heredoc3.sub     f
+tests/heredoc4.sub     f
 tests/herestr.tests    f
 tests/herestr.right    f
 tests/herestr1.sub     f
index 66d2354081c1cf04e41344ec3fb1cde943f2aba3..0ac26030677129dc59b7918dd2371f282219d427 100644 (file)
@@ -873,8 +873,13 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
       }
 
       /* 2009/02/13 -- pipeline failure is processed elsewhere.  This handles
-        only the failure of a simple command. */
-      if (was_error_trap && ignore_return == 0 && invert == 0 && pipe_in == NO_PIPE && pipe_out == NO_PIPE && exec_result != EXECUTION_SUCCESS)
+        only the failure of a simple command. We don't want to run the error
+        trap if the command run by the `command' builtin fails; we want to
+        defer that until the command builtin itself returns failure. */
+      if (was_error_trap && ignore_return == 0 && invert == 0 &&
+           pipe_in == NO_PIPE && pipe_out == NO_PIPE &&
+           (command->value.Simple->flags & CMD_COMMAND_BUILTIN) == 0 &&
+           exec_result != EXECUTION_SUCCESS)
        {
          last_command_exit_value = exec_result;
          line_number = line_number_for_err_trap;
@@ -1421,6 +1426,7 @@ time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close)
       else
        time_format = BASH_TIMEFORMAT;
     }
+
   if (time_format && *time_format)
     print_formatted_time (stderr, time_format, rs, rsf, us, usf, ss, ssf, cpu);
 
@@ -3464,12 +3470,15 @@ execute_case_command (case_command)
 
          if (es && es->word && es->word->word && *(es->word->word))
            {
+             /* Convert quoted null strings into empty strings. */
              qflags = QGLOB_CVTNULL;
+
              /* We left CTLESC in place quoting CTLESC after the call to
                 expand_word_leave_quoted; tell quote_string_for_globbing to
-                remove those here */
-             if ((list->word->flags & W_QUOTED) == 0)
-               qflags |= QGLOB_CTLESC;
+                remove those here. This works for both unquoted portions of
+                the word (which call quote_escapes) and quoted portions
+                (which call quote_string). */
+             qflags |= QGLOB_CTLESC;
              pattern = quote_string_for_globbing (es->word->word, qflags);
            }
          else
@@ -5375,9 +5384,13 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
              exit (EX_NOTFOUND);       /* Posix.2 says the exit status is 127 */
            }
 
+         /* We don't want to manage process groups for processes we start
+            from here, so we turn off job control and don't attempt to
+            manipulate the terminal's process group. */
+         without_job_control ();
+
 #if defined (JOB_CONTROL)
-         /* May need to reinitialize more of the job control state here. */
-         kill_current_pipeline ();
+         set_sigchld_handler ();
 #endif
 
          wl = make_word_list (make_word (NOTFOUND_HOOK), words);
index 4025de8435cda1d8ae62238f53baac575ad7d003..dc2f15ec65d64c601d69ffbae2f4d7337c048bb1 100644 (file)
@@ -35,6 +35,15 @@ struct func_array_state
   };
 #endif
 
+/* Placeholder for later expansion to include more execution state */
+/* XXX - watch out for pid_t */
+struct execstate
+  {
+    pid_t pid;
+    int subshell_env;
+  };
+       
+
 /* Variables delared in execute_cmd.c, used by many other files */
 extern int return_catch_flag;
 extern int return_catch_value;
diff --git a/jobs.c b/jobs.c
index 8e51fa9b3f696da24ef7fa16b2eec065fb3c8d55..45ee572d97c78dc32900dfe6c7d9f2947ba0ec1a 100644 (file)
--- a/jobs.c
+++ b/jobs.c
@@ -2723,7 +2723,17 @@ wait_for (pid)
   wait_sigint_received = child_caught_sigint = 0;
   if (job_control == 0 || (subshell_environment&SUBSHELL_COMSUB))
     {
-      old_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler);
+      SigHandler *temp_sigint_handler;
+
+      temp_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler);
+      if (temp_sigint_handler == wait_sigint_handler)
+        {
+#if defined (DEBUG)
+         internal_warning ("wait_for: recursively setting old_sigint_handler to wait_sigint_handler: running_trap = %d", running_trap);
+#endif
+        }
+      else
+       old_sigint_handler = temp_sigint_handler;
       waiting_for_child = 0;
       if (old_sigint_handler == SIG_IGN)
        set_signal_handler (SIGINT, old_sigint_handler);
index 9032c41a69b5c6e8a5d3e8d0d72420e608463a63..025fe4fca882245dfc0231a7b8cef94a7b856611 100644 (file)
@@ -380,6 +380,50 @@ is_wcclass (wc, name)
     return (iswctype (wc, desc));
 }
 
+/* Return 1 if there are no char class [:class:] expressions (degenerate case)
+   or only posix-specified (C locale supported) char class expressions in
+   PATTERN.  These are the ones where it's safe to punt to the single-byte
+   code, since wide character support allows locale-defined char classes.
+   This only uses single-byte code, but is only needed to support multibyte
+   locales. */
+static int
+posix_cclass_only (pattern)
+     char *pattern;
+{
+  char *p, *p1;
+  char cc[16];         /* sufficient for all valid posix char class names */
+  enum char_class valid;
+
+  p = pattern;
+  while (p = strchr (p, '['))
+    {
+      if (p[1] != ':')
+       {
+         p++;
+         continue;
+        }
+      p += 2;          /* skip past "[:" */
+      /* Find end of char class expression */
+      for (p1 = p; *p1;  p1++)
+       if (*p1 == ':' && p1[1] == ']')
+         break;
+      if (*p1 == 0)    /* no char class expression found */
+       break;
+      /* Find char class name and validate it against posix char classes */
+      if ((p1 - p) >= sizeof (cc))
+       return 0;
+      bcopy (p, cc, p1 - p);
+      cc[p1 - p] = '\0';
+      valid = is_valid_cclass (cc);
+      if (valid == CC_NO_CLASS)
+       return 0;               /* found unrecognized char class name */
+
+      p = p1 + 2;              /* found posix char class name */
+    }
+    
+  return 1;                    /* no char class names or only posix */
+}      
+
 /* Now include `sm_loop.c' for multibyte characters. */
 #define FOLD(c) ((flags & FNM_CASEFOLD) && iswupper (c) ? towlower (c) : (c))
 #define FCT                    internal_wstrmatch
@@ -419,7 +463,7 @@ xstrmatch (pattern, string, flags)
   if (MB_CUR_MAX == 1)
     return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
 
-  if (mbsmbchar (string) == 0 && mbsmbchar (pattern) == 0)
+  if (mbsmbchar (string) == 0 && mbsmbchar (pattern) == 0 && posix_cclass_only (pattern) )
     return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
 
   n = xdupmbstowcs (&wpattern, NULL, pattern);
index c084c6586fd1098759ac3cd7d7df9a979326f5c9..be89c2dff870e1c30cd7f4ff1fc74fca813f0c39 100644 (file)
@@ -1149,6 +1149,7 @@ and store the definition.
 .B call\-last\-kbd\-macro (C\-x e)
 Re-execute the last keyboard macro defined, by making the characters
 in the macro appear as if typed at the keyboard.
+.TP
 .B print\-last\-kbd\-macro ()
 Print the last keyboard macro defined in a format suitable for the
 \fIinputrc\fP file.
diff --git a/parse.y b/parse.y
index 274bb0e133d39fb5988a69e41508a9071907ec4c..b88962efd37f8d0c325a7c02a4e23a3db7029b62 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -4946,7 +4946,8 @@ read_token_word (character)
          strcpy (token + token_index, ttok);
          token_index += ttoklen;
          all_digit_token = 0;
-         quoted = 1;
+         if (character != '`')
+           quoted = 1;
          dollar_present |= (character == '"' && strchr (ttok, '$') != 0);
          FREE (ttok);
          goto next_character;
index 5a69f2f681c89b4b425daca0ddc4e518a9660cb2..adef8b2a169a5f66bed4b7ea5c6c40946a48ee4d 100644 (file)
--- a/pathexp.h
+++ b/pathexp.h
@@ -34,6 +34,7 @@ extern char *glob_error_return;
 #define QGLOB_FILENAME 0x02    /* do correct quoting for matching filenames */
 #define QGLOB_REGEXP   0x04    /* quote an ERE for regcomp/regexec */
 #define QGLOB_CTLESC   0x08    /* turn CTLESC CTLESC into CTLESC for BREs */
+#define QGLOB_DEQUOTE  0x10    /* like dequote_string but quote glob chars */
 
 #if defined (EXTENDED_GLOB)
 /* Flags to OR with other flag args to strmatch() to enabled the extended
diff --git a/subst.c b/subst.c
index 488becdfda1f3a75c79ca2336e249d00e652a54c..1f364cf6257573c87d8d84a85fdc16b9fc27da62 100644 (file)
--- a/subst.c
+++ b/subst.c
@@ -5713,7 +5713,7 @@ process_substitute (string, open_for_read_in_child)
      int open_for_read_in_child;
 {
   char *pathname;
-  int fd, result;
+  int fd, result, rc, function_value;
   pid_t old_pid, pid;
 #if defined (HAVE_DEV_FD)
   int parent_pipe_fd, child_pipe_fd;
@@ -5903,18 +5903,41 @@ process_substitute (string, open_for_read_in_child)
 
   remove_quoted_escapes (string);
 
-  subshell_level++;
-  result = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST));
-  /* leave subshell level intact for any exit trap */
+  /* Give process substitution a place to jump back to on failure,
+     so we don't go back up to main (). */
+  result = setjmp_nosigs (top_level);
+
+  /* If we're running a process substitution inside a shell function,
+     trap `return' so we don't return from the function in the subshell
+     and go off to never-never land. */
+  if (result == 0 && return_catch_flag)
+    function_value = setjmp_nosigs (return_catch);
+  else
+    function_value = 0;
+
+  if (result == ERREXIT)
+    rc = last_command_exit_value;
+  else if (result == EXITPROG)
+    rc = last_command_exit_value;
+  else if (result)
+    rc = EXECUTION_FAILURE;
+  else if (function_value)
+    rc = return_catch_value;
+  else
+    {
+      subshell_level++;
+      rc = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST));
+      /* leave subshell level intact for any exit trap */
+    }
 
 #if !defined (HAVE_DEV_FD)
   /* Make sure we close the named pipe in the child before we exit. */
   close (open_for_read_in_child ? 0 : 1);
 #endif /* !HAVE_DEV_FD */
 
-  last_command_exit_value = result;
-  result = run_exit_trap ();
-  exit (result);
+  last_command_exit_value = rc;
+  rc = run_exit_trap ();
+  exit (rc);
   /*NOTREACHED*/
 }
 #endif /* PROCESS_SUBSTITUTION */
index 58c375b70d886bcff86f789ae4a15eee397f87c8..554f3d6ecc09d7149b13daa2d36a6bab1480269f 100755 (executable)
@@ -1,4 +1,4 @@
-BUILD_DIR=/usr/local/build/chet/bash/bash-current
+BUILD_DIR=/usr/local/build/bash/bash-current
 THIS_SH=$BUILD_DIR/bash
 PATH=$PATH:$BUILD_DIR
 
index 91cbea2ea54c50759fbdd5e8d665be06506ff707..fc3a1285ef7518f1cd6142a2b412077434fcdb38 100644 (file)
@@ -36,3 +36,19 @@ ok 5
 ok 6
 ok 7
 ok 8
+--- testing: soh
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+--- testing: stx
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
index ef25054f77be34efb8a5f413e37c40a042f01050..cc73d8e18e895db338452601e9db021c7d3db7a9 100644 (file)
@@ -52,3 +52,4 @@ case " " in ( [" "] ) echo ok;; ( * ) echo no;; esac
 # tests of quote removal and pattern matching
 ${THIS_SH} ./case1.sub
 ${THIS_SH} ./case2.sub
+${THIS_SH} ./case3.sub
diff --git a/tests/case3.sub b/tests/case3.sub
new file mode 100644 (file)
index 0000000..6b98715
--- /dev/null
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+testmatch() {
+       case $1 in
+       ( $2 ) printf ok1 ;;
+       ( * ) printf fail1 ;;
+       esac
+       case $1,$2 in
+       ( $2,"$2" ) printf ok2 ;;
+       ( * ) printf fail2 ;;
+       esac
+       case $1, in
+       ( $2, ) printf ok3 ;;
+       ( * ) printf fail3 ;;
+       esac
+       case ,$2 in
+       ( ,"$2" ) printf ok4 ;;
+       ( * ) printf fail4 ;;
+       esac
+       case "$1,$2" in
+       ( $2,"$2" ) printf ok5 ;;
+       ( * ) printf fail5 ;;
+       esac
+       echo
+}
+
+for c in $'\1' $'\2'; do
+       echo -n "--- testing: "
+       echo "$c" | od -t a | awk 'NR==1 { print $2 } '
+       testmatch "${c}" "\\${c}"
+       testmatch "${c}x" "\\${c}\\x"  # bash-git fails case 2 and 5 for $'\1'
+       testmatch "${c}x" "${c}\\x"
+       testmatch "${c}x" "${c}x"
+       testmatch "${c}x" "\\${c}x"
+       testmatch "x${c}" "\\x\\${c}"
+       testmatch "x${c}" "x\\${c}"
+done
index 5e596a605a183b811f1402f5d45295f8f457fe06..f6541dcafc129bdf7d381a13d7c7b1b048efaa25 100644 (file)
@@ -84,6 +84,14 @@ hello
 end hello<NL>\END
 ./heredoc3.sub: line 85: warning: here-document at line 83 delimited by end-of-file (wanted `EOF')
 ./heredoc3.sub: line 86: syntax error: unexpected end of file
+heredoc1
+EOF
+Ok:0
+argv[1] = <onetwo>
+argv[2] = <threefour>
+argv[1] = <two>
+argv[2] = <threefi>
+argv[3] = <ve>
 comsub here-string
 ./heredoc.tests: line 105: warning: here-document at line 103 delimited by end-of-file (wanted `EOF')
 hi
index ba74e3b6afb75214d4fc6afd616a6d3164a6b18f..303949f48e659cd61af1a86c8648c51514285a6e 100644 (file)
@@ -90,8 +90,8 @@ ${THIS_SH} ./heredoc1.sub
 
 # test heredocs in command substitutions
 ${THIS_SH} ./heredoc2.sub
-
 ${THIS_SH} ./heredoc3.sub
+${THIS_SH} ./heredoc4.sub
 
 echo $(
        cat <<< "comsub here-string"
diff --git a/tests/heredoc4.sub b/tests/heredoc4.sub
new file mode 100644 (file)
index 0000000..381b64a
--- /dev/null
@@ -0,0 +1,12 @@
+cat <<EO`true`F
+heredoc1
+EO`false`F
+EO`true`F
+echo Ok:$? 
+
+one=one
+four=four
+five='fi ve'
+
+recho $one`echo two three`$four
+recho `echo two three`$five
index 1ff95d385bd8347ef661fa3b2dfefa97cb2fc50f..0e9d1d19ee19fc51f15293716d73601a309b50bb 100644 (file)
@@ -16,11 +16,11 @@ Waiting for job 6
 job 6 returns 0
 Waiting for job 7
 job 7 returns 0
-[1]   Running                 sleep 5 &
-[2]   Running                 sleep 5 &
-[3]   Running                 sleep 5 &
-[4]-  Running                 sleep 5 &
-[5]+  Running                 ( sleep 5; exit 4 ) &
+[1]   Running                 sleep 2 &
+[2]   Running                 sleep 2 &
+[3]   Running                 sleep 2 &
+[4]-  Running                 sleep 2 &
+[5]+  Running                 ( sleep 2; exit 4 ) &
 4
 0
 i killed it
index 1f68d3318543581249c6bcc7b2efbc8031bda844..78b930316a4f16701e8d39a409816ee1ffbe7539 100644 (file)
@@ -64,6 +64,14 @@ after while
 before false in trap2a.sub
 after false in trap2a.sub
 command substitution
+ERRTRAP
+ERRTRAP
+bar
+ERRTRAP
+ERRTRAP
+ERRTRAP
+ERRTRAP
+ERRTRAP
 +[6] echo 1
 1
 +[7] echo 2
index 73357df2a25dfd8c11adab8a78abadc2ac668ffd..0f1f2d96288bd895ebb3fbebfa794de26ac1210c 100755 (executable)
@@ -23,3 +23,27 @@ echo after while
 ./trap2a.sub
 
 echo $(false ; echo command substitution)
+
+# test behavior of failed commands following `command' builtin
+command false
+
+(command false)
+command false | echo bar
+
+(false)
+
+exit 42 | command false
+
+command command command false
+
+unset FALSE
+if [ -x /bin/false ]; then
+        FALSE=/bin/false
+elif [ -x /usr/bin/false ]; then
+        FALSE=/usr/bin/false
+else
+        FALSE='command false'
+fi
+
+command $FALSE
+command command command $FALSE