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