4e1394dead27ff27b15eb789f2f99808e7efc2ee
[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, 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, 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   if (cleanenv == 0)
195     adjust_shell_level (1);
196
197   if (executable_file (command) == 0)
198     {
199       builtin_error ("%s: cannot execute: %s", command, strerror (errno));
200       exit_value = EX_NOEXEC;   /* As per Posix.2, 3.14.6 */
201     }
202   else
203     file_error (command);
204
205 failed_exec:
206   if (command)
207     free (command);
208
209   if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0))
210     exit_shell (exit_value);
211
212   if (args)
213     free_array (args);
214
215   initialize_traps ();
216   reinitialize_signals ();
217
218 #if defined (JOB_CONTROL)
219   restart_job_control ();
220 #endif /* JOB_CONTROL */
221
222   return (exit_value);
223 }