]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
commit bash-20180504 snapshot
authorChet Ramey <chet.ramey@case.edu>
Tue, 8 May 2018 18:27:28 +0000 (14:27 -0400)
committerChet Ramey <chet.ramey@case.edu>
Tue, 8 May 2018 18:27:28 +0000 (14:27 -0400)
13 files changed:
CWRU/CWRU.chlog
bashline.c
builtins/builtin.def
doc/bashref.texi
redir.c
sig.c
tests/RUN-ONE-TEST
tests/procsub.right
tests/procsub.tests
tests/test-glue-functions
tests/varenv.right
variables.c
variables.h

index 249d8425db7e2426a6009e34f029cbe1b2a3fcc3..1cacea208bc55ac1d973991057119ff6909f8ee8 100644 (file)
@@ -15318,3 +15318,43 @@ subst.c
          to the flags passed to quote_string_for_globbing. Same issue as the
          one with `case' fixed on 4/7, report from Martijn Dekker
          <martijn@inlv.org>
+
+                                  4/30
+                                  ----
+redir.c
+       - do_redirection_internal: r_close_this: if the file descriptor is
+         already closed before the shell is asked to close it, make sure to
+         add an undo list redirect to make sure it stays closed. Report from
+         Martijn Dekker <martijn@inlv.org>
+
+                                   5/2
+                                   ---
+variables.c
+       - push_posix_temp_var: new function, takes the SHELL_VAR * passed as
+         an argument and uses the name and value to create a global variable
+       - merge_temporary_env: if posixly_correct is set, call
+         push_posix_temp_var to create global variables, otherwise call
+         push_temp_var to preserve the old behavior. Right now, it's only
+         called when in posix mode, but that might change. This undoes the
+         change from 4/27 when in posix mode
+
+                                   5/3
+                                   ---
+sig.c
+       - struct that holds the terminating signal information has a new
+         field: whether that signal is expected to cause a core dump
+       - termsig_handler: if the call to kill(2) doesn't kill the process,
+         we have a problem. If our pid is not 1, we just exit with status
+         128+sig (fake the sig exit status). If the pid is 1, we assume
+         we're in a Linux pid namespace and aren't allowed to send a signal
+         to ourselves. If we need to generate a core dump, we try to get
+         the kernel to SIGSEGV us by dereferencing location 0. If not, we
+         just exit with 128+sig. From a report and patch from Andrei Vagin
+         <avagin@virtuozzo.com>
+
+                                   5/4
+                                   ---
+bashline.c
+       - bash_execute_unix_command: make sure that parse_and_execute is called
+         with newly-allocated memory to avoid prematurely freeing the
+         command. Report and fix from Koichi Murase <myoga.murase@gmail.com>
index 91d444654041d3e3e022c88efec7bdd352e3d307..ae8fe1cccefa34adc731dd1710021ffb0badefc5 100644 (file)
@@ -4147,7 +4147,7 @@ bash_execute_unix_command (count, key)
   array_needs_making = 1;
 
   save_parser_state (&ps);
-  r = parse_and_execute (cmd, "bash_execute_unix_command", SEVAL_NOHIST|SEVAL_NOFREE);
+  r = parse_and_execute (savestring (cmd), "bash_execute_unix_command", SEVAL_NOHIST|SEVAL_NOFREE);
   restore_parser_state (&ps);
 
   v = find_variable ("READLINE_LINE");
index b09246c4194a5d7a00c4970ff9ad84a6c5264ab6..74060ee09f00a4108f5fb358c7706d5a1e1083fa 100644 (file)
@@ -31,7 +31,7 @@ as a shell function, but need to execute the builtin within the function.
 
 Exit Status:
 Returns the exit status of SHELL-BUILTIN, or false if SHELL-BUILTIN is
-not a shell builtin..
+not a shell builtin.
 $END
 #include <config.h>
 
index 04da396db3e92ec9b1c16ecf9da6999ead4ef767..f9f425368ec23b5b35af9f3b79d6ae5c65e7a48e 100644 (file)
@@ -6065,7 +6065,7 @@ as the sole input.  If set, the value denotes the number
 of consecutive @code{EOF} characters that can be read as the
 first character on an input line
 before the shell will exit.  If the variable exists but does not
-have a numeric value (or has no value) then the default is 10.
+have a numeric value, or has no value, then the default is 10.
 If the variable does not exist, then @code{EOF} signifies the end of 
 input to the shell.  This is only in effect for interactive shells.
 
diff --git a/redir.c b/redir.c
index ebb2c6352b4b9cd6517c98e29135369d81e94d99..f5276dc650813e49f871fb1198c6a146caa561eb 100644 (file)
--- a/redir.c
+++ b/redir.c
@@ -1142,9 +1142,12 @@ do_redirection_internal (redirect, flags)
 
          r = 0;
          /* XXX - only if REDIR_VARASSIGN not set? */
-         if ((flags & RX_UNDOABLE) && (fcntl (redirector, F_GETFD, 0) != -1))
+         if (flags & RX_UNDOABLE)
            {
-             r = add_undo_redirect (redirector, ri, -1);
+             if (fcntl (redirector, F_GETFD, 0) != -1)
+               r = add_undo_redirect (redirector, ri, -1);
+             else
+               r = add_undo_close_redirect (redirector);
              REDIRECTION_ERROR (r, errno, redirector);
            }
 
diff --git a/sig.c b/sig.c
index ac2ff1f3eb8d80ef48bb801f6879b073748238f3..6934f4f944e041003d145e92719d9fc79b6259c2 100644 (file)
--- a/sig.c
+++ b/sig.c
@@ -1,6 +1,6 @@
 /* sig.c - interface for shell signal handlers and signal initialization. */
 
-/* Copyright (C) 1994-2015 Free Software Foundation, Inc.
+/* Copyright (C) 1994-2018 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -113,6 +113,7 @@ struct termsig {
      int signum;
      SigHandler *orig_handler;
      int orig_flags;
+     int core_dump;
 };
 
 #define NULL_HANDLER (SigHandler *)SIG_DFL
@@ -130,15 +131,15 @@ static struct termsig terminating_signals[] = {
 #endif
 
 #ifdef SIGILL
-{  SIGILL, NULL_HANDLER, 0 },
+{  SIGILL, NULL_HANDLER, 0, 1},
 #endif
 
 #ifdef SIGTRAP
-{  SIGTRAP, NULL_HANDLER, 0 },
+{  SIGTRAP, NULL_HANDLER, 0, 1 },
 #endif
 
 #ifdef SIGIOT
-{  SIGIOT, NULL_HANDLER, 0 },
+{  SIGIOT, NULL_HANDLER, 0, 1 },
 #endif
 
 #ifdef SIGDANGER
@@ -150,19 +151,19 @@ static struct termsig terminating_signals[] = {
 #endif
 
 #ifdef SIGFPE
-{  SIGFPE, NULL_HANDLER, 0 },
+{  SIGFPE, NULL_HANDLER, 0, 1 },
 #endif
 
 #ifdef SIGBUS
-{  SIGBUS, NULL_HANDLER, 0 },
+{  SIGBUS, NULL_HANDLER, 0, 1 },
 #endif
 
 #ifdef SIGSEGV
-{  SIGSEGV, NULL_HANDLER, 0 },
+{  SIGSEGV, NULL_HANDLER, 0, 1 },
 #endif
 
 #ifdef SIGSYS
-{  SIGSYS, NULL_HANDLER, 0 },
+{  SIGSYS, NULL_HANDLER, 0, 1 },
 #endif
 
 #ifdef SIGPIPE
@@ -177,12 +178,14 @@ static struct termsig terminating_signals[] = {
 {  SIGTERM, NULL_HANDLER, 0 },
 #endif
 
+/* These don't generate core dumps on anything but Linux, but we're doing
+   this just for Linux anyway. */
 #ifdef SIGXCPU
-{  SIGXCPU, NULL_HANDLER, 0 },
+{  SIGXCPU, NULL_HANDLER, 0, 1 },
 #endif
 
 #ifdef SIGXFSZ
-{  SIGXFSZ, NULL_HANDLER, 0 },
+{  SIGXFSZ, NULL_HANDLER, 0, 1 },
 #endif
 
 #ifdef SIGVTALRM
@@ -213,6 +216,7 @@ static struct termsig terminating_signals[] = {
 #define XSIG(x) (terminating_signals[x].signum)
 #define XHANDLER(x) (terminating_signals[x].orig_handler)
 #define XSAFLAGS(x) (terminating_signals[x].orig_flags)
+#define XCOREDUMP(x) (terminating_signals[x].core_dump)
 
 static int termsigs_initialized = 0;
 
@@ -360,7 +364,6 @@ reset_terminating_signals ()
 
   termsigs_initialized = 0;
 }
-#undef XSIG
 #undef XHANDLER
 
 /* Run some of the cleanups that should be performed when we run
@@ -542,6 +545,8 @@ termsig_handler (sig)
      int sig;
 {
   static int handling_termsig = 0;
+  int i, core;
+  sigset_t mask;
 
   /* Simple semaphore to keep this function from being executed multiple
      times.  Since we no longer are running as a signal handler, we don't
@@ -583,11 +588,39 @@ termsig_handler (sig)
   executing_list = comsub_ignore_return = return_catch_flag = wait_intr_flag = 0;
 
   run_exit_trap ();    /* XXX - run exit trap possibly in signal context? */
+
+  /* We don't change the set of blocked signals. If a user starts the shell
+     with a terminating signal blocked, we won't get here (and if by some
+     magic chance we do, we'll exit below). */
   set_signal_handler (sig, SIG_DFL);
+
   kill (getpid (), sig);
 
-  exit (1);            /* just in case the kill fails? */
+  if (dollar_dollar_pid != 1)
+    exit (128+sig);            /* just in case the kill fails? */
+
+  /* We are PID 1, and the kill above failed to kill the process. We assume
+     this means that we are running as an init process in a pid namespace
+     on Linux. In this case, we can't send ourselves a fatal signal, so we
+     determine whether or not we should have generated a core dump with the
+     kill call and attempt to trick the kernel into generating one if
+     necessary. */
+  sigprocmask (SIG_SETMASK, (sigset_t *)NULL, &mask);
+  for (i = core = 0; i < TERMSIGS_LENGTH; i++)
+    {
+      set_signal_handler (XSIG (i), SIG_DFL);
+      sigdelset (&mask, XSIG (i));
+      if (sig == XSIG (i))
+       core = XCOREDUMP (i);
+    }
+  sigprocmask (SIG_SETMASK, &mask, (sigset_t *)NULL);
+
+  if (core)
+    *((volatile unsigned long *) NULL) = 0xdead0000 + sig;     /* SIGSEGV */
+
+  exit (128+sig);
 }
+#undef XSIG
 
 /* What we really do when SIGINT occurs. */
 sighandler
index 554f3d6ecc09d7149b13daa2d36a6bab1480269f..58c375b70d886bcff86f789ae4a15eee397f87c8 100755 (executable)
@@ -1,4 +1,4 @@
-BUILD_DIR=/usr/local/build/bash/bash-current
+BUILD_DIR=/usr/local/build/chet/bash/bash-current
 THIS_SH=$BUILD_DIR/bash
 PATH=$PATH:$BUILD_DIR
 
index 0d10aba404f40be906b27fd5ffcb077f78817316..cf1dbb104d590e3612b4ef293221fa056897852d 100644 (file)
@@ -3,7 +3,7 @@ foo
 test2
 test3
 test4
-       8
+8
 test5
 test6
 test7
@@ -15,15 +15,15 @@ bye
 l8r
 ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 intern
-       1
-       0
-       0
-       0
-       0
+1
+0
+0
+0
+0
 extern
-       1
-       0
-       0
-       0
-       0
+1
+0
+0
+0
+0
 123
index cbd74b0034337e7cacdf923b670a6e45bb899027..4678ac6955a06273bd0223d92331440c5a82f3dd 100644 (file)
@@ -1,4 +1,5 @@
 # process substitution constructs that have caused problems in the past
+. ./test-glue-functions
 
 eval cat <(echo test1)
 eval "echo foo;cat" <(echo test2)
@@ -13,7 +14,7 @@ unset f
 
 FN=$TMPDIR/bashtest-procsub-$$
 cat >"$FN" <<EOF
-echo "test 12" | wc -c
+echo "test 12" | wc -c | _cut_leading_spaces
 cat "\$1"
 EOF
 
@@ -44,10 +45,8 @@ f2 <(echo l8r)
 
 unset -f f1 f2
 
-moo() { ls -l "$1" >/dev/null; ls -l "$1" >/dev/null; }; moo >(true)
-moo() { ls -al "$1" >/dev/null; (true); ls -al "$1" >/dev/null; }; moo >(true)
-
-unset -f moo
+# set up conditions for test
+ulimit -n 256
 
 bug()
 {
@@ -76,7 +75,7 @@ count_lines()
 }
 
 echo intern
-count_lines <(date)
+count_lines <(date) | _cut_leading_spaces
 unset -f count_lines
 
 echo extern
@@ -89,7 +88,12 @@ true | wc -l < \$1
 wc -l < \$1
 EOF
 
-${THIS_SH} -c "source $FN <(date)"
+${THIS_SH} -c "source $FN <(date)" | _cut_leading_spaces
 rm -f $FN
 
+moo() { ls -l "$1" >/dev/null; ls -l "$1" >/dev/null; }; moo >(true)
+moo() { ls -al "$1" >/dev/null; (true); ls -al "$1" >/dev/null; }; moo >(true)
+
+unset -f moo
+
 ${THIS_SH} ./procsub1.sub
index 2b2f61d0b09e4e4c7c03ab081a17e12f06517225..b958ab71c2e7bd73f2e118239c2280e508e8d8cb 100644 (file)
@@ -6,4 +6,8 @@ _intl_normalize_spaces()
        sed -e 's/[[:space:]]\{1,\}/ /g' -e 's/[[:space:]]*$//'
 }
 
-
+# avoid whitespace differences in wc implementations
+_cut_leading_spaces()
+{
+       sed -e 's/^[[:space:]]*//g'
+}
index c1eac7fbc5eb28c7d2b8b661fab01359c7b716ed..01301719586ea483006c869a749dfb7325c9ef75 100644 (file)
@@ -135,6 +135,7 @@ declare -a bar=([0]="zero" [1]="one")
 declare -A foo=([one]="one" [zero]="zero" )
 declare -a bar=([0]="zero" [1]="one")
 ./varenv11.sub: line 29: a: readonly variable
+foo=abc
 a=z
 a=b
 a=z
index 9d46b9a0e080d62d533ac12d479976f6e1338c5d..d08e337d82edef32c1c973bddac77321be101e16 100644 (file)
@@ -280,6 +280,7 @@ static SHELL_VAR *find_variable_nameref_context __P((SHELL_VAR *, VAR_CONTEXT *,
 static SHELL_VAR *find_variable_last_nameref_context __P((SHELL_VAR *, VAR_CONTEXT *, VAR_CONTEXT **));
 
 static SHELL_VAR *bind_tempenv_variable __P((const char *, char *));
+static void push_posix_temp_var __P((PTR_T));
 static void push_temp_var __P((PTR_T));
 static void propagate_temp_var __P((PTR_T));
 static void dispose_temporary_env __P((sh_free_func_t *));     
@@ -4243,8 +4244,46 @@ find_tempenv_variable (name)
 char **tempvar_list;
 int tvlist_ind;
 
+/* Take a variable from an assignment statement preceding a posix special
+   builtin (including `return') and create a global variable from it. This
+   is called from merge_temporary_env, which is only called when in posix
+   mode. */
+static void
+push_posix_temp_var (data)
+     PTR_T data;
+{
+  SHELL_VAR *var, *v;
+  HASH_TABLE *binding_table;
+
+  var = (SHELL_VAR *)data;
+
+  binding_table = global_variables->table;
+  if (binding_table == 0)
+    binding_table = global_variables->table = hash_create (VARIABLES_HASH_BUCKETS);
+
+  v = bind_variable_internal (var->name, value_cell (var), binding_table, 0, ASS_FORCE|ASS_NOLONGJMP);
+
+  /* global variables are no longer temporary and don't need propagating. */
+  var->attributes &= ~(att_tempvar|att_propagate);
+  if (v)
+    v->attributes |= var->attributes;
+
+  if (find_special_var (var->name) >= 0)
+    tempvar_list[tvlist_ind++] = savestring (var->name);
+
+  dispose_variable (var);
+}
+
 /* Push the variable described by (SHELL_VAR *)DATA down to the next
-   variable context from the temporary environment. */
+   variable context from the temporary environment. This can be called
+   from one context:
+      1. propagate_temp_var: which is called to propagate variables in
+        assignments like `var=value declare -x var' to the surrounding
+        scope.
+
+  In this case, the variable should have the att_propagate flag set and
+  we can create variables in the current scope.
+*/
 static void
 push_temp_var (data)
      PTR_T data;
@@ -4267,7 +4306,7 @@ push_temp_var (data)
   v = bind_variable_internal (var->name, value_cell (var), binding_table, 0, ASS_FORCE|ASS_NOLONGJMP);
 
   /* XXX - should we set the context here?  It shouldn't matter because of how
-     assign_in_env works, but might want to check. */
+     assign_in_env works, but we do it anyway. */
   if (v)
     v->context = shell_variables->scope;
 
@@ -4288,6 +4327,10 @@ push_temp_var (data)
   dispose_variable (var);
 }
 
+/* Take a variable described by DATA and push it to the surrounding scope if
+   the PROPAGATE attribute is set. That gets set by push_temp_var if we are
+   taking a variable like `var=value declare -x var' and propagating it to
+   the enclosing scope. */
 static void
 propagate_temp_var (data)
      PTR_T data;
@@ -4351,12 +4394,15 @@ dispose_used_env_vars ()
 }
 
 /* Take all of the shell variables in the temporary environment HASH_TABLE
-   and make shell variables from them at the current variable context. */
+   and make shell variables from them at the current variable context.
+   Right now, this is only called in Posix mode to implement the historical
+   accident of creating global variables from assignment statements preceding
+   special builtins, but we check in case this acquires another caller later. */
 void
 merge_temporary_env ()
 {
   if (temporary_env)
-    dispose_temporary_env (push_temp_var);
+    dispose_temporary_env (posixly_correct ? push_posix_temp_var : push_temp_var);
 }
 
 void
@@ -4859,6 +4905,16 @@ push_var_context (name, flags, tempvars)
   return (shell_variables = vc);
 }
 
+/* This can be called from one of two code paths:
+       1. pop_scope, which implements the posix rules for propagating variable
+          assignments preceding special builtins to the surrounding scope.
+       2. pop_var_context, which is called from pop_context and implements the
+          posix rules for propagating variable assignments preceding function
+          calls to the surrounding scope.
+
+  It takes variables out of a temporary environment hash table. We take the
+  variable in data
+*/
 static void
 push_func_var (data)
      PTR_T data;
@@ -4978,11 +5034,7 @@ push_exported_var (data)
      propagated, bind it in the previous scope before disposing it. */
   /* XXX - This isn't exactly right, because all tempenv variables have the
     export attribute set. */
-#if 0
-  if (exported_p (var) || (var->attributes & att_propagate))
-#else
   if (tempvar_p (var) && exported_p (var) && (var->attributes & att_propagate))
-#endif
     {
       var->attributes &= ~att_tempvar;         /* XXX */
       v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
@@ -5000,11 +5052,17 @@ push_exported_var (data)
   dispose_variable (var);
 }
 
+/* This is called to propagate variables in the temporary environment of a
+   special builtin (if IS_SPECIAL != 0) or exported variables that are the
+   result of a builtin like `source' or `command' that can operate on the
+   variables in its temporary environment. In the first case, we call
+   push_func_var, which does the right thing (for now) */
 void
 pop_scope (is_special)
      int is_special;
 {
   VAR_CONTEXT *vcxt, *ret;
+  int is_bltinenv;
 
   vcxt = shell_variables;
   if (vc_istempscope (vcxt) == 0)
@@ -5012,6 +5070,7 @@ pop_scope (is_special)
       internal_error (_("pop_scope: head of shell_variables not a temporary environment scope"));
       return;
     }
+  is_bltinenv = vc_isbltnenv (vcxt);   /* XXX - for later */
 
   ret = vcxt->down;
   if (ret)
index 50d4ccb2e86c0e9ac4c29f54cc6b57e2c4b887f1..bc1546d16f046f3934a7ea538ec473804ba02049 100644 (file)
@@ -157,6 +157,7 @@ typedef struct _vlist {
 #define regen_p(var)           ((((var)->attributes) & (att_regenerate)))
 
 #define tempvar_p(var)         ((((var)->attributes) & (att_tempvar)))
+#define propagate_p(var)       ((((var)->attributes) & (att_propagate)))
 
 /* Variable names: lvalues */
 #define name_cell(var)         ((var)->name)