Imported from ../bash-4.0-rc1.tar.gz.
[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-2009 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
80 int 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. */
84 static char *
85 mkdashname (name)
86      char *name;
87 {
88   char *ret;
89
90   ret = (char *)xmalloc (2 + strlen (name));
91   ret[0] = '-';
92   strcpy (ret + 1, name);
93   return ret;
94 }
95
96 int
97 exec_builtin (list)
98      WORD_LIST *list;
99 {
100   int exit_value = EXECUTION_FAILURE;
101   int cleanenv, login, opt;
102   char *argv0, *command, **args, **env, *newname, *com2;
103
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;
127
128   /* First, let the redirections remain. */
129   dispose_redirects (redirection_undo_list);
130   redirection_undo_list = (REDIRECT *)NULL;
131
132   if (list == 0)
133     return (EXECUTION_SUCCESS);
134
135 #if defined (RESTRICTED_SHELL)
136   if (restricted)
137     {
138       sh_restricted ((char *)NULL);
139       return (EXECUTION_FAILURE);
140     }
141 #endif /* RESTRICTED_SHELL */
142
143   args = strvec_from_word_list (list, 1, 0, (int *)NULL);
144
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]);
147
148   if (command == 0)
149     {
150       sh_notfound (args[0]);
151       exit_value = EX_NOTFOUND; /* As per Posix.2, 3.14.6 */
152       goto failed_exec;
153     }
154
155   com2 = full_pathname (command);
156   if (com2)
157     {
158       if (command != args[0])
159         free (command);
160       command = com2;
161     }
162
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     }
174
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);
180
181   if (cleanenv)
182     env = (char **)NULL;
183   else
184     {   
185       maybe_make_export_env ();
186       env = export_env;
187     }
188
189 #if defined (HISTORY)
190   if (interactive_shell && subshell_environment == 0)
191     maybe_save_shell_history ();
192 #endif /* HISTORY */
193
194   restore_original_signals ();
195
196 #if defined (JOB_CONTROL)
197   if (subshell_environment == 0)
198     end_job_control ();
199 #endif /* JOB_CONTROL */
200
201   shell_execve (command, args, env);
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;
207   if (cleanenv == 0)
208     adjust_shell_level (1);
209
210   if (executable_file (command) == 0)
211     {
212       builtin_error (_("%s: cannot execute: %s"), command, strerror (errno));
213       exit_value = EX_NOEXEC;   /* As per Posix.2, 3.14.6 */
214     }
215   else
216     file_error (command);
217
218 failed_exec:
219   FREE (command);
220
221   if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0))
222     exit_shell (exit_value);
223
224   if (args)
225     strvec_dispose (args);
226
227   initialize_traps ();
228   initialize_signals (1);
229
230 #if defined (JOB_CONTROL)
231   if (interactive_shell || job_control)
232     restart_job_control ();
233 #endif /* JOB_CONTROL */
234
235   return (exit_value);
236 }