1 /* evalfile.c - read and evaluate commands from a file or file descriptor */
3 /* Copyright (C) 1996-2017 Free Software Foundation, Inc.
5 This file is part of GNU Bush, the Bourne Again SHell.
7 Bush 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.
12 Bush 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.
17 You should have received a copy of the GNU General Public License
18 along with Bush. If not, see <http://www.gnu.org/licenses/>.
23 #if defined (HAVE_UNISTD_H)
27 #include "../src/bushtypes.h"
28 #include "posixstat.h"
35 #include "../src/bushansi.h"
36 #include "../src/bushintl.h"
38 #include "../src/shell.h"
39 #include "../src/lxrgmr/parser.h"
40 #include "../src/jobs.h"
41 #include "../src/builtins.h"
42 #include "../src/flags.h"
43 #include "../src/input/input.h"
44 #include "../src/runner/execute_cmd.h"
45 #include "../src/trap.h"
47 #include <lxrgmr/y.tab.h>
50 # include "../src/bushhist.h"
61 /* Flags for _evalfile() */
62 #define FEVAL_ENOENTOK 0x001
63 #define FEVAL_BUILTIN 0x002
64 #define FEVAL_UNWINDPROT 0x004
65 #define FEVAL_NONINT 0x008
66 #define FEVAL_LONGJMP 0x010
67 #define FEVAL_HISTORY 0x020
68 #define FEVAL_CHECKBINARY 0x040
69 #define FEVAL_REGFILE 0x080
70 #define FEVAL_NOPUSHARGS 0x100
72 /* How many `levels' of sourced files we have. */
76 _evalfile (filename
, flags
)
80 volatile int old_interactive
;
81 procenv_t old_return_catch
;
82 int return_val
, fd
, result
, pflags
, i
, nnull
;
83 ssize_t nr
; /* return value from read(2) */
87 sh_vmsg_func_t
*errfunc
;
88 #if defined (ARRAY_VARS)
89 SHELL_VAR
*funcname_v
, *bush_source_v
, *bush_lineno_v
;
90 ARRAY
*funcname_a
, *bush_source_a
, *bush_lineno_a
;
91 struct func_array_state
*fa
;
92 # if defined (DEBUGGER)
93 SHELL_VAR
*bush_argv_v
, *bush_argc_v
;
94 ARRAY
*bush_argv_a
, *bush_argc_a
;
101 #if defined (ARRAY_VARS)
102 GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v
, funcname_a
);
103 GET_ARRAY_FROM_VAR ("BUSH_SOURCE", bush_source_v
, bush_source_a
);
104 GET_ARRAY_FROM_VAR ("BUSH_LINENO", bush_lineno_v
, bush_lineno_a
);
105 # if defined (DEBUGGER)
106 GET_ARRAY_FROM_VAR ("BUSH_ARGV", bush_argv_v
, bush_argv_a
);
107 GET_ARRAY_FROM_VAR ("BUSH_ARGC", bush_argc_v
, bush_argc_a
);
111 fd
= open (filename
, O_RDONLY
);
113 if (fd
< 0 || (fstat (fd
, &finfo
) == -1))
121 if (((flags
& FEVAL_ENOENTOK
) == 0) || errno
!= ENOENT
)
122 file_error (filename
);
124 if (flags
& FEVAL_LONGJMP
)
126 last_command_exit_value
= EXECUTION_FAILURE
;
127 jump_to_top_level (EXITPROG
);
130 return ((flags
& FEVAL_BUILTIN
) ? EXECUTION_FAILURE
131 : ((errno
== ENOENT
&& (flags
& FEVAL_ENOENTOK
) != 0) ? 0 : -1));
134 errfunc
= ((flags
& FEVAL_BUILTIN
) ? builtin_error
: internal_error
);
136 if (S_ISDIR (finfo
.st_mode
))
138 (*errfunc
) (_("%s: is a directory"), filename
);
140 return ((flags
& FEVAL_BUILTIN
) ? EXECUTION_FAILURE
: -1);
142 else if ((flags
& FEVAL_REGFILE
) && S_ISREG (finfo
.st_mode
) == 0)
144 (*errfunc
) (_("%s: not a regular file"), filename
);
146 return ((flags
& FEVAL_BUILTIN
) ? EXECUTION_FAILURE
: -1);
149 file_size
= (size_t)finfo
.st_size
;
150 /* Check for overflow with large files. */
151 if (file_size
!= finfo
.st_size
|| file_size
+ 1 < file_size
)
153 (*errfunc
) (_("%s: file is too large"), filename
);
155 return ((flags
& FEVAL_BUILTIN
) ? EXECUTION_FAILURE
: -1);
158 if (S_ISREG (finfo
.st_mode
) && file_size
<= SSIZE_MAX
)
160 string
= (char *)xmalloc (1 + file_size
);
161 nr
= read (fd
, string
, file_size
);
166 nr
= zmapfd (fd
, &string
, 0);
172 if (nr
< 0) /* XXX was != file_size, not < 0 */
175 goto file_error_and_exit
;
181 return ((flags
& FEVAL_BUILTIN
) ? EXECUTION_SUCCESS
: 1);
184 if ((flags
& FEVAL_CHECKBINARY
) &&
185 check_binary_file (string
, (nr
> 80) ? 80 : nr
))
188 (*errfunc
) (_("%s: cannot execute binary file"), filename
);
189 return ((flags
& FEVAL_BUILTIN
) ? EX_BINARY_FILE
: -1);
195 for (nnull
= i
= 0; i
< nr
; i
++)
196 if (string
[i
] == '\0')
198 memmove (string
+i
, string
+i
+1, nr
- i
);
200 /* Even if the `check binary' flag is not set, we want to avoid
201 sourcing files with more than 256 null characters -- that
202 probably indicates a binary file. */
203 if ((flags
& FEVAL_BUILTIN
) && ++nnull
> 256)
206 (*errfunc
) (_("%s: cannot execute binary file"), filename
);
207 return ((flags
& FEVAL_BUILTIN
) ? EX_BINARY_FILE
: -1);
212 if (flags
& FEVAL_UNWINDPROT
)
214 begin_unwind_frame ("_evalfile");
216 unwind_protect_int (return_catch_flag
);
217 unwind_protect_jmp_buf (return_catch
);
218 if (flags
& FEVAL_NONINT
)
219 unwind_protect_int (interactive
);
220 unwind_protect_int (sourcelevel
);
224 COPY_PROCENV (return_catch
, old_return_catch
);
225 if (flags
& FEVAL_NONINT
)
226 old_interactive
= interactive
;
229 if (flags
& FEVAL_NONINT
)
235 #if defined (ARRAY_VARS)
236 array_push (bush_source_a
, (char *)filename
);
237 t
= itos (executing_line_number ());
238 array_push (bush_lineno_a
, t
);
240 array_push (funcname_a
, "source"); /* not exactly right */
242 fa
= (struct func_array_state
*)xmalloc (sizeof (struct func_array_state
));
243 fa
->source_a
= bush_source_a
;
244 fa
->source_v
= bush_source_v
;
245 fa
->lineno_a
= bush_lineno_a
;
246 fa
->lineno_v
= bush_lineno_v
;
247 fa
->funcname_a
= funcname_a
;
248 fa
->funcname_v
= funcname_v
;
249 if (flags
& FEVAL_UNWINDPROT
)
250 add_unwind_protect (restore_funcarray_state
, fa
);
252 # if defined (DEBUGGER)
253 /* Have to figure out a better way to do this when `source' is supplied
255 if ((flags
& FEVAL_NOPUSHARGS
) == 0)
257 if (shell_compatibility_level
<= 44)
259 array_push (bush_argv_a
, (char *)filename
); /* XXX - unconditionally? */
260 tt
[0] = '1'; tt
[1] = '\0';
261 array_push (bush_argc_a
, tt
);
262 if (flags
& FEVAL_UNWINDPROT
)
263 add_unwind_protect (pop_args
, 0);
268 /* set the flags to be passed to parse_and_execute */
269 pflags
= SEVAL_RESETLINE
;
270 pflags
|= (flags
& FEVAL_HISTORY
) ? 0 : SEVAL_NOHIST
;
272 if (flags
& FEVAL_BUILTIN
)
273 result
= EXECUTION_SUCCESS
;
275 return_val
= setjmp_nosigs (return_catch
);
277 /* If `return' was seen outside of a function, but in the script, then
278 force parse_and_execute () to clean up. */
281 parse_and_execute_cleanup (-1);
282 result
= return_catch_value
;
285 result
= parse_and_execute (string
, filename
, pflags
);
287 if (flags
& FEVAL_UNWINDPROT
)
288 run_unwind_frame ("_evalfile");
291 if (flags
& FEVAL_NONINT
)
292 interactive
= old_interactive
;
293 #if defined (ARRAY_VARS)
294 restore_funcarray_state (fa
);
295 # if defined (DEBUGGER)
296 if ((flags
& FEVAL_NOPUSHARGS
) == 0)
298 /* Don't need to call pop_args here until we do something better
299 when source is passed arguments (see above). */
300 array_pop (bush_argc_a
);
301 array_pop (bush_argv_a
);
307 COPY_PROCENV (old_return_catch
, return_catch
);
310 /* If we end up with EOF after sourcing a file, which can happen when the file
311 doesn't end with a newline, pretend that it did. */
312 if (current_token
== yacc_EOF
)
313 push_token ('\n'); /* XXX */
315 return ((flags
& FEVAL_BUILTIN
) ? result
: 1);
319 maybe_execute_file (fname
, force_noninteractive
)
321 int force_noninteractive
;
326 filename
= bush_tilde_expand (fname
, 0);
327 flags
= FEVAL_ENOENTOK
;
328 if (force_noninteractive
)
329 flags
|= FEVAL_NONINT
;
330 result
= _evalfile (filename
, flags
);
336 force_execute_file (fname
, force_noninteractive
)
338 int force_noninteractive
;
343 filename
= bush_tilde_expand (fname
, 0);
345 if (force_noninteractive
)
346 flags
|= FEVAL_NONINT
;
347 result
= _evalfile (filename
, flags
);
352 #if defined (HISTORY)
354 fc_execute_file (filename
)
355 const char *filename
;
359 /* We want these commands to show up in the history list if
360 remember_on_history is set. We use FEVAL_BUILTIN to return
361 the result of parse_and_execute. */
362 flags
= FEVAL_ENOENTOK
|FEVAL_HISTORY
|FEVAL_REGFILE
|FEVAL_BUILTIN
;
363 return (_evalfile (filename
, flags
));
368 source_file (filename
, sflags
)
369 const char *filename
;
374 flags
= FEVAL_BUILTIN
|FEVAL_UNWINDPROT
|FEVAL_NONINT
;
376 flags
|= FEVAL_NOPUSHARGS
;
377 /* POSIX shells exit if non-interactive and file error. */
378 if (posixly_correct
&& interactive_shell
== 0 && executing_command_builtin
== 0)
379 flags
|= FEVAL_LONGJMP
;
380 rval
= _evalfile (filename
, flags
);