| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | This file is exec.def, from which is created exec.c. | 
					
						
							|  |  |  | It implements the builtin "exec" in Bash. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  | Copyright (C) 1987-2015 Free Software Foundation, Inc. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | This file is part of GNU Bash, the Bourne Again SHell. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 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. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 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. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  | along with Bash.  If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | $PRODUCES exec.c | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | $BUILTIN exec | 
					
						
							|  |  |  | $FUNCTION exec_builtin | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | $SHORT_DOC exec [-cl] [-a name] [command [arguments ...]] [redirection ...] | 
					
						
							|  |  |  | Replace the shell with the given command. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Execute COMMAND, replacing this shell with the specified program. | 
					
						
							|  |  |  | ARGUMENTS become the arguments to COMMAND.  If COMMAND is not specified, | 
					
						
							|  |  |  | any redirections take effect in the current shell. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Options: | 
					
						
							|  |  |  |   -a name	pass NAME as the zeroth argument to COMMAND | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  |   -c	execute COMMAND with an empty environment | 
					
						
							|  |  |  |   -l	place a dash in the zeroth argument to COMMAND | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | If the command cannot be executed, a non-interactive shell exits, unless | 
					
						
							|  |  |  | the shell option `execfail' is set. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Exit Status: | 
					
						
							|  |  |  | Returns success unless COMMAND is not found or a redirection error occurs. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | $END | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #include <config.h> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | #include "../bashtypes.h" | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #include "posixstat.h" | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #include <signal.h> | 
					
						
							|  |  |  | #include <errno.h> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (HAVE_UNISTD_H) | 
					
						
							|  |  |  | #  include <unistd.h> | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "../bashansi.h" | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #include "../bashintl.h" | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "../shell.h" | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #include "../execute_cmd.h" | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #include "../findcmd.h" | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (JOB_CONTROL) | 
					
						
							|  |  |  | #  include "../jobs.h" | 
					
						
							|  |  |  | #endif | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #include "../flags.h" | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #include "../trap.h" | 
					
						
							|  |  |  | #if defined (HISTORY) | 
					
						
							|  |  |  | #  include "../bashhist.h" | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | #include "common.h" | 
					
						
							|  |  |  | #include "bashgetopt.h" | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Not all systems declare ERRNO in errno.h... and some systems #define it! */ | 
					
						
							|  |  |  | #if !defined (errno) | 
					
						
							|  |  |  | extern int errno; | 
					
						
							|  |  |  | #endif /* !errno */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | extern int subshell_environment; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | extern REDIRECT *redirection_undo_list; | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | extern char *exec_argv0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | int no_exit_on_failed_exec; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* If the user wants this to look like a login shell, then | 
					
						
							|  |  |  |    prepend a `-' onto NAME and return the new name. */ | 
					
						
							|  |  |  | static char * | 
					
						
							|  |  |  | mkdashname (name) | 
					
						
							|  |  |  |      char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   ret = (char *)xmalloc (2 + strlen (name)); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   ret[0] = '-'; | 
					
						
							|  |  |  |   strcpy (ret + 1, name); | 
					
						
							|  |  |  |   return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | int | 
					
						
							|  |  |  | exec_builtin (list) | 
					
						
							|  |  |  |      WORD_LIST *list; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int exit_value = EXECUTION_FAILURE; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   int cleanenv, login, opt; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   char *argv0, *command, **args, **env, *newname, *com2; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   cleanenv = login = 0; | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   exec_argv0 = argv0 = (char *)NULL; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   reset_internal_getopt (); | 
					
						
							|  |  |  |   while ((opt = internal_getopt (list, "cla:")) != -1) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       switch (opt) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	case 'c': | 
					
						
							|  |  |  | 	  cleanenv = 1; | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	case 'l': | 
					
						
							|  |  |  | 	  login = 1; | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	case 'a': | 
					
						
							|  |  |  | 	  argv0 = list_optarg; | 
					
						
							|  |  |  | 	  break; | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  | 	CASE_HELPOPT; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	default: | 
					
						
							|  |  |  | 	  builtin_usage (); | 
					
						
							|  |  |  | 	  return (EX_USAGE); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   list = loptend; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* First, let the redirections remain. */ | 
					
						
							|  |  |  |   dispose_redirects (redirection_undo_list); | 
					
						
							|  |  |  |   redirection_undo_list = (REDIRECT *)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (list == 0) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     return (EXECUTION_SUCCESS); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if defined (RESTRICTED_SHELL) | 
					
						
							|  |  |  |   if (restricted) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       sh_restricted ((char *)NULL); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       return (EXECUTION_FAILURE); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif /* RESTRICTED_SHELL */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   args = strvec_from_word_list (list, 1, 0, (int *)NULL); | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  |   env = (char **)0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   /* A command with a slash anywhere in its name is not looked up in $PATH. */ | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   command = absolute_program (args[0]) ? args[0] : search_for_command (args[0], 1); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (command == 0) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |       if (file_isdir (args[0])) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | #if defined (EISDIR) | 
					
						
							|  |  |  | 	  builtin_error (_("%s: cannot execute: %s"), args[0], strerror (EISDIR)); | 
					
						
							|  |  |  | #else | 
					
						
							|  |  |  | 	  builtin_error (_("%s: cannot execute: %s"), args[0], strerror (errno)); | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 	  exit_value = EX_NOEXEC; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  sh_notfound (args[0]); | 
					
						
							|  |  |  | 	  exit_value = EX_NOTFOUND;	/* As per Posix.2, 3.14.6 */ | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       goto failed_exec; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   com2 = full_pathname (command); | 
					
						
							|  |  |  |   if (com2) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (command != args[0]) | 
					
						
							|  |  |  | 	free (command); | 
					
						
							|  |  |  |       command = com2; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (argv0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       free (args[0]); | 
					
						
							|  |  |  |       args[0] = login ? mkdashname (argv0) : savestring (argv0); | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |       exec_argv0 = savestring (args[0]); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   else if (login) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       newname = mkdashname (args[0]); | 
					
						
							|  |  |  |       free (args[0]); | 
					
						
							|  |  |  |       args[0] = newname; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   /* Decrement SHLVL by 1 so a new shell started here has the same value, | 
					
						
							|  |  |  |      preserving the appearance.  After we do that, we need to change the | 
					
						
							|  |  |  |      exported environment to include the new value. */ | 
					
						
							|  |  |  |   if (cleanenv == 0) | 
					
						
							|  |  |  |     adjust_shell_level (-1); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (cleanenv) | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  |     { | 
					
						
							|  |  |  |       env = strvec_create (1); | 
					
						
							|  |  |  |       env[0] = (char *)0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   else | 
					
						
							|  |  |  |     {	 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       maybe_make_export_env (); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       env = export_env; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if defined (HISTORY) | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   if (interactive_shell && subshell_environment == 0) | 
					
						
							|  |  |  |     maybe_save_shell_history (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #endif /* HISTORY */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   restore_original_signals (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if defined (JOB_CONTROL) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (subshell_environment == 0) | 
					
						
							|  |  |  |     end_job_control (); | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  |   if (interactive || job_control) | 
					
						
							|  |  |  |     default_tty_job_signals ();		/* undo initialize_job_signals */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #endif /* JOB_CONTROL */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   exit_value = shell_execve (command, args, env); | 
					
						
							| 
									
										
										
										
											1998-07-23 14:37:54 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* We have to set this to NULL because shell_execve has called realloc() | 
					
						
							|  |  |  |      to stuff more items at the front of the array, which may have caused | 
					
						
							|  |  |  |      the memory to be freed by realloc().  We don't want to free it twice. */ | 
					
						
							|  |  |  |   args = (char **)NULL; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (cleanenv == 0) | 
					
						
							|  |  |  |     adjust_shell_level (1); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   if (exit_value == EX_NOTFOUND)	/* no duplicate error message */ | 
					
						
							|  |  |  |     goto failed_exec; | 
					
						
							|  |  |  |   else if (executable_file (command) == 0) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       builtin_error (_("%s: cannot execute: %s"), command, strerror (errno)); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       exit_value = EX_NOEXEC;	/* As per Posix.2, 3.14.6 */ | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     file_error (command); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | failed_exec: | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   FREE (command); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0)) | 
					
						
							|  |  |  |     exit_shell (exit_value); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   if (args) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |     strvec_dispose (args); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-15 16:59:08 -04:00
										 |  |  |   if (env && env != export_env) | 
					
						
							|  |  |  |     strvec_dispose (env); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   initialize_traps (); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   initialize_signals (1); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if defined (JOB_CONTROL) | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   if (interactive_shell || job_control) | 
					
						
							|  |  |  |     restart_job_control (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #endif /* JOB_CONTROL */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   return (exit_value); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } |