i-bash/builtins/evalfile.c

332 lines
8.2 KiB
C
Raw Normal View History

2009-01-12 13:36:28 +00:00
/* evalfile.c - read and evaluate commands from a file or file descriptor */
/* Copyright (C) 1996-2009 Free Software Foundation, Inc.
1996-12-23 17:02:34 +00:00
This file is part of GNU Bash, the Bourne Again SHell.
2009-01-12 13:36:28 +00:00
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
1996-12-23 17:02:34 +00:00
2009-01-12 13:36:28 +00:00
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
1996-12-23 17:02:34 +00:00
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
1997-06-05 14:59:13 +00:00
#include "../bashtypes.h"
2000-03-17 21:46:59 +00:00
#include "posixstat.h"
#include "filecntl.h"
1996-12-23 17:02:34 +00:00
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include "../bashansi.h"
2004-07-27 13:29:18 +00:00
#include "../bashintl.h"
1996-12-23 17:02:34 +00:00
#include "../shell.h"
#include "../jobs.h"
#include "../builtins.h"
#include "../flags.h"
#include "../input.h"
#include "../execute_cmd.h"
2005-12-07 14:08:12 +00:00
#include "../trap.h"
1996-12-23 17:02:34 +00:00
#if defined (HISTORY)
# include "../bashhist.h"
#endif
2009-01-12 13:36:28 +00:00
#include <typemax.h>
1996-12-23 17:02:34 +00:00
#include "common.h"
#if !defined (errno)
extern int errno;
#endif
/* Flags for _evalfile() */
#define FEVAL_ENOENTOK 0x001
#define FEVAL_BUILTIN 0x002
#define FEVAL_UNWINDPROT 0x004
#define FEVAL_NONINT 0x008
#define FEVAL_LONGJMP 0x010
1997-06-05 14:59:13 +00:00
#define FEVAL_HISTORY 0x020
2001-04-06 19:14:31 +00:00
#define FEVAL_CHECKBINARY 0x040
2001-11-13 17:56:06 +00:00
#define FEVAL_REGFILE 0x080
2004-07-27 13:29:18 +00:00
#define FEVAL_NOPUSHARGS 0x100
1996-12-23 17:02:34 +00:00
2001-11-13 17:56:06 +00:00
extern int posixly_correct;
2006-10-10 14:15:34 +00:00
extern int indirection_level, subshell_environment;
1996-12-23 17:02:34 +00:00
extern int return_catch_flag, return_catch_value;
extern int last_command_exit_value;
/* How many `levels' of sourced files we have. */
int sourcelevel = 0;
static int
_evalfile (filename, flags)
2001-11-13 17:56:06 +00:00
const char *filename;
1996-12-23 17:02:34 +00:00
int flags;
{
volatile int old_interactive;
procenv_t old_return_catch;
1997-06-05 14:59:13 +00:00
int return_val, fd, result, pflags;
2009-01-12 13:36:28 +00:00
ssize_t nr; /* return value from read(2) */
1996-12-23 17:02:34 +00:00
char *string;
struct stat finfo;
1998-04-17 19:52:44 +00:00
size_t file_size;
2001-11-13 17:56:06 +00:00
sh_vmsg_func_t *errfunc;
2004-07-27 13:29:18 +00:00
#if defined (ARRAY_VARS)
2005-12-07 14:08:12 +00:00
SHELL_VAR *funcname_v, *nfv, *bash_source_v, *bash_lineno_v;
2004-07-27 13:29:18 +00:00
ARRAY *funcname_a, *bash_source_a, *bash_lineno_a;
# if defined (DEBUGGER)
SHELL_VAR *bash_argv_v, *bash_argc_v;
ARRAY *bash_argv_a, *bash_argc_a;
# endif
char *t, tt[2];
#endif
2001-11-13 17:56:06 +00:00
USE_VAR(pflags);
1996-12-23 17:02:34 +00:00
2004-07-27 13:29:18 +00:00
#if defined (ARRAY_VARS)
GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v, funcname_a);
GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v, bash_source_a);
GET_ARRAY_FROM_VAR ("BASH_LINENO", bash_lineno_v, bash_lineno_a);
# if defined (DEBUGGER)
GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
# endif
#endif
1996-12-23 17:02:34 +00:00
fd = open (filename, O_RDONLY);
if (fd < 0 || (fstat (fd, &finfo) == -1))
{
file_error_and_exit:
if (((flags & FEVAL_ENOENTOK) == 0) || errno != ENOENT)
file_error (filename);
if (flags & FEVAL_LONGJMP)
2001-04-06 19:14:31 +00:00
{
1996-12-23 17:02:34 +00:00
last_command_exit_value = 1;
jump_to_top_level (EXITPROG);
}
return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE
: ((errno == ENOENT) ? 0 : -1));
}
2001-11-13 17:56:06 +00:00
errfunc = ((flags & FEVAL_BUILTIN) ? builtin_error : internal_error);
1996-12-23 17:02:34 +00:00
if (S_ISDIR (finfo.st_mode))
{
2004-07-27 13:29:18 +00:00
(*errfunc) (_("%s: is a directory"), filename);
1996-12-23 17:02:34 +00:00
return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
}
2001-11-13 17:56:06 +00:00
else if ((flags & FEVAL_REGFILE) && S_ISREG (finfo.st_mode) == 0)
1996-12-23 17:02:34 +00:00
{
2004-07-27 13:29:18 +00:00
(*errfunc) (_("%s: not a regular file"), filename);
1996-12-23 17:02:34 +00:00
return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
}
1998-04-17 19:52:44 +00:00
file_size = (size_t)finfo.st_size;
/* Check for overflow with large files. */
if (file_size != finfo.st_size || file_size + 1 < file_size)
{
2004-07-27 13:29:18 +00:00
(*errfunc) (_("%s: file is too large"), filename);
1998-04-17 19:52:44 +00:00
return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
}
2001-04-06 19:14:31 +00:00
#if defined (__CYGWIN__) && defined (O_TEXT)
setmode (fd, O_TEXT);
#endif
2009-01-12 13:36:28 +00:00
if (S_ISREG (finfo.st_mode) && file_size <= SSIZE_MAX)
{
string = (char *)xmalloc (1 + file_size);
nr = read (fd, string, file_size);
if (nr >= 0)
string[nr] = '\0';
}
else
nr = zmapfd (fd, &string, 0);
1996-12-23 17:02:34 +00:00
return_val = errno;
close (fd);
errno = return_val;
2009-01-12 13:36:28 +00:00
if (nr < 0) /* XXX was != file_size, not < 0 */
1996-12-23 17:02:34 +00:00
{
free (string);
goto file_error_and_exit;
}
2009-01-12 13:36:28 +00:00
if (nr == 0)
1998-04-17 19:52:44 +00:00
{
free (string);
return ((flags & FEVAL_BUILTIN) ? EXECUTION_SUCCESS : 1);
}
2001-04-06 19:14:31 +00:00
if ((flags & FEVAL_CHECKBINARY) &&
2009-01-12 13:36:28 +00:00
check_binary_file (string, (nr > 80) ? 80 : nr))
1996-12-23 17:02:34 +00:00
{
free (string);
2009-01-12 13:36:28 +00:00
(*errfunc) (_("%s: cannot execute binary file"), filename);
1996-12-23 17:02:34 +00:00
return ((flags & FEVAL_BUILTIN) ? EX_BINARY_FILE : -1);
}
if (flags & FEVAL_UNWINDPROT)
{
begin_unwind_frame ("_evalfile");
unwind_protect_int (return_catch_flag);
unwind_protect_jmp_buf (return_catch);
if (flags & FEVAL_NONINT)
unwind_protect_int (interactive);
unwind_protect_int (sourcelevel);
}
else
{
COPY_PROCENV (return_catch, old_return_catch);
if (flags & FEVAL_NONINT)
old_interactive = interactive;
}
if (flags & FEVAL_NONINT)
interactive = 0;
return_catch_flag++;
sourcelevel++;
2004-07-27 13:29:18 +00:00
#if defined (ARRAY_VARS)
array_push (bash_source_a, (char *)filename);
t = itos (executing_line_number ());
array_push (bash_lineno_a, t);
free (t);
array_push (funcname_a, "source"); /* not exactly right */
# if defined (DEBUGGER)
/* Have to figure out a better way to do this when `source' is supplied
arguments */
if ((flags & FEVAL_NOPUSHARGS) == 0)
{
array_push (bash_argv_a, (char *)filename);
tt[0] = '1'; tt[1] = '\0';
array_push (bash_argc_a, tt);
}
# endif
#endif
1997-06-05 14:59:13 +00:00
/* set the flags to be passed to parse_and_execute */
2004-07-27 13:29:18 +00:00
pflags = SEVAL_RESETLINE;
pflags |= (flags & FEVAL_HISTORY) ? 0 : SEVAL_NOHIST;
1997-06-05 14:59:13 +00:00
1996-12-23 17:02:34 +00:00
if (flags & FEVAL_BUILTIN)
result = EXECUTION_SUCCESS;
return_val = setjmp (return_catch);
/* If `return' was seen outside of a function, but in the script, then
force parse_and_execute () to clean up. */
if (return_val)
{
parse_and_execute_cleanup ();
result = return_catch_value;
}
else
1997-06-05 14:59:13 +00:00
result = parse_and_execute (string, filename, pflags);
1996-12-23 17:02:34 +00:00
if (flags & FEVAL_UNWINDPROT)
run_unwind_frame ("_evalfile");
else
{
if (flags & FEVAL_NONINT)
interactive = old_interactive;
return_catch_flag--;
sourcelevel--;
COPY_PROCENV (old_return_catch, return_catch);
}
2004-07-27 13:29:18 +00:00
#if defined (ARRAY_VARS)
2005-12-07 14:08:12 +00:00
/* These two variables cannot be unset, and cannot be affected by the
sourced file. */
2004-07-27 13:29:18 +00:00
array_pop (bash_source_a);
array_pop (bash_lineno_a);
2005-12-07 14:08:12 +00:00
/* FUNCNAME can be unset, and so can potentially be changed by the
sourced file. */
GET_ARRAY_FROM_VAR ("FUNCNAME", nfv, funcname_a);
if (nfv == funcname_v)
array_pop (funcname_a);
2004-07-27 13:29:18 +00:00
# if defined (DEBUGGER)
if ((flags & FEVAL_NOPUSHARGS) == 0)
{
array_pop (bash_argc_a);
array_pop (bash_argv_a);
}
# endif
#endif
1996-12-23 17:02:34 +00:00
return ((flags & FEVAL_BUILTIN) ? result : 1);
}
int
maybe_execute_file (fname, force_noninteractive)
2001-11-13 17:56:06 +00:00
const char *fname;
1996-12-23 17:02:34 +00:00
int force_noninteractive;
{
char *filename;
int result, flags;
2002-07-17 14:10:11 +00:00
filename = bash_tilde_expand (fname, 0);
1996-12-23 17:02:34 +00:00
flags = FEVAL_ENOENTOK;
if (force_noninteractive)
flags |= FEVAL_NONINT;
result = _evalfile (filename, flags);
free (filename);
return result;
}
1997-06-05 14:59:13 +00:00
#if defined (HISTORY)
int
fc_execute_file (filename)
2001-11-13 17:56:06 +00:00
const char *filename;
1997-06-05 14:59:13 +00:00
{
int flags;
/* We want these commands to show up in the history list if
remember_on_history is set. */
2001-11-13 17:56:06 +00:00
flags = FEVAL_ENOENTOK|FEVAL_HISTORY|FEVAL_REGFILE;
1997-06-05 14:59:13 +00:00
return (_evalfile (filename, flags));
}
#endif /* HISTORY */
1996-12-23 17:02:34 +00:00
int
2004-07-27 13:29:18 +00:00
source_file (filename, sflags)
2001-11-13 17:56:06 +00:00
const char *filename;
2004-07-27 13:29:18 +00:00
int sflags;
1996-12-23 17:02:34 +00:00
{
2004-07-27 13:29:18 +00:00
int flags, rval;
1996-12-23 17:02:34 +00:00
flags = FEVAL_BUILTIN|FEVAL_UNWINDPROT|FEVAL_NONINT;
2004-07-27 13:29:18 +00:00
if (sflags)
flags |= FEVAL_NOPUSHARGS;
1996-12-23 17:02:34 +00:00
/* POSIX shells exit if non-interactive and file error. */
if (posixly_correct && !interactive_shell)
flags |= FEVAL_LONGJMP;
2004-07-27 13:29:18 +00:00
rval = _evalfile (filename, flags);
run_return_trap ();
return rval;
1996-12-23 17:02:34 +00:00
}