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