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