]> git.ipfire.org Git - thirdparty/bash.git/blob - builtins/exec.def
d578b63524afef89a03942ce2e274bac21a2d848
[thirdparty/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, 1989, 1991 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 it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
12
13 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with Bash; see the file COPYING. If not, write to the Free Software
20 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
21
22 $PRODUCES exec.c
23
24 $BUILTIN exec
25 $FUNCTION exec_builtin
26 $SHORT_DOC exec [-cl] [-a name] file [redirection ...]
27 Exec FILE, replacing this shell with the specified program.
28 If FILE is not specified, the redirections take effect in this
29 shell. If the first argument is `-l', then place a dash in the
30 zeroth arg passed to FILE, as login does. If the `-c' option
31 is supplied, FILE is executed with a null environment. The `-a'
32 option means to make set argv[0] of the executed process to NAME.
33 If the file cannot be executed and the shell is not interactive,
34 then the shell exits, unless the shell option `execfail' is set.
35 $END
36
37 #include <config.h>
38
39 #include "../bashtypes.h"
40 #include "posixstat.h"
41 #include <signal.h>
42 #include <errno.h>
43
44 #if defined (HAVE_UNISTD_H)
45 # include <unistd.h>
46 #endif
47
48 #include "../bashansi.h"
49
50 #include "../shell.h"
51 #include "../execute_cmd.h"
52 #include "../findcmd.h"
53 #if defined (JOB_CONTROL)
54 # include "../jobs.h"
55 #endif
56 #include "../flags.h"
57 #include "../trap.h"
58 #if defined (HISTORY)
59 # include "../bashhist.h"
60 #endif
61 #include "common.h"
62 #include "bashgetopt.h"
63
64 /* Not all systems declare ERRNO in errno.h... and some systems #define it! */
65 #if !defined (errno)
66 extern int errno;
67 #endif /* !errno */
68
69 extern int interactive, interactive_shell, subshell_environment;
70 extern REDIRECT *redirection_undo_list;
71
72 int no_exit_on_failed_exec;
73
74 /* If the user wants this to look like a login shell, then
75 prepend a `-' onto NAME and return the new name. */
76 static char *
77 mkdashname (name)
78 char *name;
79 {
80 char *ret;
81
82 ret = xmalloc (2 + strlen (name));
83 ret[0] = '-';
84 strcpy (ret + 1, name);
85 return ret;
86 }
87
88 int
89 exec_builtin (list)
90 WORD_LIST *list;
91 {
92 int exit_value = EXECUTION_FAILURE;
93 int cleanenv, login, opt;
94 char *argv0, *command, **args, **env, *newname, *com2;
95
96 cleanenv = login = 0;
97 argv0 = (char *)NULL;
98
99 reset_internal_getopt ();
100 while ((opt = internal_getopt (list, "cla:")) != -1)
101 {
102 switch (opt)
103 {
104 case 'c':
105 cleanenv = 1;
106 break;
107 case 'l':
108 login = 1;
109 break;
110 case 'a':
111 argv0 = list_optarg;
112 break;
113 default:
114 builtin_usage ();
115 return (EX_USAGE);
116 }
117 }
118 list = loptend;
119
120 /* First, let the redirections remain. */
121 dispose_redirects (redirection_undo_list);
122 redirection_undo_list = (REDIRECT *)NULL;
123
124 if (list == 0)
125 return (EXECUTION_SUCCESS);
126
127 #if defined (RESTRICTED_SHELL)
128 if (restricted)
129 {
130 builtin_error ("restricted");
131 return (EXECUTION_FAILURE);
132 }
133 #endif /* RESTRICTED_SHELL */
134
135 args = word_list_to_argv (list, 1, 0, (int *)NULL);
136
137 /* A command with a slash anywhere in its name is not looked up in $PATH. */
138 command = absolute_program (args[0]) ? args[0] : search_for_command (args[0]);
139
140 if (command == 0)
141 {
142 builtin_error ("%s: not found", args[0]);
143 exit_value = EX_NOTFOUND; /* As per Posix.2, 3.14.6 */
144 goto failed_exec;
145 }
146
147 com2 = full_pathname (command);
148 if (com2)
149 {
150 if (command != args[0])
151 free (command);
152 command = com2;
153 }
154
155 if (argv0)
156 {
157 free (args[0]);
158 args[0] = login ? mkdashname (argv0) : savestring (argv0);
159 }
160 else if (login)
161 {
162 newname = mkdashname (args[0]);
163 free (args[0]);
164 args[0] = newname;
165 }
166
167 /* Decrement SHLVL by 1 so a new shell started here has the same value,
168 preserving the appearance. After we do that, we need to change the
169 exported environment to include the new value. */
170 if (cleanenv == 0)
171 adjust_shell_level (-1);
172
173 if (cleanenv)
174 env = (char **)NULL;
175 else
176 {
177 maybe_make_export_env ();
178 env = export_env;
179 }
180
181 #if defined (HISTORY)
182 if (interactive_shell && subshell_environment == 0)
183 maybe_save_shell_history ();
184 #endif /* HISTORY */
185
186 restore_original_signals ();
187
188 #if defined (JOB_CONTROL)
189 if (subshell_environment == 0)
190 end_job_control ();
191 #endif /* JOB_CONTROL */
192
193 shell_execve (command, args, env);
194
195 /* We have to set this to NULL because shell_execve has called realloc()
196 to stuff more items at the front of the array, which may have caused
197 the memory to be freed by realloc(). We don't want to free it twice. */
198 args = (char **)NULL;
199 if (cleanenv == 0)
200 adjust_shell_level (1);
201
202 if (executable_file (command) == 0)
203 {
204 builtin_error ("%s: cannot execute: %s", command, strerror (errno));
205 exit_value = EX_NOEXEC; /* As per Posix.2, 3.14.6 */
206 }
207 else
208 file_error (command);
209
210 failed_exec:
211 if (command)
212 free (command);
213
214 if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0))
215 exit_shell (exit_value);
216
217 if (args)
218 free_array (args);
219
220 initialize_traps ();
221 reinitialize_signals ();
222
223 #if defined (JOB_CONTROL)
224 restart_job_control ();
225 #endif /* JOB_CONTROL */
226
227 return (exit_value);
228 }