]>
Commit | Line | Data |
---|---|---|
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) | |
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 | |
d166f048 | 58 | #define FEVAL_HISTORY 0x020 |
ccc6cda3 JA |
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; | |
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 | { | |
84 | file_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 | ||
187 | int | |
188 | maybe_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) |
205 | int | |
206 | fc_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 |
218 | int |
219 | source_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 | } |