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