blob: 88da13b3378d7df0a3a8ec8101eb6d2e49be3780 [file] [log] [blame]
Dan Pasanenc6e37862014-10-02 14:08:59 -05001/* exec.c, created from exec.def. */
2#line 22 "./exec.def"
3
4#line 43 "./exec.def"
5
6#include <config.h>
7
8#include "../bashtypes.h"
9#include "posixstat.h"
10#include <signal.h>
11#include <errno.h>
12
13#if defined (HAVE_UNISTD_H)
14# include <unistd.h>
15#endif
16
17#include "../bashansi.h"
18#include "../bashintl.h"
19
20#include "../shell.h"
21#include "../execute_cmd.h"
22#include "../findcmd.h"
23#if defined (JOB_CONTROL)
24# include "../jobs.h"
25#endif
26#include "../flags.h"
27#include "../trap.h"
28#if defined (HISTORY)
29# include "../bashhist.h"
30#endif
31#include "common.h"
32#include "bashgetopt.h"
33
34/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
35#if !defined (errno)
Ricardo Cerqueiraa02fbff2013-07-25 22:35:34 +010036#include <errno.h>
Dan Pasanenc6e37862014-10-02 14:08:59 -050037#endif /* !errno */
38
39extern int subshell_environment;
40extern REDIRECT *redirection_undo_list;
41extern char *exec_argv0;
42
43int no_exit_on_failed_exec;
44
45/* If the user wants this to look like a login shell, then
46 prepend a `-' onto NAME and return the new name. */
47static char *
48mkdashname (name)
49 char *name;
50{
51 char *ret;
52
53 ret = (char *)xmalloc (2 + strlen (name));
54 ret[0] = '-';
55 strcpy (ret + 1, name);
56 return ret;
57}
58
59int
60exec_builtin (list)
61 WORD_LIST *list;
62{
63 int exit_value = EXECUTION_FAILURE;
64 int cleanenv, login, opt;
65 char *argv0, *command, **args, **env, *newname, *com2;
66
67 cleanenv = login = 0;
68 exec_argv0 = argv0 = (char *)NULL;
69
70 reset_internal_getopt ();
71 while ((opt = internal_getopt (list, "cla:")) != -1)
72 {
73 switch (opt)
74 {
75 case 'c':
76 cleanenv = 1;
77 break;
78 case 'l':
79 login = 1;
80 break;
81 case 'a':
82 argv0 = list_optarg;
83 break;
84 default:
85 builtin_usage ();
86 return (EX_USAGE);
87 }
88 }
89 list = loptend;
90
91 /* First, let the redirections remain. */
92 dispose_redirects (redirection_undo_list);
93 redirection_undo_list = (REDIRECT *)NULL;
94
95 if (list == 0)
96 return (EXECUTION_SUCCESS);
97
98#if defined (RESTRICTED_SHELL)
99 if (restricted)
100 {
101 sh_restricted ((char *)NULL);
102 return (EXECUTION_FAILURE);
103 }
104#endif /* RESTRICTED_SHELL */
105
106 args = strvec_from_word_list (list, 1, 0, (int *)NULL);
107
108 /* A command with a slash anywhere in its name is not looked up in $PATH. */
109 command = absolute_program (args[0]) ? args[0] : search_for_command (args[0], 1);
110
111 if (command == 0)
112 {
113 if (file_isdir (args[0]))
114 {
115#if defined (EISDIR)
116 builtin_error (_("%s: cannot execute: %s"), args[0], strerror (EISDIR));
117#else
118 builtin_error (_("%s: cannot execute: %s"), args[0], strerror (errno));
119#endif
120 exit_value = EX_NOEXEC;
121 }
122 else
123 {
124 sh_notfound (args[0]);
125 exit_value = EX_NOTFOUND; /* As per Posix.2, 3.14.6 */
126 }
127 goto failed_exec;
128 }
129
130 com2 = full_pathname (command);
131 if (com2)
132 {
133 if (command != args[0])
134 free (command);
135 command = com2;
136 }
137
138 if (argv0)
139 {
140 free (args[0]);
141 args[0] = login ? mkdashname (argv0) : savestring (argv0);
142 exec_argv0 = savestring (args[0]);
143 }
144 else if (login)
145 {
146 newname = mkdashname (args[0]);
147 free (args[0]);
148 args[0] = newname;
149 }
150
151 /* Decrement SHLVL by 1 so a new shell started here has the same value,
152 preserving the appearance. After we do that, we need to change the
153 exported environment to include the new value. */
154 if (cleanenv == 0)
155 adjust_shell_level (-1);
156
157 if (cleanenv)
158 env = (char **)NULL;
159 else
160 {
161 maybe_make_export_env ();
162 env = export_env;
163 }
164
165#if defined (HISTORY)
166 if (interactive_shell && subshell_environment == 0)
167 maybe_save_shell_history ();
168#endif /* HISTORY */
169
170 restore_original_signals ();
171
172#if defined (JOB_CONTROL)
173 if (subshell_environment == 0)
174 end_job_control ();
175#endif /* JOB_CONTROL */
176
177 exit_value = shell_execve (command, args, env);
178
179 /* We have to set this to NULL because shell_execve has called realloc()
180 to stuff more items at the front of the array, which may have caused
181 the memory to be freed by realloc(). We don't want to free it twice. */
182 args = (char **)NULL;
183 if (cleanenv == 0)
184 adjust_shell_level (1);
185
186 if (exit_value == EX_NOTFOUND) /* no duplicate error message */
187 goto failed_exec;
188 else if (executable_file (command) == 0)
189 {
190 builtin_error (_("%s: cannot execute: %s"), command, strerror (errno));
191 exit_value = EX_NOEXEC; /* As per Posix.2, 3.14.6 */
192 }
193 else
194 file_error (command);
195
196failed_exec:
197 FREE (command);
198
199 if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0))
200 exit_shell (exit_value);
201
202 if (args)
203 strvec_dispose (args);
204
205 initialize_traps ();
206 initialize_signals (1);
207
208#if defined (JOB_CONTROL)
209 if (interactive_shell || job_control)
210 restart_job_control ();
211#endif /* JOB_CONTROL */
212
213 return (exit_value);
214}