]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/exec.def
Imported from ../bash-4.0-rc1.tar.gz.
[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
3185942a 4Copyright (C) 1987-2009 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
JA
78extern REDIRECT *redirection_undo_list;
79
ccc6cda3
JA
80int no_exit_on_failed_exec;
81
82/* If the user wants this to look like a login shell, then
83 prepend a `-' onto NAME and return the new name. */
84static char *
85mkdashname (name)
86 char *name;
87{
88 char *ret;
89
f73dda09 90 ret = (char *)xmalloc (2 + strlen (name));
ccc6cda3
JA
91 ret[0] = '-';
92 strcpy (ret + 1, name);
93 return ret;
94}
95
726f6388
JA
96int
97exec_builtin (list)
98 WORD_LIST *list;
99{
100 int exit_value = EXECUTION_FAILURE;
ccc6cda3 101 int cleanenv, login, opt;
d166f048 102 char *argv0, *command, **args, **env, *newname, *com2;
726f6388 103
ccc6cda3
JA
104 cleanenv = login = 0;
105 argv0 = (char *)NULL;
106
107 reset_internal_getopt ();
108 while ((opt = internal_getopt (list, "cla:")) != -1)
109 {
110 switch (opt)
111 {
112 case 'c':
113 cleanenv = 1;
114 break;
115 case 'l':
116 login = 1;
117 break;
118 case 'a':
119 argv0 = list_optarg;
120 break;
121 default:
122 builtin_usage ();
123 return (EX_USAGE);
124 }
125 }
126 list = loptend;
726f6388
JA
127
128 /* First, let the redirections remain. */
129 dispose_redirects (redirection_undo_list);
130 redirection_undo_list = (REDIRECT *)NULL;
131
ccc6cda3 132 if (list == 0)
726f6388 133 return (EXECUTION_SUCCESS);
ccc6cda3
JA
134
135#if defined (RESTRICTED_SHELL)
136 if (restricted)
726f6388 137 {
7117c2d2 138 sh_restricted ((char *)NULL);
ccc6cda3
JA
139 return (EXECUTION_FAILURE);
140 }
141#endif /* RESTRICTED_SHELL */
726f6388 142
7117c2d2 143 args = strvec_from_word_list (list, 1, 0, (int *)NULL);
726f6388 144
ccc6cda3
JA
145 /* A command with a slash anywhere in its name is not looked up in $PATH. */
146 command = absolute_program (args[0]) ? args[0] : search_for_command (args[0]);
726f6388 147
ccc6cda3
JA
148 if (command == 0)
149 {
7117c2d2 150 sh_notfound (args[0]);
ccc6cda3
JA
151 exit_value = EX_NOTFOUND; /* As per Posix.2, 3.14.6 */
152 goto failed_exec;
153 }
726f6388 154
d166f048
JA
155 com2 = full_pathname (command);
156 if (com2)
157 {
158 if (command != args[0])
159 free (command);
160 command = com2;
161 }
726f6388 162
ccc6cda3
JA
163 if (argv0)
164 {
165 free (args[0]);
166 args[0] = login ? mkdashname (argv0) : savestring (argv0);
167 }
168 else if (login)
169 {
170 newname = mkdashname (args[0]);
171 free (args[0]);
172 args[0] = newname;
173 }
726f6388 174
ccc6cda3
JA
175 /* Decrement SHLVL by 1 so a new shell started here has the same value,
176 preserving the appearance. After we do that, we need to change the
177 exported environment to include the new value. */
178 if (cleanenv == 0)
179 adjust_shell_level (-1);
726f6388 180
ccc6cda3
JA
181 if (cleanenv)
182 env = (char **)NULL;
183 else
184 {
726f6388 185 maybe_make_export_env ();
ccc6cda3
JA
186 env = export_env;
187 }
726f6388
JA
188
189#if defined (HISTORY)
d166f048
JA
190 if (interactive_shell && subshell_environment == 0)
191 maybe_save_shell_history ();
726f6388 192#endif /* HISTORY */
ccc6cda3
JA
193
194 restore_original_signals ();
726f6388
JA
195
196#if defined (JOB_CONTROL)
ccc6cda3
JA
197 if (subshell_environment == 0)
198 end_job_control ();
726f6388
JA
199#endif /* JOB_CONTROL */
200
ccc6cda3 201 shell_execve (command, args, env);
bc4cd23c
JA
202
203 /* We have to set this to NULL because shell_execve has called realloc()
204 to stuff more items at the front of the array, which may have caused
205 the memory to be freed by realloc(). We don't want to free it twice. */
206 args = (char **)NULL;
ccc6cda3
JA
207 if (cleanenv == 0)
208 adjust_shell_level (1);
726f6388 209
ccc6cda3
JA
210 if (executable_file (command) == 0)
211 {
b80f6443 212 builtin_error (_("%s: cannot execute: %s"), command, strerror (errno));
ccc6cda3
JA
213 exit_value = EX_NOEXEC; /* As per Posix.2, 3.14.6 */
214 }
215 else
216 file_error (command);
726f6388 217
ccc6cda3 218failed_exec:
b80f6443 219 FREE (command);
726f6388 220
ccc6cda3
JA
221 if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0))
222 exit_shell (exit_value);
726f6388 223
d166f048 224 if (args)
7117c2d2 225 strvec_dispose (args);
d166f048 226
ccc6cda3 227 initialize_traps ();
7117c2d2 228 initialize_signals (1);
726f6388
JA
229
230#if defined (JOB_CONTROL)
95732b49
JA
231 if (interactive_shell || job_control)
232 restart_job_control ();
726f6388
JA
233#endif /* JOB_CONTROL */
234
ccc6cda3 235 return (exit_value);
726f6388 236}