]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/evalfile.c
Bash-4.2 distribution sources and documentation
[thirdparty/bash.git] / builtins / evalfile.c
CommitLineData
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)
55extern 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 69extern int posixly_correct;
0628567a 70extern int indirection_level, subshell_environment;
ccc6cda3
JA
71extern int return_catch_flag, return_catch_value;
72extern int last_command_exit_value;
495aee44 73extern int executing_command_builtin;
ccc6cda3
JA
74
75/* How many `levels' of sourced files we have. */
76int sourcelevel = 0;
77
78static 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 {
117file_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
300int
301maybe_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)
318int
319fc_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 331int
b80f6443 332source_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}