0818a25e21cb6b9fad071e8c6ba055cc61b4410a
[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-2003 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 #include "../bashintl.h"
50
51 #include "../shell.h"
52 #include "../execute_cmd.h"
53 #include "../findcmd.h"
54 #if defined (JOB_CONTROL)
55 #  include "../jobs.h"
56 #endif
57 #include "../flags.h"
58 #include "../trap.h"
59 #if defined (HISTORY)
60 #  include "../bashhist.h"
61 #endif
62 #include "common.h"
63 #include "bashgetopt.h"
64
65 /* Not all systems declare ERRNO in errno.h... and some systems #define it! */
66 #if !defined (errno)
67 extern int errno;
68 #endif /* !errno */
69
70 extern int subshell_environment;
71 extern REDIRECT *redirection_undo_list;
72
73 int no_exit_on_failed_exec;
74
75 /* If the user wants this to look like a login shell, then
76    prepend a `-' onto NAME and return the new name. */
77 static char *
78 mkdashname (name)
79      char *name;
80 {
81   char *ret;
82
83   ret = (char *)xmalloc (2 + strlen (name));
84   ret[0] = '-';
85   strcpy (ret + 1, name);
86   return ret;
87 }
88
89 int
90 exec_builtin (list)
91      WORD_LIST *list;
92 {
93   int exit_value = EXECUTION_FAILURE;
94   int cleanenv, login, opt;
95   char *argv0, *command, **args, **env, *newname, *com2;
96
97   cleanenv = login = 0;
98   argv0 = (char *)NULL;
99
100   reset_internal_getopt ();
101   while ((opt = internal_getopt (list, "cla:")) != -1)
102     {
103       switch (opt)
104         {
105         case 'c':
106           cleanenv = 1;
107           break;
108         case 'l':
109           login = 1;
110           break;
111         case 'a':
112           argv0 = list_optarg;
113           break;
114         default:
115           builtin_usage ();
116           return (EX_USAGE);
117         }
118     }
119   list = loptend;
120
121   /* First, let the redirections remain. */
122   dispose_redirects (redirection_undo_list);
123   redirection_undo_list = (REDIRECT *)NULL;
124
125   if (list == 0)
126     return (EXECUTION_SUCCESS);
127
128 #if defined (RESTRICTED_SHELL)
129   if (restricted)
130     {
131       sh_restricted ((char *)NULL);
132       return (EXECUTION_FAILURE);
133     }
134 #endif /* RESTRICTED_SHELL */
135
136   args = strvec_from_word_list (list, 1, 0, (int *)NULL);
137
138   /* A command with a slash anywhere in its name is not looked up in $PATH. */
139   command = absolute_program (args[0]) ? args[0] : search_for_command (args[0]);
140
141   if (command == 0)
142     {
143       sh_notfound (args[0]);
144       exit_value = EX_NOTFOUND; /* As per Posix.2, 3.14.6 */
145       goto failed_exec;
146     }
147
148   com2 = full_pathname (command);
149   if (com2)
150     {
151       if (command != args[0])
152         free (command);
153       command = com2;
154     }
155
156   if (argv0)
157     {
158       free (args[0]);
159       args[0] = login ? mkdashname (argv0) : savestring (argv0);
160     }
161   else if (login)
162     {
163       newname = mkdashname (args[0]);
164       free (args[0]);
165       args[0] = newname;
166     }
167
168   /* Decrement SHLVL by 1 so a new shell started here has the same value,
169      preserving the appearance.  After we do that, we need to change the
170      exported environment to include the new value. */
171   if (cleanenv == 0)
172     adjust_shell_level (-1);
173
174   if (cleanenv)
175     env = (char **)NULL;
176   else
177     {   
178       maybe_make_export_env ();
179       env = export_env;
180     }
181
182 #if defined (HISTORY)
183   if (interactive_shell && subshell_environment == 0)
184     maybe_save_shell_history ();
185 #endif /* HISTORY */
186
187   restore_original_signals ();
188
189 #if defined (JOB_CONTROL)
190   if (subshell_environment == 0)
191     end_job_control ();
192 #endif /* JOB_CONTROL */
193
194   shell_execve (command, args, env);
195
196   /* We have to set this to NULL because shell_execve has called realloc()
197      to stuff more items at the front of the array, which may have caused
198      the memory to be freed by realloc().  We don't want to free it twice. */
199   args = (char **)NULL;
200   if (cleanenv == 0)
201     adjust_shell_level (1);
202
203   if (executable_file (command) == 0)
204     {
205       builtin_error (_("%s: cannot execute: %s"), command, strerror (errno));
206       exit_value = EX_NOEXEC;   /* As per Posix.2, 3.14.6 */
207     }
208   else
209     file_error (command);
210
211 failed_exec:
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     strvec_dispose (args);
219
220   initialize_traps ();
221   initialize_signals (1);
222
223 #if defined (JOB_CONTROL)
224   if (interactive_shell || job_control)
225     restart_job_control ();
226 #endif /* JOB_CONTROL */
227
228   return (exit_value);
229 }