]> git.ipfire.org Git - thirdparty/bash.git/blob - builtins/evalfile.c
bb3217d3bf128c2b5e9e2cea646d8faa76a76f50
[thirdparty/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 "../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
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 #define FEVAL_HISTORY 0x020
59
60 extern int interactive, interactive_shell, posixly_correct;
61 extern int indirection_level, startup_state, subshell_environment;
62 extern int return_catch_flag, return_catch_value;
63 extern int last_command_exit_value;
64
65 /* How many `levels' of sourced files we have. */
66 int sourcelevel = 0;
67
68 static int
69 _evalfile (filename, flags)
70 char *filename;
71 int flags;
72 {
73 volatile int old_interactive;
74 procenv_t old_return_catch;
75 int return_val, fd, result, pflags;
76 char *string;
77 struct stat finfo;
78 size_t file_size;
79 VFunction *errfunc;
80
81 fd = open (filename, O_RDONLY);
82
83 if (fd < 0 || (fstat (fd, &finfo) == -1))
84 {
85 file_error_and_exit:
86 if (((flags & FEVAL_ENOENTOK) == 0) || errno != ENOENT)
87 file_error (filename);
88
89 if (flags & FEVAL_LONGJMP)
90 {
91 last_command_exit_value = 1;
92 jump_to_top_level (EXITPROG);
93 }
94
95 return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE
96 : ((errno == ENOENT) ? 0 : -1));
97 }
98
99 errfunc = (VFunction *)((flags & FEVAL_BUILTIN) ? builtin_error : internal_error);
100
101 if (S_ISDIR (finfo.st_mode))
102 {
103 (*errfunc) ("%s: is a directory", filename);
104 return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
105 }
106 else if (S_ISREG (finfo.st_mode) == 0)
107 {
108 (*errfunc) ("%s: not a regular file", filename);
109 return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
110 }
111
112 file_size = (size_t)finfo.st_size;
113 /* Check for overflow with large files. */
114 if (file_size != finfo.st_size || file_size + 1 < file_size)
115 {
116 (*errfunc) ("%s: file is too large", filename);
117 return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
118 }
119 string = xmalloc (1 + file_size);
120 result = read (fd, string, file_size);
121 string[result] = '\0';
122
123 return_val = errno;
124 close (fd);
125 errno = return_val;
126
127 if (result < 0) /* XXX was != file_size, not < 0 */
128 {
129 free (string);
130 goto file_error_and_exit;
131 }
132
133 if (result == 0)
134 {
135 free (string);
136 return ((flags & FEVAL_BUILTIN) ? EXECUTION_SUCCESS : 1);
137 }
138
139 if (check_binary_file ((unsigned char *)string, (result > 80) ? 80 : result))
140 {
141 free (string);
142 (*errfunc) ("%s: cannot execute binary file", filename);
143 return ((flags & FEVAL_BUILTIN) ? EX_BINARY_FILE : -1);
144 }
145
146 if (flags & FEVAL_UNWINDPROT)
147 {
148 begin_unwind_frame ("_evalfile");
149
150 unwind_protect_int (return_catch_flag);
151 unwind_protect_jmp_buf (return_catch);
152 if (flags & FEVAL_NONINT)
153 unwind_protect_int (interactive);
154 unwind_protect_int (sourcelevel);
155 }
156 else
157 {
158 COPY_PROCENV (return_catch, old_return_catch);
159 if (flags & FEVAL_NONINT)
160 old_interactive = interactive;
161 }
162
163 if (flags & FEVAL_NONINT)
164 interactive = 0;
165
166 return_catch_flag++;
167 sourcelevel++;
168
169 /* set the flags to be passed to parse_and_execute */
170 pflags = (flags & FEVAL_HISTORY) ? 0 : SEVAL_NOHIST;
171
172 if (flags & FEVAL_BUILTIN)
173 result = EXECUTION_SUCCESS;
174
175 return_val = setjmp (return_catch);
176
177 /* If `return' was seen outside of a function, but in the script, then
178 force parse_and_execute () to clean up. */
179 if (return_val)
180 {
181 parse_and_execute_cleanup ();
182 result = return_catch_value;
183 }
184 else
185 result = parse_and_execute (string, filename, pflags);
186
187 if (flags & FEVAL_UNWINDPROT)
188 run_unwind_frame ("_evalfile");
189 else
190 {
191 if (flags & FEVAL_NONINT)
192 interactive = old_interactive;
193 return_catch_flag--;
194 sourcelevel--;
195 COPY_PROCENV (old_return_catch, return_catch);
196 }
197
198 return ((flags & FEVAL_BUILTIN) ? result : 1);
199 }
200
201 int
202 maybe_execute_file (fname, force_noninteractive)
203 char *fname;
204 int force_noninteractive;
205 {
206 char *filename;
207 int result, flags;
208
209 filename = bash_tilde_expand (fname);
210 flags = FEVAL_ENOENTOK;
211 if (force_noninteractive)
212 flags |= FEVAL_NONINT;
213 result = _evalfile (filename, flags);
214 free (filename);
215 return result;
216 }
217
218 #if defined (HISTORY)
219 int
220 fc_execute_file (filename)
221 char *filename;
222 {
223 int flags;
224
225 /* We want these commands to show up in the history list if
226 remember_on_history is set. */
227 flags = FEVAL_ENOENTOK|FEVAL_HISTORY;
228 return (_evalfile (filename, flags));
229 }
230 #endif /* HISTORY */
231
232 int
233 source_file (filename)
234 char *filename;
235 {
236 int flags;
237
238 flags = FEVAL_BUILTIN|FEVAL_UNWINDPROT|FEVAL_NONINT;
239 /* POSIX shells exit if non-interactive and file error. */
240 if (posixly_correct && !interactive_shell)
241 flags |= FEVAL_LONGJMP;
242 return (_evalfile (filename, flags));
243 }