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