81be017bd36b44a66144c5f74cd2b7da7f313ec2
[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 #include "../trap.h"
43
44 #if defined (HISTORY)
45 #  include "../bashhist.h"
46 #endif
47
48 #include "common.h"
49
50 #if !defined (errno)
51 extern 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
65 extern int posixly_correct;
66 extern int indirection_level, startup_state, subshell_environment;
67 extern int return_catch_flag, return_catch_value;
68 extern int last_command_exit_value;
69
70 /* How many `levels' of sourced files we have. */
71 int sourcelevel = 0;
72
73 static 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     {
111 file_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
272 int
273 maybe_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)
290 int
291 fc_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
303 int
304 source_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 }