Bash-4.3 patch 12
[platform/upstream/bash.git] / eval.c
diff --git a/eval.c b/eval.c
index 3ca5141..1f65aac 100644 (file)
--- a/eval.c
+++ b/eval.c
@@ -1,24 +1,22 @@
-/* eval.c -- reading and evaluating commands.
+/* eval.c -- reading and evaluating commands. */
 
-   Copyright (C) 1996 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2011 Free Software Foundation, Inc.
 
-   This file is part of GNU Bash.
+   This file is part of GNU Bash, the Bourne Again SHell.
 
-   Bash is distributed in the hope that it will be useful, but WITHOUT
-   ANY WARRANTY.  No author or distributor accepts responsibility to
-   anyone for the consequences of using it or for whether it serves
-   any particular purpose or works at all, unless he says so in
-   writing.  Refer to the GNU Emacs General Public License for full
-   details.
+   Bash is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
 
-   Everyone is granted permission to copy, modify and redistribute
-   Bash, but only under the conditions described in the GNU General
-   Public License.  A copy of this license is supposed to have been
-   given to you along with GNU Emacs so you can know your rights and
-   responsibilities.  It should be in a file named COPYING.
+   Bash is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-   Among other things, the copyright notice and this notice must be
-   preserved on all copies. */
+   You should have received a copy of the GNU General Public License
+   along with Bash.  If not, see <http://www.gnu.org/licenses/>.
+*/
 
 #include "config.h"
 
@@ -32,6 +30,8 @@
 #include "bashansi.h"
 #include <stdio.h>
 
+#include "bashintl.h"
+
 #include "shell.h"
 #include "flags.h"
 #include "trap.h"
 #  include "bashhist.h"
 #endif
 
-extern int yyparse ();
-
 extern int EOF_reached;
-extern int indirection_level, interactive, interactive_shell;
+extern int indirection_level;
+extern int posixly_correct;
 extern int subshell_environment, running_under_emacs;
 extern int last_command_exit_value, stdin_redir;
 extern int need_here_doc;
 extern int current_command_number, current_command_line_count, line_number;
-extern char *ps1_prompt, **prompt_string_pointer;
 extern int expand_aliases;
 
+#if defined (HAVE_POSIX_SIGNALS)
+extern sigset_t top_level_mask;
+#endif
+
+static void send_pwd_to_eterm __P((void));
+static sighandler alrm_catcher __P((int));
+
 /* Read and execute commands until EOF is reached.  This assumes that
    the input source has already been initialized. */
 int
 reader_loop ()
 {
   int our_indirection_level;
-  COMMAND *current_command = (COMMAND *)NULL;
+  COMMAND * volatile current_command;
+
+  USE_VAR(current_command);
+
+  current_command = (COMMAND *)NULL;
 
   our_indirection_level = ++indirection_level;
 
@@ -70,12 +79,13 @@ reader_loop ()
     {
       int code;
 
-      code = setjmp (top_level);
+      code = setjmp_nosigs (top_level);
 
 #if defined (PROCESS_SUBSTITUTION)
       unlink_fifo_list ();
 #endif /* PROCESS_SUBSTITUTION */
 
+      /* XXX - why do we set this every time through the loop? */
       if (interactive_shell && signal_is_ignored (SIGINT) == 0)
        set_signal_handler (SIGINT, sigint_sighandler);
 
@@ -85,15 +95,22 @@ reader_loop ()
 
          switch (code)
            {
-             /* Some kind of throw to top_level has occured. */
+             /* Some kind of throw to top_level has occurred. */
            case FORCE_EOF:
+           case ERREXIT:
            case EXITPROG:
              current_command = (COMMAND *)NULL;
+             if (exit_immediately_on_error)
+               variable_context = 0;   /* not in a function */
              EOF_Reached = EOF;
              goto exec_done;
 
            case DISCARD:
-             last_command_exit_value = 1;
+             /* Make sure the exit status is reset to a non-zero value, but
+                leave existing non-zero values (e.g., > 128 on signal)
+                alone. */
+             if (last_command_exit_value == 0)
+               last_command_exit_value = EXECUTION_FAILURE;
              if (subshell_environment)
                {
                  current_command = (COMMAND *)NULL;
@@ -106,6 +123,9 @@ reader_loop ()
                  dispose_command (current_command);
                  current_command = (COMMAND *)NULL;
                }
+#if defined (HAVE_POSIX_SIGNALS)
+             sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
+#endif
              break;
 
            default:
@@ -114,7 +134,8 @@ reader_loop ()
        }
 
       executing = 0;
-      dispose_used_env_vars ();
+      if (temporary_env)
+       dispose_used_env_vars ();
 
 #if (defined (ultrix) && defined (mips)) || defined (C_ALLOCA)
       /* Attempt to reclaim memory allocated with alloca (). */
@@ -139,13 +160,13 @@ reader_loop ()
              execute_command (current_command);
 
            exec_done:
+             QUIT;
+
              if (current_command)
-               {
+               {
                  dispose_command (current_command);
                  current_command = (COMMAND *)NULL;
-               }
-
-             QUIT;
+               }
            }
        }
       else
@@ -165,7 +186,9 @@ static sighandler
 alrm_catcher(i)
      int i;
 {
-  printf ("\007timed out waiting for input: auto-logout\n");
+  printf (_("\007timed out waiting for input: auto-logout\n"));
+  fflush (stdout);
+  bash_logout ();      /* run ~/.bash_logout if this is a login shell */
   jump_to_top_level (EXITPROG);
   SIGRETURN (0);
 }
@@ -175,12 +198,14 @@ alrm_catcher(i)
 static void
 send_pwd_to_eterm ()
 {
-  char *pwd;
+  char *pwd, *f;
 
+  f = 0;
   pwd = get_string_value ("PWD");
   if (pwd == 0)
-    pwd = get_working_directory ("eterm");
+    f = pwd = get_working_directory ("eterm");
   fprintf (stderr, "\032/%s\n", pwd);
+  free (f);
 }
 
 /* Call the YACC-generated parser and return the status of the parse.
@@ -203,7 +228,7 @@ parse_command ()
     {
       command_to_execute = get_string_value ("PROMPT_COMMAND");
       if (command_to_execute)
-       execute_prompt_command (command_to_execute);
+       execute_variable_command (command_to_execute, "PROMPT_COMMAND");
 
       if (running_under_emacs == 2)
        send_pwd_to_eterm ();   /* Yuck */
@@ -228,21 +253,21 @@ read_command ()
   int tmout_len, result;
   SigHandler *old_alrm;
 
-  prompt_string_pointer = &ps1_prompt;
+  set_current_prompt_level (1);
   global_command = (COMMAND *)NULL;
 
   /* Only do timeouts if interactive. */
   tmout_var = (SHELL_VAR *)NULL;
   tmout_len = 0;
+  old_alrm = (SigHandler *)NULL;
 
   if (interactive)
     {
       tmout_var = find_variable ("TMOUT");
-      old_alrm = (SigHandler *)NULL;
 
-      if (tmout_var && tmout_var->value)
+      if (tmout_var && var_isset (tmout_var))
        {
-         tmout_len = atoi (tmout_var->value);
+         tmout_len = atoi (value_cell (tmout_var));
          if (tmout_len > 0)
            {
              old_alrm = set_signal_handler (SIGALRM, alrm_catcher);
@@ -264,56 +289,3 @@ read_command ()
 
   return (result);
 }
-
-/* Take a string and run it through the shell parser, returning the
-   resultant word list.  Used by compound array assignment. */
-WORD_LIST *
-parse_string_to_word_list (s, whom)
-     char *s, *whom;
-{
-  WORD_LIST *wl;
-  COMMAND *saved_global;
-#if defined (HISTORY)
-  int old_remember_on_history, old_history_expansion_inhibited;
-#endif
-
-#if defined (HISTORY)
-  old_remember_on_history = remember_on_history;
-#  if defined (BANG_HISTORY)
-  old_history_expansion_inhibited = history_expansion_inhibited;
-#  endif
-  bash_history_disable ();
-#endif
-
-  push_stream (1);
-
-  saved_global = global_command;
-  global_command = (COMMAND *)0;
-
-  with_input_from_string (s, whom);
-  if (parse_command () != 0 || global_command == 0 || global_command->type != cm_simple)
-    {
-      if (global_command)
-       dispose_command (global_command);
-      wl = (WORD_LIST *)NULL;
-    }
-  else
-    {
-      wl = global_command->value.Simple->words;
-      free (global_command->value.Simple);
-      free (global_command);
-    }
-
-  global_command = saved_global;
-
-  pop_stream ();
-
-#if defined (HISTORY)
-  remember_on_history = old_remember_on_history;
-#  if defined (BANG_HISTORY)
-  history_expansion_inhibited = old_history_expansion_inhibited;
-#  endif /* BANG_HISTORY */
-#endif /* HISTORY */
-
-  return (wl);
-}