1 /* Copyright (C) 1996 Free Software Foundation, Inc.
3 This file is part of GNU Bash, the Bourne Again SHell.
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 1, or (at your option) any later
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
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 #if defined (HAVE_UNISTD_H)
25 #include <sys/types.h>
26 #include "../posixstat.h"
27 #include "../filecntl.h"
33 #include "../bashansi.h"
37 #include "../builtins.h"
40 #include "../execute_cmd.h"
43 # include "../bashhist.h"
52 /* Flags for _evalfile() */
53 #define FEVAL_ENOENTOK 0x001
54 #define FEVAL_BUILTIN 0x002
55 #define FEVAL_UNWINDPROT 0x004
56 #define FEVAL_NONINT 0x008
57 #define FEVAL_LONGJMP 0x010
59 extern int interactive, interactive_shell, posixly_correct;
60 extern int indirection_level, startup_state, subshell_environment;
61 extern int return_catch_flag, return_catch_value;
62 extern int last_command_exit_value;
64 /* How many `levels' of sourced files we have. */
68 _evalfile (filename, flags)
72 volatile int old_interactive;
73 procenv_t old_return_catch;
74 int return_val, fd, result;
79 fd = open (filename, O_RDONLY);
81 if (fd < 0 || (fstat (fd, &finfo) == -1))
84 if (((flags & FEVAL_ENOENTOK) == 0) || errno != ENOENT)
85 file_error (filename);
87 if (flags & FEVAL_LONGJMP)
89 last_command_exit_value = 1;
90 jump_to_top_level (EXITPROG);
93 return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE
94 : ((errno == ENOENT) ? 0 : -1));
97 errfunc = (VFunction *)((flags & FEVAL_BUILTIN) ? builtin_error : internal_error);
99 if (S_ISDIR (finfo.st_mode))
101 (*errfunc) ("%s: is a directory", filename);
102 return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
104 else if (S_ISREG (finfo.st_mode) == 0)
106 (*errfunc) ("%s: not a regular file", filename);
107 return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
110 string = xmalloc (1 + (int)finfo.st_size);
111 result = read (fd, string, finfo.st_size);
112 string[result] = '\0';
118 if (result != (int)finfo.st_size)
121 goto file_error_and_exit;
124 if (check_binary_file ((unsigned char *)string, (result > 80) ? 80 : result))
127 (*errfunc) ("%s: cannot execute binary file", filename);
128 return ((flags & FEVAL_BUILTIN) ? EX_BINARY_FILE : -1);
131 if (flags & FEVAL_UNWINDPROT)
133 begin_unwind_frame ("_evalfile");
135 unwind_protect_int (return_catch_flag);
136 unwind_protect_jmp_buf (return_catch);
137 if (flags & FEVAL_NONINT)
138 unwind_protect_int (interactive);
139 unwind_protect_int (sourcelevel);
143 COPY_PROCENV (return_catch, old_return_catch);
144 if (flags & FEVAL_NONINT)
145 old_interactive = interactive;
148 if (flags & FEVAL_NONINT)
154 if (flags & FEVAL_BUILTIN)
155 result = EXECUTION_SUCCESS;
157 return_val = setjmp (return_catch);
159 /* If `return' was seen outside of a function, but in the script, then
160 force parse_and_execute () to clean up. */
163 parse_and_execute_cleanup ();
164 result = return_catch_value;
167 result = parse_and_execute (string, filename, -1);
169 if (flags & FEVAL_UNWINDPROT)
170 run_unwind_frame ("_evalfile");
173 if (flags & FEVAL_NONINT)
174 interactive = old_interactive;
177 COPY_PROCENV (old_return_catch, return_catch);
180 return ((flags & FEVAL_BUILTIN) ? result : 1);
184 maybe_execute_file (fname, force_noninteractive)
186 int force_noninteractive;
191 filename = bash_tilde_expand (fname);
192 flags = FEVAL_ENOENTOK;
193 if (force_noninteractive)
194 flags |= FEVAL_NONINT;
195 result = _evalfile (filename, flags);
201 source_file (filename)
206 flags = FEVAL_BUILTIN|FEVAL_UNWINDPROT|FEVAL_NONINT;
207 /* POSIX shells exit if non-interactive and file error. */
208 if (posixly_correct && !interactive_shell)
209 flags |= FEVAL_LONGJMP;
210 return (_evalfile (filename, flags));