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