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