]> git.ipfire.org Git - thirdparty/bash.git/blobdiff - builtins/evalstring.c
Imported from ../bash-3.2.48.tar.gz.
[thirdparty/bash.git] / builtins / evalstring.c
index 21e4772e1ff4f2d9637c1d0b659ecf00cac18a5e..511ce86c35ffe8a79f6635a99a13d56bb364f35a 100644 (file)
@@ -1,4 +1,6 @@
-/* Copyright (C) 1996 Free Software Foundation, Inc.
+/* Evaluate a string as one or more shell commands.
+
+   Copyright (C) 1996-2005 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -40,6 +42,7 @@
 #include "../input.h"
 #include "../execute_cmd.h"
 #include "../redir.h"
+#include "../trap.h"
 
 #if defined (HISTORY)
 #  include "../bashhist.h"
@@ -53,20 +56,24 @@ extern int errno;
 
 #define IS_BUILTIN(s)  (builtin_address_internal(s, 0) != (struct builtin *)NULL)
 
-extern void run_trap_cleanup ();
-extern int zwrite ();
-
-extern int interactive, interactive_shell;
-extern int indirection_level, startup_state, subshell_environment;
+extern int indirection_level, subshell_environment;
 extern int line_number;
 extern int last_command_exit_value;
 extern int running_trap;
+extern int loop_level;
 extern int posixly_correct;
-extern COMMAND *global_command;
 
 int parse_and_execute_level = 0;
 
-static int cat_file ();
+static int cat_file __P((REDIRECT *));
+
+#if defined (HISTORY)
+static void
+set_history_remembering ()
+{
+  remember_on_history = enable_history_list;
+}
+#endif
 
 /* How to force parse_and_execute () to clean up after itself. */
 void
@@ -87,15 +94,17 @@ parse_and_execute_cleanup ()
        (flags & SEVAL_NONINT) -> interactive = 0;
        (flags & SEVAL_INTERACT) -> interactive = 1;
        (flags & SEVAL_NOHIST) -> call bash_history_disable ()
+       (flags & SEVAL_NOFREE) -> don't free STRING when finished
+       (flags & SEVAL_RESETLINE) -> reset line_number to 1
 */
 
 int
 parse_and_execute (string, from_file, flags)
      char *string;
-     char *from_file;
+     const char *from_file;
      int flags;
 {
-  int code, x;
+  int code, x, lreset;
   volatile int should_jump_to_top_level, last_result;
   char *orig_string;
   COMMAND *volatile command;
@@ -107,11 +116,17 @@ parse_and_execute (string, from_file, flags)
   unwind_protect_jmp_buf (top_level);
   unwind_protect_int (indirection_level);
   unwind_protect_int (line_number);
+  unwind_protect_int (loop_level);
   if (flags & (SEVAL_NONINT|SEVAL_INTERACT))
     unwind_protect_int (interactive);
 
+  lreset = flags & SEVAL_RESETLINE;
+
 #if defined (HISTORY)
-  unwind_protect_int (remember_on_history);    /* can be used in scripts */
+  if (parse_and_execute_level == 0)
+    add_unwind_protect (set_history_remembering, (char *)NULL);
+  else
+    unwind_protect_int (remember_on_history);  /* can be used in scripts */
 #  if defined (BANG_HISTORY)
   if (interactive_shell)
     {
@@ -127,12 +142,20 @@ parse_and_execute (string, from_file, flags)
     }
   
   add_unwind_protect (pop_stream, (char *)NULL);
-  if (orig_string)
+  if (orig_string && ((flags & SEVAL_NOFREE) == 0))
     add_unwind_protect (xfree, orig_string);
   end_unwind_frame ();
 
   parse_and_execute_level++;
-  push_stream (1);     /* reset the line number */
+
+  /* Reset the line number if the caller wants us to.  If we don't reset the
+     line number, we have to subtract one, because we will add one just
+     before executing the next command (resetting the line number sets it to
+     0; the first line number is 1). */
+  push_stream (lreset);
+  if (lreset == 0)
+    line_number--;
+    
   indirection_level++;
   if (flags & (SEVAL_NONINT|SEVAL_INTERACT))
     interactive = (flags & SEVAL_NONINT) ? 0 : 1;
@@ -144,11 +167,12 @@ parse_and_execute (string, from_file, flags)
 
   code = should_jump_to_top_level = 0;
   last_result = EXECUTION_SUCCESS;
-  command = (COMMAND *)NULL;
 
   with_input_from_string (string, from_file);
   while (*(bash_input.location.string))
     {
+      command = (COMMAND *)NULL;
+
       if (interrupt_state)
        {
          last_result = EXECUTION_FAILURE;
@@ -166,15 +190,18 @@ parse_and_execute (string, from_file, flags)
          switch (code)
            {
            case FORCE_EOF:
+           case ERREXIT:
            case EXITPROG:
-             run_unwind_frame ("pe_dispose");
+             if (command)
+               run_unwind_frame ("pe_dispose");
              /* Remember to call longjmp (top_level) after the old
                 value for it is restored. */
              should_jump_to_top_level = 1;
              goto out;
 
            case DISCARD:
-             run_unwind_frame ("pe_dispose");
+             if (command)
+               run_unwind_frame ("pe_dispose");
              last_result = last_command_exit_value = EXECUTION_FAILURE; /* XXX */
              if (subshell_environment)
                {
@@ -219,17 +246,23 @@ parse_and_execute (string, from_file, flags)
               * IF
               *   we were invoked as `bash -c' (startup_state == 2) AND
               *   parse_and_execute has not been called recursively AND
+              *   we're not running a trap AND
               *   we have parsed the full command (string == '\0') AND
+              *   we're not going to run the exit trap AND
               *   we have a simple command without redirections AND
-              *   the command is not being timed
+              *   the command is not being timed AND
+              *   the command's return status is not being inverted
               * THEN
               *   tell the execution code that we don't need to fork
               */
              if (startup_state == 2 && parse_and_execute_level == 1 &&
+                 running_trap == 0 &&
                  *bash_input.location.string == '\0' &&
                  command->type == cm_simple &&
-                 !command->redirects && !command->value.Simple->redirects &&
-                 ((command->flags & CMD_TIME_PIPELINE) == 0))
+                 signal_is_trapped (EXIT_TRAP) == 0 &&
+                 command->redirects == 0 && command->value.Simple->redirects == 0 &&
+                 ((command->flags & CMD_TIME_PIPELINE) == 0) &&
+                 ((command->flags & CMD_INVERT_RETURN) == 0))
                {
                  command->flags |= CMD_NO_FORK;
                  command->value.Simple->flags |= CMD_NO_FORK;
@@ -296,8 +329,8 @@ static int
 cat_file (r)
      REDIRECT *r;
 {
-  char lbuf[128], *fn;
-  int nr, fd, rval;
+  char *fn;
+  int fd, rval;
 
   if (r->instruction != r_input_direction)
     return -1;
@@ -323,26 +356,10 @@ cat_file (r)
       return -1;
     }
 
-  rval = 0;
-  while (1)
-    {
-      nr = zread (fd, lbuf, sizeof(lbuf));
-      if (nr == 0)
-       break;
-      else if (nr < 0)
-       {
-         rval = -1;
-         break;
-       }
-      if (zwrite (1, lbuf, nr) < 0)
-       {
-         rval = -1;
-         break;
-       }
-    }
+  rval = zcatfd (fd, 1, fn);
 
   free (fn);
   close (fd);
 
-  return (0);  
+  return (rval);
 }