]> git.ipfire.org Git - thirdparty/bash.git/blob - builtins/evalstring.c
Imported from ../bash-2.05b.tar.gz.
[thirdparty/bash.git] / builtins / evalstring.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 2, 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
18
19 #include <config.h>
20
21 #if defined (HAVE_UNISTD_H)
22 # ifdef _MINIX
23 # include <sys/types.h>
24 # endif
25 # include <unistd.h>
26 #endif
27
28 #include <stdio.h>
29 #include <signal.h>
30
31 #include <errno.h>
32
33 #include "filecntl.h"
34 #include "../bashansi.h"
35
36 #include "../shell.h"
37 #include "../jobs.h"
38 #include "../builtins.h"
39 #include "../flags.h"
40 #include "../input.h"
41 #include "../execute_cmd.h"
42 #include "../redir.h"
43 #include "../trap.h"
44
45 #if defined (HISTORY)
46 # include "../bashhist.h"
47 #endif
48
49 #include "common.h"
50
51 #if !defined (errno)
52 extern int errno;
53 #endif
54
55 #define IS_BUILTIN(s) (builtin_address_internal(s, 0) != (struct builtin *)NULL)
56
57 extern int indirection_level, startup_state, subshell_environment;
58 extern int line_number;
59 extern int last_command_exit_value;
60 extern int running_trap;
61 extern int posixly_correct;
62
63 int parse_and_execute_level = 0;
64
65 static int cat_file __P((REDIRECT *));
66
67 /* How to force parse_and_execute () to clean up after itself. */
68 void
69 parse_and_execute_cleanup ()
70 {
71 if (running_trap)
72 {
73 run_trap_cleanup (running_trap - 1);
74 unfreeze_jobs_list ();
75 }
76 run_unwind_frame ("parse_and_execute_top");
77 }
78
79 /* Parse and execute the commands in STRING. Returns whatever
80 execute_command () returns. This frees STRING. FLAGS is a
81 flags word; look in common.h for the possible values. Actions
82 are:
83 (flags & SEVAL_NONINT) -> interactive = 0;
84 (flags & SEVAL_INTERACT) -> interactive = 1;
85 (flags & SEVAL_NOHIST) -> call bash_history_disable ()
86 (flags & SEVAL_NOFREE) -> don't free STRING when finished
87 */
88
89 int
90 parse_and_execute (string, from_file, flags)
91 char *string;
92 const char *from_file;
93 int flags;
94 {
95 int code, x;
96 volatile int should_jump_to_top_level, last_result;
97 char *orig_string;
98 COMMAND *volatile command;
99
100 orig_string = string;
101 /* Unwind protect this invocation of parse_and_execute (). */
102 begin_unwind_frame ("parse_and_execute_top");
103 unwind_protect_int (parse_and_execute_level);
104 unwind_protect_jmp_buf (top_level);
105 unwind_protect_int (indirection_level);
106 unwind_protect_int (line_number);
107 if (flags & (SEVAL_NONINT|SEVAL_INTERACT))
108 unwind_protect_int (interactive);
109
110 #if defined (HISTORY)
111 unwind_protect_int (remember_on_history); /* can be used in scripts */
112 # if defined (BANG_HISTORY)
113 if (interactive_shell)
114 {
115 unwind_protect_int (history_expansion_inhibited);
116 }
117 # endif /* BANG_HISTORY */
118 #endif /* HISTORY */
119
120 if (interactive_shell)
121 {
122 x = get_current_prompt_level ();
123 add_unwind_protect (set_current_prompt_level, x);
124 }
125
126 add_unwind_protect (pop_stream, (char *)NULL);
127 if (orig_string && ((flags & SEVAL_NOFREE) == 0))
128 add_unwind_protect (xfree, orig_string);
129 end_unwind_frame ();
130
131 parse_and_execute_level++;
132 push_stream (1); /* reset the line number */
133 indirection_level++;
134 if (flags & (SEVAL_NONINT|SEVAL_INTERACT))
135 interactive = (flags & SEVAL_NONINT) ? 0 : 1;
136
137 #if defined (HISTORY)
138 if (flags & SEVAL_NOHIST)
139 bash_history_disable ();
140 #endif /* HISTORY */
141
142 code = should_jump_to_top_level = 0;
143 last_result = EXECUTION_SUCCESS;
144 command = (COMMAND *)NULL;
145
146 with_input_from_string (string, from_file);
147 while (*(bash_input.location.string))
148 {
149 if (interrupt_state)
150 {
151 last_result = EXECUTION_FAILURE;
152 break;
153 }
154
155 /* Provide a location for functions which `longjmp (top_level)' to
156 jump to. This prevents errors in substitution from restarting
157 the reader loop directly, for example. */
158 code = setjmp (top_level);
159
160 if (code)
161 {
162 should_jump_to_top_level = 0;
163 switch (code)
164 {
165 case FORCE_EOF:
166 case EXITPROG:
167 run_unwind_frame ("pe_dispose");
168 /* Remember to call longjmp (top_level) after the old
169 value for it is restored. */
170 should_jump_to_top_level = 1;
171 goto out;
172
173 case DISCARD:
174 run_unwind_frame ("pe_dispose");
175 last_result = last_command_exit_value = EXECUTION_FAILURE; /* XXX */
176 if (subshell_environment)
177 {
178 should_jump_to_top_level = 1;
179 goto out;
180 }
181 else
182 {
183 #if 0
184 dispose_command (command); /* pe_dispose does this */
185 #endif
186 continue;
187 }
188
189 default:
190 command_error ("parse_and_execute", CMDERR_BADJUMP, code, 0);
191 break;
192 }
193 }
194
195 if (parse_command () == 0)
196 {
197 if (interactive_shell == 0 && read_but_dont_execute)
198 {
199 last_result = EXECUTION_SUCCESS;
200 dispose_command (global_command);
201 global_command = (COMMAND *)NULL;
202 }
203 else if (command = global_command)
204 {
205 struct fd_bitmap *bitmap;
206
207 bitmap = new_fd_bitmap (FD_BITMAP_SIZE);
208 begin_unwind_frame ("pe_dispose");
209 add_unwind_protect (dispose_fd_bitmap, bitmap);
210 add_unwind_protect (dispose_command, command); /* XXX */
211
212 global_command = (COMMAND *)NULL;
213
214 #if defined (ONESHOT)
215 /*
216 * IF
217 * we were invoked as `bash -c' (startup_state == 2) AND
218 * parse_and_execute has not been called recursively AND
219 * we have parsed the full command (string == '\0') AND
220 * we have a simple command without redirections AND
221 * the command is not being timed
222 * THEN
223 * tell the execution code that we don't need to fork
224 */
225 if (startup_state == 2 && parse_and_execute_level == 1 &&
226 *bash_input.location.string == '\0' &&
227 command->type == cm_simple &&
228 !command->redirects && !command->value.Simple->redirects &&
229 ((command->flags & CMD_TIME_PIPELINE) == 0))
230 {
231 command->flags |= CMD_NO_FORK;
232 command->value.Simple->flags |= CMD_NO_FORK;
233 }
234 #endif /* ONESHOT */
235
236 /* See if this is a candidate for $( <file ). */
237 if (startup_state == 2 &&
238 (subshell_environment & SUBSHELL_COMSUB) &&
239 *bash_input.location.string == '\0' &&
240 command->type == cm_simple && !command->redirects &&
241 (command->flags & CMD_TIME_PIPELINE) == 0 &&
242 command->value.Simple->words == 0 &&
243 command->value.Simple->redirects &&
244 command->value.Simple->redirects->next == 0 &&
245 command->value.Simple->redirects->instruction == r_input_direction)
246 {
247 int r;
248 r = cat_file (command->value.Simple->redirects);
249 last_result = (r < 0) ? EXECUTION_FAILURE : EXECUTION_SUCCESS;
250 }
251 else
252 last_result = execute_command_internal
253 (command, 0, NO_PIPE, NO_PIPE, bitmap);
254
255 dispose_command (command);
256 dispose_fd_bitmap (bitmap);
257 discard_unwind_frame ("pe_dispose");
258 }
259 }
260 else
261 {
262 last_result = EXECUTION_FAILURE;
263
264 /* Since we are shell compatible, syntax errors in a script
265 abort the execution of the script. Right? */
266 break;
267 }
268 }
269
270 out:
271
272 run_unwind_frame ("parse_and_execute_top");
273
274 if (interrupt_state && parse_and_execute_level == 0)
275 {
276 /* An interrupt during non-interactive execution in an
277 interactive shell (e.g. via $PROMPT_COMMAND) should
278 not cause the shell to exit. */
279 interactive = interactive_shell;
280 throw_to_top_level ();
281 }
282
283 if (should_jump_to_top_level)
284 jump_to_top_level (code);
285
286 return (last_result);
287 }
288
289 /* Handle a $( < file ) command substitution. This expands the filename,
290 returning errors as appropriate, then just cats the file to the standard
291 output. */
292 static int
293 cat_file (r)
294 REDIRECT *r;
295 {
296 char lbuf[128], *fn;
297 int fd, rval;
298 ssize_t nr;
299
300 if (r->instruction != r_input_direction)
301 return -1;
302
303 /* Get the filename. */
304 if (posixly_correct && !interactive_shell)
305 disallow_filename_globbing++;
306 fn = redirection_expand (r->redirectee.filename);
307 if (posixly_correct && !interactive_shell)
308 disallow_filename_globbing--;
309
310 if (fn == 0)
311 {
312 redirection_error (r, AMBIGUOUS_REDIRECT);
313 return -1;
314 }
315
316 fd = open(fn, O_RDONLY);
317 if (fd < 0)
318 {
319 file_error (fn);
320 free (fn);
321 return -1;
322 }
323
324 rval = zcatfd (fd, 1, fn);
325
326 free (fn);
327 close (fd);
328
329 return (rval);
330 }