Imported from ../bash-3.0.tar.gz.
[platform/upstream/bash.git] / builtins / evalfile.c
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
43 #if defined (HISTORY)
44 #  include "../bashhist.h"
45 #endif
46
47 #include "common.h"
48
49 #if !defined (errno)
50 extern 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
59 #define FEVAL_HISTORY           0x020
60 #define FEVAL_CHECKBINARY       0x040
61 #define FEVAL_REGFILE           0x080
62 #define FEVAL_NOPUSHARGS        0x100
63
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;
68
69 /* How many `levels' of sourced files we have. */
70 int sourcelevel = 0;
71
72 static int
73 _evalfile (filename, flags)
74      const char *filename;
75      int flags;
76 {
77   volatile int old_interactive;
78   procenv_t old_return_catch;
79   int return_val, fd, result, pflags;
80   char *string;
81   struct stat finfo;
82   size_t file_size;
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;
90 #  endif
91   char *t, tt[2];
92 #endif
93
94   USE_VAR(pflags);
95
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   
106   fd = open (filename, O_RDONLY);
107
108   if (fd < 0 || (fstat (fd, &finfo) == -1))
109     {
110 file_error_and_exit:
111       if (((flags & FEVAL_ENOENTOK) == 0) || errno != ENOENT)
112         file_error (filename);
113
114       if (flags & FEVAL_LONGJMP)
115         {
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
124   errfunc = ((flags & FEVAL_BUILTIN) ? builtin_error : internal_error);
125
126   if (S_ISDIR (finfo.st_mode))
127     {
128       (*errfunc) (_("%s: is a directory"), filename);
129       return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
130     }
131   else if ((flags & FEVAL_REGFILE) && S_ISREG (finfo.st_mode) == 0)
132     {
133       (*errfunc) (_("%s: not a regular file"), filename);
134       return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
135     }
136
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     {
141       (*errfunc) (_("%s: file is too large"), filename);
142       return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
143     }      
144
145 #if defined (__CYGWIN__) && defined (O_TEXT)
146   setmode (fd, O_TEXT);
147 #endif
148
149   string = (char *)xmalloc (1 + file_size);
150   result = read (fd, string, file_size);
151   string[result] = '\0';
152
153   return_val = errno;
154   close (fd);
155   errno = return_val;
156
157   if (result < 0)               /* XXX was != file_size, not < 0 */
158     {
159       free (string);
160       goto file_error_and_exit;
161     }
162
163   if (result == 0)
164     {
165       free (string);
166       return ((flags & FEVAL_BUILTIN) ? EXECUTION_SUCCESS : 1);
167     }
168       
169   if ((flags & FEVAL_CHECKBINARY) && 
170       check_binary_file (string, (result > 80) ? 80 : result))
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
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
218   /* set the flags to be passed to parse_and_execute */
219   pflags = SEVAL_RESETLINE;
220   pflags |= (flags & FEVAL_HISTORY) ? 0 : SEVAL_NOHIST;
221
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
235     result = parse_and_execute (string, filename, pflags);
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
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
261   return ((flags & FEVAL_BUILTIN) ? result : 1);
262 }
263
264 int
265 maybe_execute_file (fname, force_noninteractive)
266      const char *fname;
267      int force_noninteractive;
268 {
269   char *filename;
270   int result, flags;
271
272   filename = bash_tilde_expand (fname, 0);
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
281 #if defined (HISTORY)
282 int
283 fc_execute_file (filename)
284      const char *filename;
285 {
286   int flags;
287
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));
292 }
293 #endif /* HISTORY */
294
295 int
296 source_file (filename, sflags)
297      const char *filename;
298      int sflags;
299 {
300   int flags, rval;
301
302   flags = FEVAL_BUILTIN|FEVAL_UNWINDPROT|FEVAL_NONINT;
303   if (sflags)
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);
309
310   run_return_trap ();
311   return rval;
312 }