Line data Source code
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-2015 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 0 : mkdashname (name)
87 : char *name;
88 : {
89 0 : char *ret;
90 :
91 0 : ret = (char *)xmalloc (2 + strlen (name));
92 0 : ret[0] = '-';
93 0 : strcpy (ret + 1, name);
94 0 : return ret;
95 : }
96 :
97 : int
98 0 : exec_builtin (list)
99 : WORD_LIST *list;
100 : {
101 0 : int exit_value = EXECUTION_FAILURE;
102 0 : int cleanenv, login, opt;
103 0 : char *argv0, *command, **args, **env, *newname, *com2;
104 :
105 0 : cleanenv = login = 0;
106 0 : exec_argv0 = argv0 = (char *)NULL;
107 :
108 0 : reset_internal_getopt ();
109 0 : while ((opt = internal_getopt (list, "cla:")) != -1)
110 : {
111 0 : switch (opt)
112 : {
113 : case 'c':
114 : cleanenv = 1;
115 : break;
116 0 : case 'l':
117 0 : login = 1;
118 0 : break;
119 0 : case 'a':
120 0 : argv0 = list_optarg;
121 0 : break;
122 0 : CASE_HELPOPT;
123 0 : default:
124 0 : builtin_usage ();
125 0 : return (EX_USAGE);
126 : }
127 : }
128 0 : list = loptend;
129 :
130 : /* First, let the redirections remain. */
131 0 : dispose_redirects (redirection_undo_list);
132 0 : redirection_undo_list = (REDIRECT *)NULL;
133 :
134 0 : if (list == 0)
135 : return (EXECUTION_SUCCESS);
136 :
137 : #if defined (RESTRICTED_SHELL)
138 : if (restricted)
139 : {
140 : sh_restricted ((char *)NULL);
141 : return (EXECUTION_FAILURE);
142 : }
143 : #endif /* RESTRICTED_SHELL */
144 :
145 0 : args = strvec_from_word_list (list, 1, 0, (int *)NULL);
146 0 : env = (char **)0;
147 :
148 : /* A command with a slash anywhere in its name is not looked up in $PATH. */
149 0 : command = absolute_program (args[0]) ? args[0] : search_for_command (args[0], 1);
150 :
151 0 : if (command == 0)
152 : {
153 0 : if (file_isdir (args[0]))
154 : {
155 : #if defined (EISDIR)
156 0 : builtin_error (_("%s: cannot execute: %s"), args[0], strerror (EISDIR));
157 : #else
158 : builtin_error (_("%s: cannot execute: %s"), args[0], strerror (errno));
159 : #endif
160 0 : exit_value = EX_NOEXEC;
161 : }
162 : else
163 : {
164 0 : sh_notfound (args[0]);
165 0 : exit_value = EX_NOTFOUND; /* As per Posix.2, 3.14.6 */
166 : }
167 0 : goto failed_exec;
168 : }
169 :
170 0 : com2 = full_pathname (command);
171 0 : if (com2)
172 : {
173 0 : if (command != args[0])
174 0 : free (command);
175 : command = com2;
176 : }
177 :
178 0 : if (argv0)
179 : {
180 0 : free (args[0]);
181 0 : args[0] = login ? mkdashname (argv0) : savestring (argv0);
182 0 : exec_argv0 = savestring (args[0]);
183 : }
184 0 : else if (login)
185 : {
186 0 : newname = mkdashname (args[0]);
187 0 : free (args[0]);
188 0 : args[0] = newname;
189 : }
190 :
191 : /* Decrement SHLVL by 1 so a new shell started here has the same value,
192 : preserving the appearance. After we do that, we need to change the
193 : exported environment to include the new value. */
194 0 : if (cleanenv == 0)
195 0 : adjust_shell_level (-1);
196 :
197 0 : if (cleanenv)
198 : {
199 0 : env = strvec_create (1);
200 0 : env[0] = (char *)0;
201 : }
202 : else
203 : {
204 0 : maybe_make_export_env ();
205 0 : env = export_env;
206 : }
207 :
208 : #if defined (HISTORY)
209 : if (interactive_shell && subshell_environment == 0)
210 : maybe_save_shell_history ();
211 : #endif /* HISTORY */
212 :
213 0 : restore_original_signals ();
214 :
215 : #if defined (JOB_CONTROL)
216 0 : if (subshell_environment == 0)
217 0 : end_job_control ();
218 0 : if (interactive || job_control)
219 0 : default_tty_job_signals (); /* undo initialize_job_signals */
220 : #endif /* JOB_CONTROL */
221 :
222 0 : exit_value = shell_execve (command, args, env);
223 :
224 : /* We have to set this to NULL because shell_execve has called realloc()
225 : to stuff more items at the front of the array, which may have caused
226 : the memory to be freed by realloc(). We don't want to free it twice. */
227 0 : args = (char **)NULL;
228 0 : if (cleanenv == 0)
229 0 : adjust_shell_level (1);
230 :
231 0 : if (exit_value == EX_NOTFOUND) /* no duplicate error message */
232 : goto failed_exec;
233 0 : else if (executable_file (command) == 0)
234 : {
235 0 : builtin_error (_("%s: cannot execute: %s"), command, strerror (errno));
236 0 : exit_value = EX_NOEXEC; /* As per Posix.2, 3.14.6 */
237 : }
238 : else
239 0 : file_error (command);
240 :
241 0 : failed_exec:
242 0 : FREE (command);
243 :
244 0 : if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0))
245 0 : exit_shell (exit_value);
246 :
247 0 : if (args)
248 0 : strvec_dispose (args);
249 :
250 0 : if (env && env != export_env)
251 0 : strvec_dispose (env);
252 :
253 0 : initialize_traps ();
254 0 : initialize_signals (1);
255 :
256 : #if defined (JOB_CONTROL)
257 0 : if (interactive_shell || job_control)
258 0 : restart_job_control ();
259 : #endif /* JOB_CONTROL */
260 :
261 : return (exit_value);
262 : }
|