Bash-4.3 distribution sources and documentation
[platform/upstream/bash.git] / builtins / exec.def
1 This file is exec.def, from which is created exec.c.
2 It implements the builtin "exec" in Bash.
3
4 Copyright (C) 1987-2012 Free Software Foundation, Inc.
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
8 Bash is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 Bash is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Bash.  If not, see <http://www.gnu.org/licenses/>.
20
21 $PRODUCES exec.c
22
23 $BUILTIN exec
24 $FUNCTION exec_builtin
25 $SHORT_DOC exec [-cl] [-a name] [command [arguments ...]] [redirection ...]
26 Replace the shell with the given command.
27
28 Execute COMMAND, replacing this shell with the specified program.
29 ARGUMENTS become the arguments to COMMAND.  If COMMAND is not specified,
30 any redirections take effect in the current shell.
31
32 Options:
33   -a name       pass NAME as the zeroth argument to COMMAND
34   -c            execute COMMAND with an empty environment
35   -l            place a dash in the zeroth argument to COMMAND
36
37 If the command cannot be executed, a non-interactive shell exits, unless
38 the shell option `execfail' is set.
39
40 Exit Status:
41 Returns success unless COMMAND is not found or a redirection error occurs.
42 $END
43
44 #include <config.h>
45
46 #include "../bashtypes.h"
47 #include "posixstat.h"
48 #include <signal.h>
49 #include <errno.h>
50
51 #if defined (HAVE_UNISTD_H)
52 #  include <unistd.h>
53 #endif
54
55 #include "../bashansi.h"
56 #include "../bashintl.h"
57
58 #include "../shell.h"
59 #include "../execute_cmd.h"
60 #include "../findcmd.h"
61 #if defined (JOB_CONTROL)
62 #  include "../jobs.h"
63 #endif
64 #include "../flags.h"
65 #include "../trap.h"
66 #if defined (HISTORY)
67 #  include "../bashhist.h"
68 #endif
69 #include "common.h"
70 #include "bashgetopt.h"
71
72 /* Not all systems declare ERRNO in errno.h... and some systems #define it! */
73 #if !defined (errno)
74 extern int errno;
75 #endif /* !errno */
76
77 extern int subshell_environment;
78 extern REDIRECT *redirection_undo_list;
79 extern char *exec_argv0;
80
81 int no_exit_on_failed_exec;
82
83 /* If the user wants this to look like a login shell, then
84    prepend a `-' onto NAME and return the new name. */
85 static char *
86 mkdashname (name)
87      char *name;
88 {
89   char *ret;
90
91   ret = (char *)xmalloc (2 + strlen (name));
92   ret[0] = '-';
93   strcpy (ret + 1, name);
94   return ret;
95 }
96
97 int
98 exec_builtin (list)
99      WORD_LIST *list;
100 {
101   int exit_value = EXECUTION_FAILURE;
102   int cleanenv, login, opt;
103   char *argv0, *command, **args, **env, *newname, *com2;
104
105   cleanenv = login = 0;
106   exec_argv0 = argv0 = (char *)NULL;
107
108   reset_internal_getopt ();
109   while ((opt = internal_getopt (list, "cla:")) != -1)
110     {
111       switch (opt)
112         {
113         case 'c':
114           cleanenv = 1;
115           break;
116         case 'l':
117           login = 1;
118           break;
119         case 'a':
120           argv0 = list_optarg;
121           break;
122         default:
123           builtin_usage ();
124           return (EX_USAGE);
125         }
126     }
127   list = loptend;
128
129   /* First, let the redirections remain. */
130   dispose_redirects (redirection_undo_list);
131   redirection_undo_list = (REDIRECT *)NULL;
132
133   if (list == 0)
134     return (EXECUTION_SUCCESS);
135
136 #if defined (RESTRICTED_SHELL)
137   if (restricted)
138     {
139       sh_restricted ((char *)NULL);
140       return (EXECUTION_FAILURE);
141     }
142 #endif /* RESTRICTED_SHELL */
143
144   args = strvec_from_word_list (list, 1, 0, (int *)NULL);
145
146   /* A command with a slash anywhere in its name is not looked up in $PATH. */
147   command = absolute_program (args[0]) ? args[0] : search_for_command (args[0], 1);
148
149   if (command == 0)
150     {
151       if (file_isdir (args[0]))
152         {
153 #if defined (EISDIR)
154           builtin_error (_("%s: cannot execute: %s"), args[0], strerror (EISDIR));
155 #else
156           builtin_error (_("%s: cannot execute: %s"), args[0], strerror (errno));
157 #endif
158           exit_value = EX_NOEXEC;
159         }
160       else
161         {
162           sh_notfound (args[0]);
163           exit_value = EX_NOTFOUND;     /* As per Posix.2, 3.14.6 */
164         }
165       goto failed_exec;
166     }
167
168   com2 = full_pathname (command);
169   if (com2)
170     {
171       if (command != args[0])
172         free (command);
173       command = com2;
174     }
175
176   if (argv0)
177     {
178       free (args[0]);
179       args[0] = login ? mkdashname (argv0) : savestring (argv0);
180       exec_argv0 = savestring (args[0]);
181     }
182   else if (login)
183     {
184       newname = mkdashname (args[0]);
185       free (args[0]);
186       args[0] = newname;
187     }
188
189   /* Decrement SHLVL by 1 so a new shell started here has the same value,
190      preserving the appearance.  After we do that, we need to change the
191      exported environment to include the new value. */
192   if (cleanenv == 0)
193     adjust_shell_level (-1);
194
195   if (cleanenv)
196     env = (char **)NULL;
197   else
198     {   
199       maybe_make_export_env ();
200       env = export_env;
201     }
202
203 #if defined (HISTORY)
204   if (interactive_shell && subshell_environment == 0)
205     maybe_save_shell_history ();
206 #endif /* HISTORY */
207
208   restore_original_signals ();
209
210 #if defined (JOB_CONTROL)
211   if (subshell_environment == 0)
212     end_job_control ();
213 #endif /* JOB_CONTROL */
214
215   exit_value = shell_execve (command, args, env);
216
217   /* We have to set this to NULL because shell_execve has called realloc()
218      to stuff more items at the front of the array, which may have caused
219      the memory to be freed by realloc().  We don't want to free it twice. */
220   args = (char **)NULL;
221   if (cleanenv == 0)
222     adjust_shell_level (1);
223
224   if (exit_value == EX_NOTFOUND)        /* no duplicate error message */
225     goto failed_exec;
226   else if (executable_file (command) == 0)
227     {
228       builtin_error (_("%s: cannot execute: %s"), command, strerror (errno));
229       exit_value = EX_NOEXEC;   /* As per Posix.2, 3.14.6 */
230     }
231   else
232     file_error (command);
233
234 failed_exec:
235   FREE (command);
236
237   if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0))
238     exit_shell (exit_value);
239
240   if (args)
241     strvec_dispose (args);
242
243   initialize_traps ();
244   initialize_signals (1);
245
246 #if defined (JOB_CONTROL)
247   if (interactive_shell || job_control)
248     restart_job_control ();
249 #endif /* JOB_CONTROL */
250
251   return (exit_value);
252 }