]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/exec.def
Bash-4.2 distribution sources and documentation
[thirdparty/bash.git] / builtins / exec.def
CommitLineData
726f6388
JA
1This file is exec.def, from which is created exec.c.
2It implements the builtin "exec" in Bash.
3
495aee44 4Copyright (C) 1987-2010 Free Software Foundation, Inc.
726f6388
JA
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
3185942a
JA
8Bash is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
726f6388 12
3185942a
JA
13Bash is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
726f6388 17
3185942a
JA
18You should have received a copy of the GNU General Public License
19along with Bash. If not, see <http://www.gnu.org/licenses/>.
726f6388
JA
20
21$PRODUCES exec.c
22
23$BUILTIN exec
24$FUNCTION exec_builtin
3185942a
JA
25$SHORT_DOC exec [-cl] [-a name] [command [arguments ...]] [redirection ...]
26Replace the shell with the given command.
27
28Execute COMMAND, replacing this shell with the specified program.
29ARGUMENTS become the arguments to COMMAND. If COMMAND is not specified,
30any redirections take effect in the current shell.
31
32Options:
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
37If the command cannot be executed, a non-interactive shell exits, unless
38the shell option `execfail' is set.
39
40Exit Status:
41Returns success unless COMMAND is not found or a redirection error occurs.
726f6388
JA
42$END
43
ccc6cda3
JA
44#include <config.h>
45
d166f048 46#include "../bashtypes.h"
bb70624e 47#include "posixstat.h"
726f6388
JA
48#include <signal.h>
49#include <errno.h>
50
ccc6cda3
JA
51#if defined (HAVE_UNISTD_H)
52# include <unistd.h>
53#endif
54
55#include "../bashansi.h"
b80f6443 56#include "../bashintl.h"
ccc6cda3
JA
57
58#include "../shell.h"
726f6388 59#include "../execute_cmd.h"
cce855bc 60#include "../findcmd.h"
ccc6cda3
JA
61#if defined (JOB_CONTROL)
62# include "../jobs.h"
63#endif
726f6388 64#include "../flags.h"
ccc6cda3
JA
65#include "../trap.h"
66#if defined (HISTORY)
67# include "../bashhist.h"
68#endif
69#include "common.h"
70#include "bashgetopt.h"
726f6388
JA
71
72/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
73#if !defined (errno)
74extern int errno;
75#endif /* !errno */
ccc6cda3 76
f73dda09 77extern int subshell_environment;
726f6388 78extern REDIRECT *redirection_undo_list;
495aee44 79extern char *exec_argv0;
726f6388 80
ccc6cda3
JA
81int 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. */
85static char *
86mkdashname (name)
87 char *name;
88{
89 char *ret;
90
f73dda09 91 ret = (char *)xmalloc (2 + strlen (name));
ccc6cda3
JA
92 ret[0] = '-';
93 strcpy (ret + 1, name);
94 return ret;
95}
96
726f6388
JA
97int
98exec_builtin (list)
99 WORD_LIST *list;
100{
101 int exit_value = EXECUTION_FAILURE;
ccc6cda3 102 int cleanenv, login, opt;
d166f048 103 char *argv0, *command, **args, **env, *newname, *com2;
726f6388 104
ccc6cda3 105 cleanenv = login = 0;
495aee44 106 exec_argv0 = argv0 = (char *)NULL;
ccc6cda3
JA
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;
726f6388
JA
128
129 /* First, let the redirections remain. */
130 dispose_redirects (redirection_undo_list);
131 redirection_undo_list = (REDIRECT *)NULL;
132
ccc6cda3 133 if (list == 0)
726f6388 134 return (EXECUTION_SUCCESS);
ccc6cda3
JA
135
136#if defined (RESTRICTED_SHELL)
137 if (restricted)
726f6388 138 {
7117c2d2 139 sh_restricted ((char *)NULL);
ccc6cda3
JA
140 return (EXECUTION_FAILURE);
141 }
142#endif /* RESTRICTED_SHELL */
726f6388 143
7117c2d2 144 args = strvec_from_word_list (list, 1, 0, (int *)NULL);
726f6388 145
ccc6cda3
JA
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]);
726f6388 148
ccc6cda3
JA
149 if (command == 0)
150 {
495aee44
CR
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 }
ccc6cda3
JA
165 goto failed_exec;
166 }
726f6388 167
d166f048
JA
168 com2 = full_pathname (command);
169 if (com2)
170 {
171 if (command != args[0])
172 free (command);
173 command = com2;
174 }
726f6388 175
ccc6cda3
JA
176 if (argv0)
177 {
178 free (args[0]);
179 args[0] = login ? mkdashname (argv0) : savestring (argv0);
495aee44 180 exec_argv0 = savestring (args[0]);
ccc6cda3
JA
181 }
182 else if (login)
183 {
184 newname = mkdashname (args[0]);
185 free (args[0]);
186 args[0] = newname;
187 }
726f6388 188
ccc6cda3
JA
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);
726f6388 194
ccc6cda3
JA
195 if (cleanenv)
196 env = (char **)NULL;
197 else
198 {
726f6388 199 maybe_make_export_env ();
ccc6cda3
JA
200 env = export_env;
201 }
726f6388
JA
202
203#if defined (HISTORY)
d166f048
JA
204 if (interactive_shell && subshell_environment == 0)
205 maybe_save_shell_history ();
726f6388 206#endif /* HISTORY */
ccc6cda3
JA
207
208 restore_original_signals ();
726f6388
JA
209
210#if defined (JOB_CONTROL)
ccc6cda3
JA
211 if (subshell_environment == 0)
212 end_job_control ();
726f6388
JA
213#endif /* JOB_CONTROL */
214
495aee44 215 exit_value = shell_execve (command, args, env);
bc4cd23c
JA
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;
ccc6cda3
JA
221 if (cleanenv == 0)
222 adjust_shell_level (1);
726f6388 223
495aee44
CR
224 if (exit_value == EX_NOTFOUND) /* no duplicate error message */
225 goto failed_exec;
226 else if (executable_file (command) == 0)
ccc6cda3 227 {
b80f6443 228 builtin_error (_("%s: cannot execute: %s"), command, strerror (errno));
ccc6cda3
JA
229 exit_value = EX_NOEXEC; /* As per Posix.2, 3.14.6 */
230 }
231 else
232 file_error (command);
726f6388 233
ccc6cda3 234failed_exec:
b80f6443 235 FREE (command);
726f6388 236
ccc6cda3
JA
237 if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0))
238 exit_shell (exit_value);
726f6388 239
d166f048 240 if (args)
7117c2d2 241 strvec_dispose (args);
d166f048 242
ccc6cda3 243 initialize_traps ();
7117c2d2 244 initialize_signals (1);
726f6388
JA
245
246#if defined (JOB_CONTROL)
95732b49
JA
247 if (interactive_shell || job_control)
248 restart_job_control ();
726f6388
JA
249#endif /* JOB_CONTROL */
250
ccc6cda3 251 return (exit_value);
726f6388 252}