source: vendor/bash/3.1/builtins/evalfile.c

Last change on this file was 3228, checked in by bird, 18 years ago

bash 3.1

File size: 8.0 KB
Line 
1/* Copyright (C) 1996-2003 Free Software Foundation, Inc.
2
3 This file is part of GNU Bash, the Bourne Again SHell.
4
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
8 version.
9
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
13 for more details.
14
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. */
18
19#include <config.h>
20
21#if defined (HAVE_UNISTD_H)
22# include <unistd.h>
23#endif
24
25#include "../bashtypes.h"
26#include "posixstat.h"
27#include "filecntl.h"
28
29#include <stdio.h>
30#include <signal.h>
31#include <errno.h>
32
33#include "../bashansi.h"
34#include "../bashintl.h"
35
36#include "../shell.h"
37#include "../jobs.h"
38#include "../builtins.h"
39#include "../flags.h"
40#include "../input.h"
41#include "../execute_cmd.h"
42#include "../trap.h"
43
44#if defined (HISTORY)
45# include "../bashhist.h"
46#endif
47
48#include "common.h"
49
50#if !defined (errno)
51extern int errno;
52#endif
53
54/* Flags for _evalfile() */
55#define FEVAL_ENOENTOK 0x001
56#define FEVAL_BUILTIN 0x002
57#define FEVAL_UNWINDPROT 0x004
58#define FEVAL_NONINT 0x008
59#define FEVAL_LONGJMP 0x010
60#define FEVAL_HISTORY 0x020
61#define FEVAL_CHECKBINARY 0x040
62#define FEVAL_REGFILE 0x080
63#define FEVAL_NOPUSHARGS 0x100
64
65extern int posixly_correct;
66extern int indirection_level, startup_state, subshell_environment;
67extern int return_catch_flag, return_catch_value;
68extern int last_command_exit_value;
69
70/* How many `levels' of sourced files we have. */
71int sourcelevel = 0;
72
73static int
74_evalfile (filename, flags)
75 const char *filename;
76 int flags;
77{
78 volatile int old_interactive;
79 procenv_t old_return_catch;
80 int return_val, fd, result, pflags;
81 char *string;
82 struct stat finfo;
83 size_t file_size;
84 sh_vmsg_func_t *errfunc;
85#if defined (ARRAY_VARS)
86 SHELL_VAR *funcname_v, *nfv, *bash_source_v, *bash_lineno_v;
87 ARRAY *funcname_a, *bash_source_a, *bash_lineno_a;
88# if defined (DEBUGGER)
89 SHELL_VAR *bash_argv_v, *bash_argc_v;
90 ARRAY *bash_argv_a, *bash_argc_a;
91# endif
92 char *t, tt[2];
93#endif
94
95 USE_VAR(pflags);
96
97#if defined (ARRAY_VARS)
98 GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v, funcname_a);
99 GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v, bash_source_a);
100 GET_ARRAY_FROM_VAR ("BASH_LINENO", bash_lineno_v, bash_lineno_a);
101# if defined (DEBUGGER)
102 GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
103 GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
104# endif
105#endif
106
107 fd = open (filename, O_RDONLY);
108
109 if (fd < 0 || (fstat (fd, &finfo) == -1))
110 {
111file_error_and_exit:
112 if (((flags & FEVAL_ENOENTOK) == 0) || errno != ENOENT)
113 file_error (filename);
114
115 if (flags & FEVAL_LONGJMP)
116 {
117 last_command_exit_value = 1;
118 jump_to_top_level (EXITPROG);
119 }
120
121 return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE
122 : ((errno == ENOENT) ? 0 : -1));
123 }
124
125 errfunc = ((flags & FEVAL_BUILTIN) ? builtin_error : internal_error);
126
127 if (S_ISDIR (finfo.st_mode))
128 {
129 (*errfunc) (_("%s: is a directory"), filename);
130 return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
131 }
132 else if ((flags & FEVAL_REGFILE) && S_ISREG (finfo.st_mode) == 0)
133 {
134 (*errfunc) (_("%s: not a regular file"), filename);
135 return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
136 }
137
138 file_size = (size_t)finfo.st_size;
139 /* Check for overflow with large files. */
140 if (file_size != finfo.st_size || file_size + 1 < file_size)
141 {
142 (*errfunc) (_("%s: file is too large"), filename);
143 return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
144 }
145
146#if defined (__CYGWIN__) && defined (O_TEXT)
147 setmode (fd, O_TEXT);
148#endif
149
150 string = (char *)xmalloc (1 + file_size);
151 result = read (fd, string, file_size);
152 string[result] = '\0';
153
154 return_val = errno;
155 close (fd);
156 errno = return_val;
157
158 if (result < 0) /* XXX was != file_size, not < 0 */
159 {
160 free (string);
161 goto file_error_and_exit;
162 }
163
164 if (result == 0)
165 {
166 free (string);
167 return ((flags & FEVAL_BUILTIN) ? EXECUTION_SUCCESS : 1);
168 }
169
170 if ((flags & FEVAL_CHECKBINARY) &&
171 check_binary_file (string, (result > 80) ? 80 : result))
172 {
173 free (string);
174 (*errfunc) ("%s: cannot execute binary file", filename);
175 return ((flags & FEVAL_BUILTIN) ? EX_BINARY_FILE : -1);
176 }
177
178 if (flags & FEVAL_UNWINDPROT)
179 {
180 begin_unwind_frame ("_evalfile");
181
182 unwind_protect_int (return_catch_flag);
183 unwind_protect_jmp_buf (return_catch);
184 if (flags & FEVAL_NONINT)
185 unwind_protect_int (interactive);
186 unwind_protect_int (sourcelevel);
187 }
188 else
189 {
190 COPY_PROCENV (return_catch, old_return_catch);
191 if (flags & FEVAL_NONINT)
192 old_interactive = interactive;
193 }
194
195 if (flags & FEVAL_NONINT)
196 interactive = 0;
197
198 return_catch_flag++;
199 sourcelevel++;
200
201#if defined (ARRAY_VARS)
202 array_push (bash_source_a, (char *)filename);
203 t = itos (executing_line_number ());
204 array_push (bash_lineno_a, t);
205 free (t);
206 array_push (funcname_a, "source"); /* not exactly right */
207# if defined (DEBUGGER)
208 /* Have to figure out a better way to do this when `source' is supplied
209 arguments */
210 if ((flags & FEVAL_NOPUSHARGS) == 0)
211 {
212 array_push (bash_argv_a, (char *)filename);
213 tt[0] = '1'; tt[1] = '\0';
214 array_push (bash_argc_a, tt);
215 }
216# endif
217#endif
218
219 /* set the flags to be passed to parse_and_execute */
220 pflags = SEVAL_RESETLINE;
221 pflags |= (flags & FEVAL_HISTORY) ? 0 : SEVAL_NOHIST;
222
223 if (flags & FEVAL_BUILTIN)
224 result = EXECUTION_SUCCESS;
225
226 return_val = setjmp (return_catch);
227
228 /* If `return' was seen outside of a function, but in the script, then
229 force parse_and_execute () to clean up. */
230 if (return_val)
231 {
232 parse_and_execute_cleanup ();
233 result = return_catch_value;
234 }
235 else
236 result = parse_and_execute (string, filename, pflags);
237
238 if (flags & FEVAL_UNWINDPROT)
239 run_unwind_frame ("_evalfile");
240 else
241 {
242 if (flags & FEVAL_NONINT)
243 interactive = old_interactive;
244 return_catch_flag--;
245 sourcelevel--;
246 COPY_PROCENV (old_return_catch, return_catch);
247 }
248
249#if defined (ARRAY_VARS)
250 /* These two variables cannot be unset, and cannot be affected by the
251 sourced file. */
252 array_pop (bash_source_a);
253 array_pop (bash_lineno_a);
254
255 /* FUNCNAME can be unset, and so can potentially be changed by the
256 sourced file. */
257 GET_ARRAY_FROM_VAR ("FUNCNAME", nfv, funcname_a);
258 if (nfv == funcname_v)
259 array_pop (funcname_a);
260# if defined (DEBUGGER)
261 if ((flags & FEVAL_NOPUSHARGS) == 0)
262 {
263 array_pop (bash_argc_a);
264 array_pop (bash_argv_a);
265 }
266# endif
267#endif
268
269 return ((flags & FEVAL_BUILTIN) ? result : 1);
270}
271
272int
273maybe_execute_file (fname, force_noninteractive)
274 const char *fname;
275 int force_noninteractive;
276{
277 char *filename;
278 int result, flags;
279
280 filename = bash_tilde_expand (fname, 0);
281 flags = FEVAL_ENOENTOK;
282 if (force_noninteractive)
283 flags |= FEVAL_NONINT;
284 result = _evalfile (filename, flags);
285 free (filename);
286 return result;
287}
288
289#if defined (HISTORY)
290int
291fc_execute_file (filename)
292 const char *filename;
293{
294 int flags;
295
296 /* We want these commands to show up in the history list if
297 remember_on_history is set. */
298 flags = FEVAL_ENOENTOK|FEVAL_HISTORY|FEVAL_REGFILE;
299 return (_evalfile (filename, flags));
300}
301#endif /* HISTORY */
302
303int
304source_file (filename, sflags)
305 const char *filename;
306 int sflags;
307{
308 int flags, rval;
309
310 flags = FEVAL_BUILTIN|FEVAL_UNWINDPROT|FEVAL_NONINT;
311 if (sflags)
312 flags |= FEVAL_NOPUSHARGS;
313 /* POSIX shells exit if non-interactive and file error. */
314 if (posixly_correct && !interactive_shell)
315 flags |= FEVAL_LONGJMP;
316 rval = _evalfile (filename, flags);
317
318 run_return_trap ();
319 return rval;
320}
Note: See TracBrowser for help on using the repository browser.