improve of cmpl.
[bush.git] / builtins / evalfile.c
blob0ea9240c9a3a55970199459c9fd149c12daaa174
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/>.
21 #include <config.h>
23 #if defined (HAVE_UNISTD_H)
24 # include <unistd.h>
25 #endif
27 #include "../src/bushtypes.h"
28 #include "posixstat.h"
29 #include "filecntl.h"
31 #include <stdio.h>
32 #include <signal.h>
33 #include <errno.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>
49 #if defined (HISTORY)
50 # include "../src/bushhist.h"
51 #endif
53 #include <typemax.h>
55 #include "common.h"
57 #if !defined (errno)
58 extern int errno;
59 #endif
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. */
73 int sourcelevel = 0;
75 static int
76 _evalfile (filename, flags)
77 const char *filename;
78 int 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) */
84 char *string;
85 struct stat finfo;
86 size_t file_size;
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;
95 # endif
96 char *t, tt[2];
97 #endif
99 USE_VAR(pflags);
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);
108 # endif
109 #endif
111 fd = open (filename, O_RDONLY);
113 if (fd < 0 || (fstat (fd, &finfo) == -1))
115 i = errno;
116 if (fd >= 0)
117 close (fd);
118 errno = i;
120 file_error_and_exit:
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);
139 close (fd);
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);
145 close (fd);
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);
154 close (fd);
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);
162 if (nr >= 0)
163 string[nr] = '\0';
165 else
166 nr = zmapfd (fd, &string, 0);
168 return_val = errno;
169 close (fd);
170 errno = return_val;
172 if (nr < 0) /* XXX was != file_size, not < 0 */
174 free (string);
175 goto file_error_and_exit;
178 if (nr == 0)
180 free (string);
181 return ((flags & FEVAL_BUILTIN) ? EXECUTION_SUCCESS : 1);
184 if ((flags & FEVAL_CHECKBINARY) &&
185 check_binary_file (string, (nr > 80) ? 80 : nr))
187 free (string);
188 (*errfunc) (_("%s: cannot execute binary file"), filename);
189 return ((flags & FEVAL_BUILTIN) ? EX_BINARY_FILE : -1);
192 i = strlen (string);
193 if (i < nr)
195 for (nnull = i = 0; i < nr; i++)
196 if (string[i] == '\0')
198 memmove (string+i, string+i+1, nr - i);
199 nr--;
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)
205 free (string);
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);
222 else
224 COPY_PROCENV (return_catch, old_return_catch);
225 if (flags & FEVAL_NONINT)
226 old_interactive = interactive;
229 if (flags & FEVAL_NONINT)
230 interactive = 0;
232 return_catch_flag++;
233 sourcelevel++;
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);
239 free (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
254 arguments */
255 if ((flags & FEVAL_NOPUSHARGS) == 0)
257 if (shell_compatibility_level <= 44)
258 init_bush_argv ();
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);
265 # endif
266 #endif
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. */
279 if (return_val)
281 parse_and_execute_cleanup (-1);
282 result = return_catch_value;
284 else
285 result = parse_and_execute (string, filename, pflags);
287 if (flags & FEVAL_UNWINDPROT)
288 run_unwind_frame ("_evalfile");
289 else
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);
303 # endif
304 #endif
305 return_catch_flag--;
306 sourcelevel--;
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)
320 const char *fname;
321 int force_noninteractive;
323 char *filename;
324 int result, flags;
326 filename = bush_tilde_expand (fname, 0);
327 flags = FEVAL_ENOENTOK;
328 if (force_noninteractive)
329 flags |= FEVAL_NONINT;
330 result = _evalfile (filename, flags);
331 free (filename);
332 return result;
336 force_execute_file (fname, force_noninteractive)
337 const char *fname;
338 int force_noninteractive;
340 char *filename;
341 int result, flags;
343 filename = bush_tilde_expand (fname, 0);
344 flags = 0;
345 if (force_noninteractive)
346 flags |= FEVAL_NONINT;
347 result = _evalfile (filename, flags);
348 free (filename);
349 return result;
352 #if defined (HISTORY)
354 fc_execute_file (filename)
355 const char *filename;
357 int flags;
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));
365 #endif /* HISTORY */
368 source_file (filename, sflags)
369 const char *filename;
370 int sflags;
372 int flags, rval;
374 flags = FEVAL_BUILTIN|FEVAL_UNWINDPROT|FEVAL_NONINT;
375 if (sflags)
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);
382 run_return_trap ();
383 return rval;