1 /* Copyright (C) 1996-2003 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 2, 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
21 #if defined (HAVE_UNISTD_H)
25 #include "../bashtypes.h"
26 #include "posixstat.h"
33 #include "../bashansi.h"
34 #include "../bashintl.h"
38 #include "../builtins.h"
41 #include "../execute_cmd.h"
44 # include "../bashhist.h"
53 /* Flags for _evalfile() */
54 #define FEVAL_ENOENTOK 0x001
55 #define FEVAL_BUILTIN 0x002
56 #define FEVAL_UNWINDPROT 0x004
57 #define FEVAL_NONINT 0x008
58 #define FEVAL_LONGJMP 0x010
59 #define FEVAL_HISTORY 0x020
60 #define FEVAL_CHECKBINARY 0x040
61 #define FEVAL_REGFILE 0x080
62 #define FEVAL_NOPUSHARGS 0x100
64 extern int posixly_correct
;
65 extern int indirection_level
, startup_state
, subshell_environment
;
66 extern int return_catch_flag
, return_catch_value
;
67 extern int last_command_exit_value
;
69 /* How many `levels' of sourced files we have. */
73 _evalfile (filename
, flags
)
77 volatile int old_interactive
;
78 procenv_t old_return_catch
;
79 int return_val
, fd
, result
, pflags
;
83 sh_vmsg_func_t
*errfunc
;
84 #if defined (ARRAY_VARS)
85 SHELL_VAR
*funcname_v
, *bash_source_v
, *bash_lineno_v
;
86 ARRAY
*funcname_a
, *bash_source_a
, *bash_lineno_a
;
87 # if defined (DEBUGGER)
88 SHELL_VAR
*bash_argv_v
, *bash_argc_v
;
89 ARRAY
*bash_argv_a
, *bash_argc_a
;
96 #if defined (ARRAY_VARS)
97 GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v
, funcname_a
);
98 GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v
, bash_source_a
);
99 GET_ARRAY_FROM_VAR ("BASH_LINENO", bash_lineno_v
, bash_lineno_a
);
100 # if defined (DEBUGGER)
101 GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v
, bash_argv_a
);
102 GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v
, bash_argc_a
);
106 fd
= open (filename
, O_RDONLY
);
108 if (fd
< 0 || (fstat (fd
, &finfo
) == -1))
111 if (((flags
& FEVAL_ENOENTOK
) == 0) || errno
!= ENOENT
)
112 file_error (filename
);
114 if (flags
& FEVAL_LONGJMP
)
116 last_command_exit_value
= 1;
117 jump_to_top_level (EXITPROG
);
120 return ((flags
& FEVAL_BUILTIN
) ? EXECUTION_FAILURE
121 : ((errno
== ENOENT
) ? 0 : -1));
124 errfunc
= ((flags
& FEVAL_BUILTIN
) ? builtin_error
: internal_error
);
126 if (S_ISDIR (finfo
.st_mode
))
128 (*errfunc
) (_("%s: is a directory"), filename
);
129 return ((flags
& FEVAL_BUILTIN
) ? EXECUTION_FAILURE
: -1);
131 else if ((flags
& FEVAL_REGFILE
) && S_ISREG (finfo
.st_mode
) == 0)
133 (*errfunc
) (_("%s: not a regular file"), filename
);
134 return ((flags
& FEVAL_BUILTIN
) ? EXECUTION_FAILURE
: -1);
137 file_size
= (size_t)finfo
.st_size
;
138 /* Check for overflow with large files. */
139 if (file_size
!= finfo
.st_size
|| file_size
+ 1 < file_size
)
141 (*errfunc
) (_("%s: file is too large"), filename
);
142 return ((flags
& FEVAL_BUILTIN
) ? EXECUTION_FAILURE
: -1);
145 #if defined (__CYGWIN__) && defined (O_TEXT)
146 setmode (fd
, O_TEXT
);
149 string
= (char *)xmalloc (1 + file_size
);
150 result
= read (fd
, string
, file_size
);
151 string
[result
] = '\0';
157 if (result
< 0) /* XXX was != file_size, not < 0 */
160 goto file_error_and_exit
;
166 return ((flags
& FEVAL_BUILTIN
) ? EXECUTION_SUCCESS
: 1);
169 if ((flags
& FEVAL_CHECKBINARY
) &&
170 check_binary_file (string
, (result
> 80) ? 80 : result
))
173 (*errfunc
) ("%s: cannot execute binary file", filename
);
174 return ((flags
& FEVAL_BUILTIN
) ? EX_BINARY_FILE
: -1);
177 if (flags
& FEVAL_UNWINDPROT
)
179 begin_unwind_frame ("_evalfile");
181 unwind_protect_int (return_catch_flag
);
182 unwind_protect_jmp_buf (return_catch
);
183 if (flags
& FEVAL_NONINT
)
184 unwind_protect_int (interactive
);
185 unwind_protect_int (sourcelevel
);
189 COPY_PROCENV (return_catch
, old_return_catch
);
190 if (flags
& FEVAL_NONINT
)
191 old_interactive
= interactive
;
194 if (flags
& FEVAL_NONINT
)
200 #if defined (ARRAY_VARS)
201 array_push (bash_source_a
, (char *)filename
);
202 t
= itos (executing_line_number ());
203 array_push (bash_lineno_a
, t
);
205 array_push (funcname_a
, "source"); /* not exactly right */
206 # if defined (DEBUGGER)
207 /* Have to figure out a better way to do this when `source' is supplied
209 if ((flags
& FEVAL_NOPUSHARGS
) == 0)
211 array_push (bash_argv_a
, (char *)filename
);
212 tt
[0] = '1'; tt
[1] = '\0';
213 array_push (bash_argc_a
, tt
);
218 /* set the flags to be passed to parse_and_execute */
219 pflags
= SEVAL_RESETLINE
;
220 pflags
|= (flags
& FEVAL_HISTORY
) ? 0 : SEVAL_NOHIST
;
222 if (flags
& FEVAL_BUILTIN
)
223 result
= EXECUTION_SUCCESS
;
225 return_val
= setjmp (return_catch
);
227 /* If `return' was seen outside of a function, but in the script, then
228 force parse_and_execute () to clean up. */
231 parse_and_execute_cleanup ();
232 result
= return_catch_value
;
235 result
= parse_and_execute (string
, filename
, pflags
);
237 if (flags
& FEVAL_UNWINDPROT
)
238 run_unwind_frame ("_evalfile");
241 if (flags
& FEVAL_NONINT
)
242 interactive
= old_interactive
;
245 COPY_PROCENV (old_return_catch
, return_catch
);
248 #if defined (ARRAY_VARS)
249 array_pop (bash_source_a
);
250 array_pop (bash_lineno_a
);
251 array_pop (funcname_a
);
252 # if defined (DEBUGGER)
253 if ((flags
& FEVAL_NOPUSHARGS
) == 0)
255 array_pop (bash_argc_a
);
256 array_pop (bash_argv_a
);
261 return ((flags
& FEVAL_BUILTIN
) ? result
: 1);
265 maybe_execute_file (fname
, force_noninteractive
)
267 int force_noninteractive
;
272 filename
= bash_tilde_expand (fname
, 0);
273 flags
= FEVAL_ENOENTOK
;
274 if (force_noninteractive
)
275 flags
|= FEVAL_NONINT
;
276 result
= _evalfile (filename
, flags
);
281 #if defined (HISTORY)
283 fc_execute_file (filename
)
284 const char *filename
;
288 /* We want these commands to show up in the history list if
289 remember_on_history is set. */
290 flags
= FEVAL_ENOENTOK
|FEVAL_HISTORY
|FEVAL_REGFILE
;
291 return (_evalfile (filename
, flags
));
296 source_file (filename
, sflags
)
297 const char *filename
;
302 flags
= FEVAL_BUILTIN
|FEVAL_UNWINDPROT
|FEVAL_NONINT
;
304 flags
|= FEVAL_NOPUSHARGS
;
305 /* POSIX shells exit if non-interactive and file error. */
306 if (posixly_correct
&& !interactive_shell
)
307 flags
|= FEVAL_LONGJMP
;
308 rval
= _evalfile (filename
, flags
);