1 | /* Copyright (C) 1996-2003 Free Software Foundation, Inc.
|
---|
2 |
|
---|
3 | This file is part of GNU Bash, the Bourne Again SHell.
|
---|
4 |
|
---|
5 | Bash is free software; you can redistribute it and/or modify it under
|
---|
6 | the terms of the GNU General Public License as published by the Free
|
---|
7 | Software Foundation; either version 2, or (at your option) any later
|
---|
8 | version.
|
---|
9 |
|
---|
10 | Bash is distributed in the hope that it will be useful, but WITHOUT ANY
|
---|
11 | WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
---|
12 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
---|
13 | for more details.
|
---|
14 |
|
---|
15 | You should have received a copy of the GNU General Public License along
|
---|
16 | with Bash; see the file COPYING. If not, write to the Free Software
|
---|
17 | Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
---|
18 |
|
---|
19 | #include <config.h>
|
---|
20 |
|
---|
21 | #if defined (HAVE_UNISTD_H)
|
---|
22 | # include <unistd.h>
|
---|
23 | #endif
|
---|
24 |
|
---|
25 | #include "../bashtypes.h"
|
---|
26 | #include "posixstat.h"
|
---|
27 | #include "filecntl.h"
|
---|
28 |
|
---|
29 | #include <stdio.h>
|
---|
30 | #include <signal.h>
|
---|
31 | #include <errno.h>
|
---|
32 |
|
---|
33 | #include "../bashansi.h"
|
---|
34 | #include "../bashintl.h"
|
---|
35 |
|
---|
36 | #include "../shell.h"
|
---|
37 | #include "../jobs.h"
|
---|
38 | #include "../builtins.h"
|
---|
39 | #include "../flags.h"
|
---|
40 | #include "../input.h"
|
---|
41 | #include "../execute_cmd.h"
|
---|
42 | #include "../trap.h"
|
---|
43 |
|
---|
44 | #if defined (HISTORY)
|
---|
45 | # include "../bashhist.h"
|
---|
46 | #endif
|
---|
47 |
|
---|
48 | #include "common.h"
|
---|
49 |
|
---|
50 | #if !defined (errno)
|
---|
51 | extern int errno;
|
---|
52 | #endif
|
---|
53 |
|
---|
54 | /* Flags for _evalfile() */
|
---|
55 | #define FEVAL_ENOENTOK 0x001
|
---|
56 | #define FEVAL_BUILTIN 0x002
|
---|
57 | #define FEVAL_UNWINDPROT 0x004
|
---|
58 | #define FEVAL_NONINT 0x008
|
---|
59 | #define FEVAL_LONGJMP 0x010
|
---|
60 | #define FEVAL_HISTORY 0x020
|
---|
61 | #define FEVAL_CHECKBINARY 0x040
|
---|
62 | #define FEVAL_REGFILE 0x080
|
---|
63 | #define FEVAL_NOPUSHARGS 0x100
|
---|
64 |
|
---|
65 | extern int posixly_correct;
|
---|
66 | extern int indirection_level, startup_state, subshell_environment;
|
---|
67 | extern int return_catch_flag, return_catch_value;
|
---|
68 | extern int last_command_exit_value;
|
---|
69 |
|
---|
70 | /* How many `levels' of sourced files we have. */
|
---|
71 | int sourcelevel = 0;
|
---|
72 |
|
---|
73 | static int
|
---|
74 | _evalfile (filename, flags)
|
---|
75 | const char *filename;
|
---|
76 | int flags;
|
---|
77 | {
|
---|
78 | volatile int old_interactive;
|
---|
79 | procenv_t old_return_catch;
|
---|
80 | int return_val, fd, result, pflags;
|
---|
81 | char *string;
|
---|
82 | struct stat finfo;
|
---|
83 | size_t file_size;
|
---|
84 | sh_vmsg_func_t *errfunc;
|
---|
85 | #if defined (ARRAY_VARS)
|
---|
86 | SHELL_VAR *funcname_v, *nfv, *bash_source_v, *bash_lineno_v;
|
---|
87 | ARRAY *funcname_a, *bash_source_a, *bash_lineno_a;
|
---|
88 | # if defined (DEBUGGER)
|
---|
89 | SHELL_VAR *bash_argv_v, *bash_argc_v;
|
---|
90 | ARRAY *bash_argv_a, *bash_argc_a;
|
---|
91 | # endif
|
---|
92 | char *t, tt[2];
|
---|
93 | #endif
|
---|
94 |
|
---|
95 | USE_VAR(pflags);
|
---|
96 |
|
---|
97 | #if defined (ARRAY_VARS)
|
---|
98 | GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v, funcname_a);
|
---|
99 | GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v, bash_source_a);
|
---|
100 | GET_ARRAY_FROM_VAR ("BASH_LINENO", bash_lineno_v, bash_lineno_a);
|
---|
101 | # if defined (DEBUGGER)
|
---|
102 | GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
|
---|
103 | GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
|
---|
104 | # endif
|
---|
105 | #endif
|
---|
106 |
|
---|
107 | fd = open (filename, O_RDONLY);
|
---|
108 |
|
---|
109 | if (fd < 0 || (fstat (fd, &finfo) == -1))
|
---|
110 | {
|
---|
111 | file_error_and_exit:
|
---|
112 | if (((flags & FEVAL_ENOENTOK) == 0) || errno != ENOENT)
|
---|
113 | file_error (filename);
|
---|
114 |
|
---|
115 | if (flags & FEVAL_LONGJMP)
|
---|
116 | {
|
---|
117 | last_command_exit_value = 1;
|
---|
118 | jump_to_top_level (EXITPROG);
|
---|
119 | }
|
---|
120 |
|
---|
121 | return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE
|
---|
122 | : ((errno == ENOENT) ? 0 : -1));
|
---|
123 | }
|
---|
124 |
|
---|
125 | errfunc = ((flags & FEVAL_BUILTIN) ? builtin_error : internal_error);
|
---|
126 |
|
---|
127 | if (S_ISDIR (finfo.st_mode))
|
---|
128 | {
|
---|
129 | (*errfunc) (_("%s: is a directory"), filename);
|
---|
130 | return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
|
---|
131 | }
|
---|
132 | else if ((flags & FEVAL_REGFILE) && S_ISREG (finfo.st_mode) == 0)
|
---|
133 | {
|
---|
134 | (*errfunc) (_("%s: not a regular file"), filename);
|
---|
135 | return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
|
---|
136 | }
|
---|
137 |
|
---|
138 | file_size = (size_t)finfo.st_size;
|
---|
139 | /* Check for overflow with large files. */
|
---|
140 | if (file_size != finfo.st_size || file_size + 1 < file_size)
|
---|
141 | {
|
---|
142 | (*errfunc) (_("%s: file is too large"), filename);
|
---|
143 | return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
|
---|
144 | }
|
---|
145 |
|
---|
146 | #if defined (__CYGWIN__) && defined (O_TEXT)
|
---|
147 | setmode (fd, O_TEXT);
|
---|
148 | #endif
|
---|
149 |
|
---|
150 | string = (char *)xmalloc (1 + file_size);
|
---|
151 | result = read (fd, string, file_size);
|
---|
152 | string[result] = '\0';
|
---|
153 |
|
---|
154 | return_val = errno;
|
---|
155 | close (fd);
|
---|
156 | errno = return_val;
|
---|
157 |
|
---|
158 | if (result < 0) /* XXX was != file_size, not < 0 */
|
---|
159 | {
|
---|
160 | free (string);
|
---|
161 | goto file_error_and_exit;
|
---|
162 | }
|
---|
163 |
|
---|
164 | if (result == 0)
|
---|
165 | {
|
---|
166 | free (string);
|
---|
167 | return ((flags & FEVAL_BUILTIN) ? EXECUTION_SUCCESS : 1);
|
---|
168 | }
|
---|
169 |
|
---|
170 | if ((flags & FEVAL_CHECKBINARY) &&
|
---|
171 | check_binary_file (string, (result > 80) ? 80 : result))
|
---|
172 | {
|
---|
173 | free (string);
|
---|
174 | (*errfunc) ("%s: cannot execute binary file", filename);
|
---|
175 | return ((flags & FEVAL_BUILTIN) ? EX_BINARY_FILE : -1);
|
---|
176 | }
|
---|
177 |
|
---|
178 | if (flags & FEVAL_UNWINDPROT)
|
---|
179 | {
|
---|
180 | begin_unwind_frame ("_evalfile");
|
---|
181 |
|
---|
182 | unwind_protect_int (return_catch_flag);
|
---|
183 | unwind_protect_jmp_buf (return_catch);
|
---|
184 | if (flags & FEVAL_NONINT)
|
---|
185 | unwind_protect_int (interactive);
|
---|
186 | unwind_protect_int (sourcelevel);
|
---|
187 | }
|
---|
188 | else
|
---|
189 | {
|
---|
190 | COPY_PROCENV (return_catch, old_return_catch);
|
---|
191 | if (flags & FEVAL_NONINT)
|
---|
192 | old_interactive = interactive;
|
---|
193 | }
|
---|
194 |
|
---|
195 | if (flags & FEVAL_NONINT)
|
---|
196 | interactive = 0;
|
---|
197 |
|
---|
198 | return_catch_flag++;
|
---|
199 | sourcelevel++;
|
---|
200 |
|
---|
201 | #if defined (ARRAY_VARS)
|
---|
202 | array_push (bash_source_a, (char *)filename);
|
---|
203 | t = itos (executing_line_number ());
|
---|
204 | array_push (bash_lineno_a, t);
|
---|
205 | free (t);
|
---|
206 | array_push (funcname_a, "source"); /* not exactly right */
|
---|
207 | # if defined (DEBUGGER)
|
---|
208 | /* Have to figure out a better way to do this when `source' is supplied
|
---|
209 | arguments */
|
---|
210 | if ((flags & FEVAL_NOPUSHARGS) == 0)
|
---|
211 | {
|
---|
212 | array_push (bash_argv_a, (char *)filename);
|
---|
213 | tt[0] = '1'; tt[1] = '\0';
|
---|
214 | array_push (bash_argc_a, tt);
|
---|
215 | }
|
---|
216 | # endif
|
---|
217 | #endif
|
---|
218 |
|
---|
219 | /* set the flags to be passed to parse_and_execute */
|
---|
220 | pflags = SEVAL_RESETLINE;
|
---|
221 | pflags |= (flags & FEVAL_HISTORY) ? 0 : SEVAL_NOHIST;
|
---|
222 |
|
---|
223 | if (flags & FEVAL_BUILTIN)
|
---|
224 | result = EXECUTION_SUCCESS;
|
---|
225 |
|
---|
226 | return_val = setjmp (return_catch);
|
---|
227 |
|
---|
228 | /* If `return' was seen outside of a function, but in the script, then
|
---|
229 | force parse_and_execute () to clean up. */
|
---|
230 | if (return_val)
|
---|
231 | {
|
---|
232 | parse_and_execute_cleanup ();
|
---|
233 | result = return_catch_value;
|
---|
234 | }
|
---|
235 | else
|
---|
236 | result = parse_and_execute (string, filename, pflags);
|
---|
237 |
|
---|
238 | if (flags & FEVAL_UNWINDPROT)
|
---|
239 | run_unwind_frame ("_evalfile");
|
---|
240 | else
|
---|
241 | {
|
---|
242 | if (flags & FEVAL_NONINT)
|
---|
243 | interactive = old_interactive;
|
---|
244 | return_catch_flag--;
|
---|
245 | sourcelevel--;
|
---|
246 | COPY_PROCENV (old_return_catch, return_catch);
|
---|
247 | }
|
---|
248 |
|
---|
249 | #if defined (ARRAY_VARS)
|
---|
250 | /* These two variables cannot be unset, and cannot be affected by the
|
---|
251 | sourced file. */
|
---|
252 | array_pop (bash_source_a);
|
---|
253 | array_pop (bash_lineno_a);
|
---|
254 |
|
---|
255 | /* FUNCNAME can be unset, and so can potentially be changed by the
|
---|
256 | sourced file. */
|
---|
257 | GET_ARRAY_FROM_VAR ("FUNCNAME", nfv, funcname_a);
|
---|
258 | if (nfv == funcname_v)
|
---|
259 | array_pop (funcname_a);
|
---|
260 | # if defined (DEBUGGER)
|
---|
261 | if ((flags & FEVAL_NOPUSHARGS) == 0)
|
---|
262 | {
|
---|
263 | array_pop (bash_argc_a);
|
---|
264 | array_pop (bash_argv_a);
|
---|
265 | }
|
---|
266 | # endif
|
---|
267 | #endif
|
---|
268 |
|
---|
269 | return ((flags & FEVAL_BUILTIN) ? result : 1);
|
---|
270 | }
|
---|
271 |
|
---|
272 | int
|
---|
273 | maybe_execute_file (fname, force_noninteractive)
|
---|
274 | const char *fname;
|
---|
275 | int force_noninteractive;
|
---|
276 | {
|
---|
277 | char *filename;
|
---|
278 | int result, flags;
|
---|
279 |
|
---|
280 | filename = bash_tilde_expand (fname, 0);
|
---|
281 | flags = FEVAL_ENOENTOK;
|
---|
282 | if (force_noninteractive)
|
---|
283 | flags |= FEVAL_NONINT;
|
---|
284 | result = _evalfile (filename, flags);
|
---|
285 | free (filename);
|
---|
286 | return result;
|
---|
287 | }
|
---|
288 |
|
---|
289 | #if defined (HISTORY)
|
---|
290 | int
|
---|
291 | fc_execute_file (filename)
|
---|
292 | const char *filename;
|
---|
293 | {
|
---|
294 | int flags;
|
---|
295 |
|
---|
296 | /* We want these commands to show up in the history list if
|
---|
297 | remember_on_history is set. */
|
---|
298 | flags = FEVAL_ENOENTOK|FEVAL_HISTORY|FEVAL_REGFILE;
|
---|
299 | return (_evalfile (filename, flags));
|
---|
300 | }
|
---|
301 | #endif /* HISTORY */
|
---|
302 |
|
---|
303 | int
|
---|
304 | source_file (filename, sflags)
|
---|
305 | const char *filename;
|
---|
306 | int sflags;
|
---|
307 | {
|
---|
308 | int flags, rval;
|
---|
309 |
|
---|
310 | flags = FEVAL_BUILTIN|FEVAL_UNWINDPROT|FEVAL_NONINT;
|
---|
311 | if (sflags)
|
---|
312 | flags |= FEVAL_NOPUSHARGS;
|
---|
313 | /* POSIX shells exit if non-interactive and file error. */
|
---|
314 | if (posixly_correct && !interactive_shell)
|
---|
315 | flags |= FEVAL_LONGJMP;
|
---|
316 | rval = _evalfile (filename, flags);
|
---|
317 |
|
---|
318 | run_return_trap ();
|
---|
319 | return rval;
|
---|
320 | }
|
---|