14fbc4dcb3e3dcb406ac1a9ed0a6934cd7daf8c0
[platform/upstream/bash.git] / builtins / evalfile.c
1 /* Copyright (C) 1996 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
18
19 #include <config.h>
20
21 #if defined (HAVE_UNISTD_H)
22 #  include <unistd.h>
23 #endif
24
25 #include <sys/types.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
35 #include "../shell.h"
36 #include "../jobs.h"
37 #include "../builtins.h"
38 #include "../flags.h"
39 #include "../input.h"
40 #include "../execute_cmd.h"
41
42 #if defined (HISTORY)
43 #  include "../bashhist.h"
44 #endif
45
46 #include "common.h"
47
48 #if !defined (errno)
49 extern int errno;
50 #endif
51
52 /* Flags for _evalfile() */
53 #define FEVAL_ENOENTOK          0x001
54 #define FEVAL_BUILTIN           0x002
55 #define FEVAL_UNWINDPROT        0x004
56 #define FEVAL_NONINT            0x008
57 #define FEVAL_LONGJMP           0x010
58
59 extern int interactive, interactive_shell, posixly_correct;
60 extern int indirection_level, startup_state, subshell_environment;
61 extern int return_catch_flag, return_catch_value;
62 extern int last_command_exit_value;
63
64 /* How many `levels' of sourced files we have. */
65 int sourcelevel = 0;
66
67 static int
68 _evalfile (filename, flags)
69      char *filename;
70      int flags;
71 {
72   volatile int old_interactive;
73   procenv_t old_return_catch;
74   int return_val, fd, result;
75   char *string;
76   struct stat finfo;
77   VFunction *errfunc;
78
79   fd = open (filename, O_RDONLY);
80
81   if (fd < 0 || (fstat (fd, &finfo) == -1))
82     {
83 file_error_and_exit:
84       if (((flags & FEVAL_ENOENTOK) == 0) || errno != ENOENT)
85         file_error (filename);
86
87       if (flags & FEVAL_LONGJMP)
88         {
89           last_command_exit_value = 1;
90           jump_to_top_level (EXITPROG);
91         }
92
93       return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE
94                                       : ((errno == ENOENT) ? 0 : -1));
95     }
96
97   errfunc = (VFunction *)((flags & FEVAL_BUILTIN) ? builtin_error : internal_error);
98
99   if (S_ISDIR (finfo.st_mode))
100     {
101       (*errfunc) ("%s: is a directory", filename);
102       return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
103     }
104   else if (S_ISREG (finfo.st_mode) == 0)
105     {
106       (*errfunc) ("%s: not a regular file", filename);
107       return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
108     }
109
110   string = xmalloc (1 + (int)finfo.st_size);
111   result = read (fd, string, finfo.st_size);
112   string[result] = '\0';
113
114   return_val = errno;
115   close (fd);
116   errno = return_val;
117
118   if (result != (int)finfo.st_size)
119     {
120       free (string);
121       goto file_error_and_exit;
122     }
123
124   if (check_binary_file ((unsigned char *)string, (result > 80) ? 80 : result))
125     {
126       free (string);
127       (*errfunc) ("%s: cannot execute binary file", filename);
128       return ((flags & FEVAL_BUILTIN) ? EX_BINARY_FILE : -1);
129     }
130
131   if (flags & FEVAL_UNWINDPROT)
132     {
133       begin_unwind_frame ("_evalfile");
134
135       unwind_protect_int (return_catch_flag);
136       unwind_protect_jmp_buf (return_catch);
137       if (flags & FEVAL_NONINT)
138         unwind_protect_int (interactive);
139       unwind_protect_int (sourcelevel);
140     }
141   else
142     {
143       COPY_PROCENV (return_catch, old_return_catch);
144       if (flags & FEVAL_NONINT)
145         old_interactive = interactive;
146     }
147
148   if (flags & FEVAL_NONINT)
149     interactive = 0;
150
151   return_catch_flag++;
152   sourcelevel++;
153
154   if (flags & FEVAL_BUILTIN)
155     result = EXECUTION_SUCCESS;
156
157   return_val = setjmp (return_catch);
158
159   /* If `return' was seen outside of a function, but in the script, then
160      force parse_and_execute () to clean up. */
161   if (return_val)
162     {
163       parse_and_execute_cleanup ();
164       result = return_catch_value;
165     }
166   else
167     result = parse_and_execute (string, filename, -1);
168
169   if (flags & FEVAL_UNWINDPROT)
170     run_unwind_frame ("_evalfile");
171   else
172     {
173       if (flags & FEVAL_NONINT)
174         interactive = old_interactive;
175       return_catch_flag--;
176       sourcelevel--;
177       COPY_PROCENV (old_return_catch, return_catch);
178     }
179
180   return ((flags & FEVAL_BUILTIN) ? result : 1);
181 }
182
183 int
184 maybe_execute_file (fname, force_noninteractive)
185      char *fname;
186      int force_noninteractive;
187 {
188   char *filename;
189   int result, flags;
190
191   filename = bash_tilde_expand (fname);
192   flags = FEVAL_ENOENTOK;
193   if (force_noninteractive)
194     flags |= FEVAL_NONINT;
195   result = _evalfile (filename, flags);
196   free (filename);
197   return result;
198 }
199
200 int
201 source_file (filename)
202      char *filename;
203 {
204   int flags;
205
206   flags = FEVAL_BUILTIN|FEVAL_UNWINDPROT|FEVAL_NONINT;
207   /* POSIX shells exit if non-interactive and file error. */
208   if (posixly_correct && !interactive_shell)
209     flags |= FEVAL_LONGJMP;
210   return (_evalfile (filename, flags));
211 }