| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | /* Evaluate a string as one or more shell commands.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    Copyright (C) 1996-2005 Free Software Foundation, Inc. | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    This file is part of GNU Bash, the Bourne Again SHell. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    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 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |    Software Foundation; either version 2, or (at your option) any later | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |    version. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    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. | 
					
						
							|  |  |  |     | 
					
						
							|  |  |  |    You should have received a copy of the GNU General Public License along | 
					
						
							|  |  |  |    with Bash; see the file COPYING.  If not, write to the Free Software | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |    Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <config.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (HAVE_UNISTD_H)
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #  ifdef _MINIX
 | 
					
						
							|  |  |  | #    include <sys/types.h>
 | 
					
						
							|  |  |  | #  endif
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #  include <unistd.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <signal.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #include <errno.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #include "filecntl.h"
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #include "../bashansi.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "../shell.h"
 | 
					
						
							|  |  |  | #include "../jobs.h"
 | 
					
						
							|  |  |  | #include "../builtins.h"
 | 
					
						
							|  |  |  | #include "../flags.h"
 | 
					
						
							|  |  |  | #include "../input.h"
 | 
					
						
							|  |  |  | #include "../execute_cmd.h"
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #include "../redir.h"
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #include "../trap.h"
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if defined (HISTORY)
 | 
					
						
							|  |  |  | #  include "../bashhist.h"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "common.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #if !defined (errno)
 | 
					
						
							|  |  |  | extern int errno; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | #define IS_BUILTIN(s)	(builtin_address_internal(s, 0) != (struct builtin *)NULL)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | extern int indirection_level, startup_state, subshell_environment; | 
					
						
							|  |  |  | extern int line_number; | 
					
						
							|  |  |  | extern int last_command_exit_value; | 
					
						
							|  |  |  | extern int running_trap; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | extern int loop_level; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | extern int posixly_correct; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | int parse_and_execute_level = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | static int cat_file __P((REDIRECT *)); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* How to force parse_and_execute () to clean up after itself. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | parse_and_execute_cleanup () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (running_trap) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       run_trap_cleanup (running_trap - 1); | 
					
						
							|  |  |  |       unfreeze_jobs_list (); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   run_unwind_frame ("parse_and_execute_top"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Parse and execute the commands in STRING.  Returns whatever
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |    execute_command () returns.  This frees STRING.  FLAGS is a | 
					
						
							|  |  |  |    flags word; look in common.h for the possible values.  Actions | 
					
						
							|  |  |  |    are: | 
					
						
							|  |  |  |    	(flags & SEVAL_NONINT) -> interactive = 0; | 
					
						
							|  |  |  |    	(flags & SEVAL_INTERACT) -> interactive = 1; | 
					
						
							|  |  |  |    	(flags & SEVAL_NOHIST) -> call bash_history_disable () | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |    	(flags & SEVAL_NOFREE) -> don't free STRING when finished | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |    	(flags & SEVAL_RESETLINE) -> reset line_number to 1 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | parse_and_execute (string, from_file, flags) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |      char *string; | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |      const char *from_file; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |      int flags; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   int code, x, lreset; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   volatile int should_jump_to_top_level, last_result; | 
					
						
							|  |  |  |   char *orig_string; | 
					
						
							|  |  |  |   COMMAND *volatile command; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   orig_string = string; | 
					
						
							|  |  |  |   /* Unwind protect this invocation of parse_and_execute (). */ | 
					
						
							|  |  |  |   begin_unwind_frame ("parse_and_execute_top"); | 
					
						
							|  |  |  |   unwind_protect_int (parse_and_execute_level); | 
					
						
							|  |  |  |   unwind_protect_jmp_buf (top_level); | 
					
						
							|  |  |  |   unwind_protect_int (indirection_level); | 
					
						
							|  |  |  |   unwind_protect_int (line_number); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   unwind_protect_int (loop_level); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   if (flags & (SEVAL_NONINT|SEVAL_INTERACT)) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     unwind_protect_int (interactive); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   lreset = flags & SEVAL_RESETLINE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (HISTORY)
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   unwind_protect_int (remember_on_history);	/* can be used in scripts */ | 
					
						
							|  |  |  | #  if defined (BANG_HISTORY)
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (interactive_shell) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       unwind_protect_int (history_expansion_inhibited); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | #  endif /* BANG_HISTORY */
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #endif /* HISTORY */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   if (interactive_shell) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       x = get_current_prompt_level (); | 
					
						
							|  |  |  |       add_unwind_protect (set_current_prompt_level, x); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |    | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   add_unwind_protect (pop_stream, (char *)NULL); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   if (orig_string && ((flags & SEVAL_NOFREE) == 0)) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     add_unwind_protect (xfree, orig_string); | 
					
						
							|  |  |  |   end_unwind_frame (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   parse_and_execute_level++; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* 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--; | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   indirection_level++; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   if (flags & (SEVAL_NONINT|SEVAL_INTERACT)) | 
					
						
							|  |  |  |     interactive = (flags & SEVAL_NONINT) ? 0 : 1; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if defined (HISTORY)
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   if (flags & SEVAL_NOHIST) | 
					
						
							|  |  |  |     bash_history_disable (); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #endif /* HISTORY */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   code = should_jump_to_top_level = 0; | 
					
						
							|  |  |  |   last_result = EXECUTION_SUCCESS; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   with_input_from_string (string, from_file); | 
					
						
							|  |  |  |   while (*(bash_input.location.string)) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       command = (COMMAND *)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       if (interrupt_state) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  last_result = EXECUTION_FAILURE; | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* Provide a location for functions which `longjmp (top_level)' to
 | 
					
						
							|  |  |  | 	 jump to.  This prevents errors in substitution from restarting | 
					
						
							|  |  |  | 	 the reader loop directly, for example. */ | 
					
						
							|  |  |  |       code = setjmp (top_level); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (code) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  should_jump_to_top_level = 0; | 
					
						
							|  |  |  | 	  switch (code) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	    case FORCE_EOF: | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	    case ERREXIT: | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	    case EXITPROG: | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	      if (command) | 
					
						
							|  |  |  | 		run_unwind_frame ("pe_dispose"); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	      /* Remember to call longjmp (top_level) after the old
 | 
					
						
							|  |  |  | 		 value for it is restored. */ | 
					
						
							|  |  |  | 	      should_jump_to_top_level = 1; | 
					
						
							|  |  |  | 	      goto out; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    case DISCARD: | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	      if (command) | 
					
						
							|  |  |  | 		run_unwind_frame ("pe_dispose"); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	      last_result = last_command_exit_value = EXECUTION_FAILURE; /* XXX */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	      if (subshell_environment) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  should_jump_to_top_level = 1; | 
					
						
							|  |  |  | 		  goto out; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	      else | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											1997-09-22 20:22:27 +00:00
										 |  |  | #if 0
 | 
					
						
							|  |  |  | 		  dispose_command (command);	/* pe_dispose does this */ | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 		  continue; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    default: | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | 	      command_error ("parse_and_execute", CMDERR_BADJUMP, code, 0); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	      break; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	   | 
					
						
							|  |  |  |       if (parse_command () == 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  if (interactive_shell == 0 && read_but_dont_execute) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      last_result = EXECUTION_SUCCESS; | 
					
						
							|  |  |  | 	      dispose_command (global_command); | 
					
						
							|  |  |  | 	      global_command = (COMMAND *)NULL; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  else if (command = global_command) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      struct fd_bitmap *bitmap; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	      bitmap = new_fd_bitmap (FD_BITMAP_SIZE); | 
					
						
							|  |  |  | 	      begin_unwind_frame ("pe_dispose"); | 
					
						
							|  |  |  | 	      add_unwind_protect (dispose_fd_bitmap, bitmap); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 	      add_unwind_protect (dispose_command, command);	/* XXX */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	      global_command = (COMMAND *)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (ONESHOT)
 | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | 	      /*
 | 
					
						
							|  |  |  | 	       * IF | 
					
						
							|  |  |  | 	       *   we were invoked as `bash -c' (startup_state == 2) AND | 
					
						
							|  |  |  | 	       *   parse_and_execute has not been called recursively AND | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 	       *   we're not running a trap AND | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | 	       *   we have parsed the full command (string == '\0') AND | 
					
						
							|  |  |  | 	       *   we have a simple command without redirections AND | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 	       *   the command is not being timed AND | 
					
						
							|  |  |  | 	       *   the command's return status is not being inverted | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | 	       * THEN | 
					
						
							|  |  |  | 	       *   tell the execution code that we don't need to fork | 
					
						
							|  |  |  | 	       */ | 
					
						
							|  |  |  | 	      if (startup_state == 2 && parse_and_execute_level == 1 && | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 		  running_trap == 0 && | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | 		  *bash_input.location.string == '\0' && | 
					
						
							|  |  |  | 		  command->type == cm_simple && | 
					
						
							|  |  |  | 		  !command->redirects && !command->value.Simple->redirects && | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 		  ((command->flags & CMD_TIME_PIPELINE) == 0) && | 
					
						
							|  |  |  | 		  ((command->flags & CMD_INVERT_RETURN) == 0)) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 		  command->flags |= CMD_NO_FORK; | 
					
						
							|  |  |  | 		  command->value.Simple->flags |= CMD_NO_FORK; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | #endif /* ONESHOT */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	      /* See if this is a candidate for $( <file ). */ | 
					
						
							|  |  |  | 	      if (startup_state == 2 && | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 		  (subshell_environment & SUBSHELL_COMSUB) && | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 		  *bash_input.location.string == '\0' && | 
					
						
							|  |  |  | 		  command->type == cm_simple && !command->redirects && | 
					
						
							|  |  |  | 		  (command->flags & CMD_TIME_PIPELINE) == 0 && | 
					
						
							|  |  |  | 		  command->value.Simple->words == 0 && | 
					
						
							|  |  |  | 		  command->value.Simple->redirects && | 
					
						
							|  |  |  | 		  command->value.Simple->redirects->next == 0 && | 
					
						
							|  |  |  | 		  command->value.Simple->redirects->instruction == r_input_direction) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  int r; | 
					
						
							|  |  |  | 		  r = cat_file (command->value.Simple->redirects); | 
					
						
							|  |  |  | 		  last_result = (r < 0) ? EXECUTION_FAILURE : EXECUTION_SUCCESS; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	      else | 
					
						
							|  |  |  | 		last_result = execute_command_internal | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 				(command, 0, NO_PIPE, NO_PIPE, bitmap); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	      dispose_command (command); | 
					
						
							|  |  |  | 	      dispose_fd_bitmap (bitmap); | 
					
						
							|  |  |  | 	      discard_unwind_frame ("pe_dispose"); | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  last_result = EXECUTION_FAILURE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  /* Since we are shell compatible, syntax errors in a script
 | 
					
						
							|  |  |  | 	     abort the execution of the script.  Right? */ | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  out: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   run_unwind_frame ("parse_and_execute_top"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (interrupt_state && parse_and_execute_level == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       /* An interrupt during non-interactive execution in an
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	 interactive shell (e.g. via $PROMPT_COMMAND) should | 
					
						
							|  |  |  | 	 not cause the shell to exit. */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       interactive = interactive_shell; | 
					
						
							|  |  |  |       throw_to_top_level (); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (should_jump_to_top_level) | 
					
						
							|  |  |  |     jump_to_top_level (code); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (last_result); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Handle a $( < file ) command substitution.  This expands the filename,
 | 
					
						
							|  |  |  |    returning errors as appropriate, then just cats the file to the standard | 
					
						
							|  |  |  |    output. */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | cat_file (r) | 
					
						
							|  |  |  |      REDIRECT *r; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char lbuf[128], *fn; | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   int fd, rval; | 
					
						
							|  |  |  |   ssize_t nr; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (r->instruction != r_input_direction) | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Get the filename. */ | 
					
						
							|  |  |  |   if (posixly_correct && !interactive_shell) | 
					
						
							|  |  |  |     disallow_filename_globbing++; | 
					
						
							|  |  |  |   fn = redirection_expand (r->redirectee.filename); | 
					
						
							|  |  |  |   if (posixly_correct && !interactive_shell) | 
					
						
							|  |  |  |     disallow_filename_globbing--; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (fn == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       redirection_error (r, AMBIGUOUS_REDIRECT); | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   fd = open(fn, O_RDONLY); | 
					
						
							|  |  |  |   if (fd < 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       file_error (fn); | 
					
						
							|  |  |  |       free (fn); | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   rval = zcatfd (fd, 1, fn); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   free (fn); | 
					
						
							|  |  |  |   close (fd); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   return (rval); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | } |