]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/evalfile.c
Imported from ../bash-3.0.16.tar.gz.
[thirdparty/bash.git] / builtins / evalfile.c
CommitLineData
b80f6443 1/* Copyright (C) 1996-2003 Free Software Foundation, Inc.
ccc6cda3
JA
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
bb70624e 7 Software Foundation; either version 2, or (at your option) any later
ccc6cda3
JA
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
bb70624e 17 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
ccc6cda3
JA
18
19#include <config.h>
20
21#if defined (HAVE_UNISTD_H)
22# include <unistd.h>
23#endif
24
d166f048 25#include "../bashtypes.h"
bb70624e
JA
26#include "posixstat.h"
27#include "filecntl.h"
ccc6cda3
JA
28
29#include <stdio.h>
30#include <signal.h>
31#include <errno.h>
32
33#include "../bashansi.h"
b80f6443 34#include "../bashintl.h"
ccc6cda3
JA
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
43#if defined (HISTORY)
44# include "../bashhist.h"
45#endif
46
47#include "common.h"
48
49#if !defined (errno)
50extern int errno;
51#endif
52
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
d166f048 59#define FEVAL_HISTORY 0x020
28ef6c31 60#define FEVAL_CHECKBINARY 0x040
f73dda09 61#define FEVAL_REGFILE 0x080
b80f6443 62#define FEVAL_NOPUSHARGS 0x100
ccc6cda3 63
f73dda09 64extern int posixly_correct;
ccc6cda3
JA
65extern int indirection_level, startup_state, subshell_environment;
66extern int return_catch_flag, return_catch_value;
67extern int last_command_exit_value;
68
69/* How many `levels' of sourced files we have. */
70int sourcelevel = 0;
71
72static int
73_evalfile (filename, flags)
f73dda09 74 const char *filename;
ccc6cda3
JA
75 int flags;
76{
77 volatile int old_interactive;
78 procenv_t old_return_catch;
d166f048 79 int return_val, fd, result, pflags;
ccc6cda3
JA
80 char *string;
81 struct stat finfo;
cce855bc 82 size_t file_size;
f73dda09 83 sh_vmsg_func_t *errfunc;
b80f6443
JA
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;
90# endif
91 char *t, tt[2];
92#endif
f73dda09
JA
93
94 USE_VAR(pflags);
ccc6cda3 95
b80f6443
JA
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);
103# endif
104#endif
105
ccc6cda3
JA
106 fd = open (filename, O_RDONLY);
107
108 if (fd < 0 || (fstat (fd, &finfo) == -1))
109 {
110file_error_and_exit:
111 if (((flags & FEVAL_ENOENTOK) == 0) || errno != ENOENT)
112 file_error (filename);
113
114 if (flags & FEVAL_LONGJMP)
28ef6c31 115 {
ccc6cda3
JA
116 last_command_exit_value = 1;
117 jump_to_top_level (EXITPROG);
118 }
119
120 return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE
121 : ((errno == ENOENT) ? 0 : -1));
122 }
123
f73dda09 124 errfunc = ((flags & FEVAL_BUILTIN) ? builtin_error : internal_error);
ccc6cda3
JA
125
126 if (S_ISDIR (finfo.st_mode))
127 {
b80f6443 128 (*errfunc) (_("%s: is a directory"), filename);
ccc6cda3
JA
129 return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
130 }
f73dda09 131 else if ((flags & FEVAL_REGFILE) && S_ISREG (finfo.st_mode) == 0)
ccc6cda3 132 {
b80f6443 133 (*errfunc) (_("%s: not a regular file"), filename);
ccc6cda3
JA
134 return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
135 }
136
cce855bc
JA
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)
140 {
b80f6443 141 (*errfunc) (_("%s: file is too large"), filename);
cce855bc
JA
142 return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
143 }
28ef6c31
JA
144
145#if defined (__CYGWIN__) && defined (O_TEXT)
146 setmode (fd, O_TEXT);
147#endif
148
f73dda09 149 string = (char *)xmalloc (1 + file_size);
cce855bc 150 result = read (fd, string, file_size);
ccc6cda3
JA
151 string[result] = '\0';
152
153 return_val = errno;
154 close (fd);
155 errno = return_val;
156
cce855bc 157 if (result < 0) /* XXX was != file_size, not < 0 */
ccc6cda3
JA
158 {
159 free (string);
160 goto file_error_and_exit;
161 }
162
cce855bc
JA
163 if (result == 0)
164 {
165 free (string);
166 return ((flags & FEVAL_BUILTIN) ? EXECUTION_SUCCESS : 1);
167 }
168
28ef6c31 169 if ((flags & FEVAL_CHECKBINARY) &&
f73dda09 170 check_binary_file (string, (result > 80) ? 80 : result))
ccc6cda3
JA
171 {
172 free (string);
173 (*errfunc) ("%s: cannot execute binary file", filename);
174 return ((flags & FEVAL_BUILTIN) ? EX_BINARY_FILE : -1);
175 }
176
177 if (flags & FEVAL_UNWINDPROT)
178 {
179 begin_unwind_frame ("_evalfile");
180
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);
186 }
187 else
188 {
189 COPY_PROCENV (return_catch, old_return_catch);
190 if (flags & FEVAL_NONINT)
191 old_interactive = interactive;
192 }
193
194 if (flags & FEVAL_NONINT)
195 interactive = 0;
196
197 return_catch_flag++;
198 sourcelevel++;
199
b80f6443
JA
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);
204 free (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
208 arguments */
209 if ((flags & FEVAL_NOPUSHARGS) == 0)
210 {
211 array_push (bash_argv_a, (char *)filename);
212 tt[0] = '1'; tt[1] = '\0';
213 array_push (bash_argc_a, tt);
214 }
215# endif
216#endif
217
d166f048 218 /* set the flags to be passed to parse_and_execute */
b80f6443
JA
219 pflags = SEVAL_RESETLINE;
220 pflags |= (flags & FEVAL_HISTORY) ? 0 : SEVAL_NOHIST;
d166f048 221
ccc6cda3
JA
222 if (flags & FEVAL_BUILTIN)
223 result = EXECUTION_SUCCESS;
224
225 return_val = setjmp (return_catch);
226
227 /* If `return' was seen outside of a function, but in the script, then
228 force parse_and_execute () to clean up. */
229 if (return_val)
230 {
231 parse_and_execute_cleanup ();
232 result = return_catch_value;
233 }
234 else
d166f048 235 result = parse_and_execute (string, filename, pflags);
ccc6cda3
JA
236
237 if (flags & FEVAL_UNWINDPROT)
238 run_unwind_frame ("_evalfile");
239 else
240 {
241 if (flags & FEVAL_NONINT)
242 interactive = old_interactive;
243 return_catch_flag--;
244 sourcelevel--;
245 COPY_PROCENV (old_return_catch, return_catch);
246 }
247
b80f6443
JA
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)
254 {
255 array_pop (bash_argc_a);
256 array_pop (bash_argv_a);
257 }
258# endif
259#endif
260
ccc6cda3
JA
261 return ((flags & FEVAL_BUILTIN) ? result : 1);
262}
263
264int
265maybe_execute_file (fname, force_noninteractive)
f73dda09 266 const char *fname;
ccc6cda3
JA
267 int force_noninteractive;
268{
269 char *filename;
270 int result, flags;
271
7117c2d2 272 filename = bash_tilde_expand (fname, 0);
ccc6cda3
JA
273 flags = FEVAL_ENOENTOK;
274 if (force_noninteractive)
275 flags |= FEVAL_NONINT;
276 result = _evalfile (filename, flags);
277 free (filename);
278 return result;
279}
280
d166f048
JA
281#if defined (HISTORY)
282int
283fc_execute_file (filename)
f73dda09 284 const char *filename;
d166f048
JA
285{
286 int flags;
287
288 /* We want these commands to show up in the history list if
289 remember_on_history is set. */
f73dda09 290 flags = FEVAL_ENOENTOK|FEVAL_HISTORY|FEVAL_REGFILE;
d166f048
JA
291 return (_evalfile (filename, flags));
292}
293#endif /* HISTORY */
294
ccc6cda3 295int
b80f6443 296source_file (filename, sflags)
f73dda09 297 const char *filename;
b80f6443 298 int sflags;
ccc6cda3 299{
b80f6443 300 int flags, rval;
ccc6cda3
JA
301
302 flags = FEVAL_BUILTIN|FEVAL_UNWINDPROT|FEVAL_NONINT;
b80f6443
JA
303 if (sflags)
304 flags |= FEVAL_NOPUSHARGS;
ccc6cda3
JA
305 /* POSIX shells exit if non-interactive and file error. */
306 if (posixly_correct && !interactive_shell)
307 flags |= FEVAL_LONGJMP;
b80f6443
JA
308 rval = _evalfile (filename, flags);
309
310 run_return_trap ();
311 return rval;
ccc6cda3 312}