]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/evalstring.c
Imported from ../bash-2.02.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
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)
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
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
d166f048
JA
54extern void run_trap_cleanup ();
55
ccc6cda3
JA
56extern int interactive, interactive_shell;
57extern int indirection_level, startup_state, subshell_environment;
58extern int line_number;
59extern int last_command_exit_value;
60extern int running_trap;
cce855bc 61extern int posixly_correct;
ccc6cda3
JA
62extern COMMAND *global_command;
63
64int parse_and_execute_level = 0;
65
cce855bc
JA
66static int cat_file ();
67
ccc6cda3
JA
68/* How to force parse_and_execute () to clean up after itself. */
69void
70parse_and_execute_cleanup ()
71{
72 if (running_trap)
73 {
74 run_trap_cleanup (running_trap - 1);
75 unfreeze_jobs_list ();
76 }
77 run_unwind_frame ("parse_and_execute_top");
78}
79
80/* Parse and execute the commands in STRING. Returns whatever
d166f048
JA
81 execute_command () returns. This frees STRING. FLAGS is a
82 flags word; look in common.h for the possible values. Actions
83 are:
84 (flags & SEVAL_NONINT) -> interactive = 0;
85 (flags & SEVAL_INTERACT) -> interactive = 1;
86 (flags & SEVAL_NOHIST) -> call bash_history_disable ()
87*/
88
ccc6cda3 89int
d166f048 90parse_and_execute (string, from_file, flags)
ccc6cda3
JA
91 char *string;
92 char *from_file;
d166f048 93 int flags;
ccc6cda3
JA
94{
95 int code;
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);
d166f048 107 if (flags & (SEVAL_NONINT|SEVAL_INTERACT))
ccc6cda3
JA
108 unwind_protect_int (interactive);
109
110#if defined (HISTORY)
d166f048
JA
111 unwind_protect_int (remember_on_history); /* can be used in scripts */
112# if defined (BANG_HISTORY)
ccc6cda3
JA
113 if (interactive_shell)
114 {
ccc6cda3 115 unwind_protect_int (history_expansion_inhibited);
ccc6cda3 116 }
d166f048 117# endif /* BANG_HISTORY */
ccc6cda3
JA
118#endif /* HISTORY */
119
120 add_unwind_protect (pop_stream, (char *)NULL);
121 if (orig_string)
122 add_unwind_protect (xfree, orig_string);
123 end_unwind_frame ();
124
125 parse_and_execute_level++;
126 push_stream (1); /* reset the line number */
127 indirection_level++;
d166f048
JA
128 if (flags & (SEVAL_NONINT|SEVAL_INTERACT))
129 interactive = (flags & SEVAL_NONINT) ? 0 : 1;
ccc6cda3
JA
130
131#if defined (HISTORY)
d166f048
JA
132 if (flags & SEVAL_NOHIST)
133 bash_history_disable ();
ccc6cda3
JA
134#endif /* HISTORY */
135
136 code = should_jump_to_top_level = 0;
137 last_result = EXECUTION_SUCCESS;
138 command = (COMMAND *)NULL;
139
140 with_input_from_string (string, from_file);
141 while (*(bash_input.location.string))
142 {
143 if (interrupt_state)
144 {
145 last_result = EXECUTION_FAILURE;
146 break;
147 }
148
149 /* Provide a location for functions which `longjmp (top_level)' to
150 jump to. This prevents errors in substitution from restarting
151 the reader loop directly, for example. */
152 code = setjmp (top_level);
153
154 if (code)
155 {
156 should_jump_to_top_level = 0;
157 switch (code)
158 {
159 case FORCE_EOF:
160 case EXITPROG:
161 run_unwind_frame ("pe_dispose");
162 /* Remember to call longjmp (top_level) after the old
163 value for it is restored. */
164 should_jump_to_top_level = 1;
165 goto out;
166
167 case DISCARD:
168 run_unwind_frame ("pe_dispose");
169 last_command_exit_value = 1; /* XXX */
170 if (subshell_environment)
171 {
172 should_jump_to_top_level = 1;
173 goto out;
174 }
175 else
176 {
e8ce775d
JA
177#if 0
178 dispose_command (command); /* pe_dispose does this */
179#endif
ccc6cda3
JA
180 continue;
181 }
182
183 default:
184 programming_error ("parse_and_execute: bad jump: code %d", code);
185 break;
186 }
187 }
188
189 if (parse_command () == 0)
190 {
191 if (interactive_shell == 0 && read_but_dont_execute)
192 {
193 last_result = EXECUTION_SUCCESS;
194 dispose_command (global_command);
195 global_command = (COMMAND *)NULL;
196 }
197 else if (command = global_command)
198 {
199 struct fd_bitmap *bitmap;
200
201 bitmap = new_fd_bitmap (FD_BITMAP_SIZE);
202 begin_unwind_frame ("pe_dispose");
203 add_unwind_protect (dispose_fd_bitmap, bitmap);
d166f048 204 add_unwind_protect (dispose_command, command); /* XXX */
ccc6cda3
JA
205
206 global_command = (COMMAND *)NULL;
207
208#if defined (ONESHOT)
209 if (startup_state == 2 && *bash_input.location.string == '\0' &&
210 command->type == cm_simple && !command->redirects &&
e8ce775d
JA
211 !command->value.Simple->redirects &&
212 ((command->flags & CMD_TIME_PIPELINE) == 0))
ccc6cda3
JA
213 {
214 command->flags |= CMD_NO_FORK;
215 command->value.Simple->flags |= CMD_NO_FORK;
216 }
217#endif /* ONESHOT */
218
cce855bc
JA
219 /* See if this is a candidate for $( <file ). */
220 if (startup_state == 2 &&
221 subshell_environment == SUBSHELL_COMSUB &&
222 *bash_input.location.string == '\0' &&
223 command->type == cm_simple && !command->redirects &&
224 (command->flags & CMD_TIME_PIPELINE) == 0 &&
225 command->value.Simple->words == 0 &&
226 command->value.Simple->redirects &&
227 command->value.Simple->redirects->next == 0 &&
228 command->value.Simple->redirects->instruction == r_input_direction)
229 {
230 int r;
231 r = cat_file (command->value.Simple->redirects);
232 last_result = (r < 0) ? EXECUTION_FAILURE : EXECUTION_SUCCESS;
233 }
234 else
235 last_result = execute_command_internal
ccc6cda3
JA
236 (command, 0, NO_PIPE, NO_PIPE, bitmap);
237
238 dispose_command (command);
239 dispose_fd_bitmap (bitmap);
240 discard_unwind_frame ("pe_dispose");
241 }
242 }
243 else
244 {
245 last_result = EXECUTION_FAILURE;
246
247 /* Since we are shell compatible, syntax errors in a script
248 abort the execution of the script. Right? */
249 break;
250 }
251 }
252
253 out:
254
255 run_unwind_frame ("parse_and_execute_top");
256
257 if (interrupt_state && parse_and_execute_level == 0)
258 {
259 /* An interrupt during non-interactive execution in an
260 interactive shell (e.g. via $PROMPT_COMMAND) should
261 not cause the shell to exit. */
262 interactive = interactive_shell;
263 throw_to_top_level ();
264 }
265
266 if (should_jump_to_top_level)
267 jump_to_top_level (code);
268
269 return (last_result);
270}
cce855bc
JA
271
272/* Write NB bytes from BUF to file descriptor FD, retrying the write if
273 it is interrupted. We retry three times if we get a zero-length
274 write. Any other signal causes this function to return prematurely. */
275static int
276zwrite (fd, buf, nb)
277 int fd;
278 unsigned char *buf;
279 int nb;
280{
281 int n, i, nt;
282
283 for (n = nb, nt = 0;;)
284 {
285 i = write (fd, buf, n);
286 if (i > 0)
287 {
288 n -= i;
289 if (n <= 0)
290 return nb;
291 }
292 else if (i == 0)
293 {
294 if (++nt > 3)
295 return (nb - n);
296 }
297 else if (errno != EINTR)
298 return -1;
299 }
300}
301
302/* Handle a $( < file ) command substitution. This expands the filename,
303 returning errors as appropriate, then just cats the file to the standard
304 output. */
305static int
306cat_file (r)
307 REDIRECT *r;
308{
309 char lbuf[128], *fn;
310 int nr, fd, rval;
311
312 if (r->instruction != r_input_direction)
313 return -1;
314
315 /* Get the filename. */
316 if (posixly_correct && !interactive_shell)
317 disallow_filename_globbing++;
318 fn = redirection_expand (r->redirectee.filename);
319 if (posixly_correct && !interactive_shell)
320 disallow_filename_globbing--;
321
322 if (fn == 0)
323 {
324 redirection_error (r, AMBIGUOUS_REDIRECT);
325 return -1;
326 }
327
328 fd = open(fn, O_RDONLY);
329 if (fd < 0)
330 {
331 file_error (fn);
332 free (fn);
333 return -1;
334 }
335
336 rval = 0;
337 while (1)
338 {
339 /* Retry the reads on EINTR. Any other error causes a break from the
340 loop. */
341 while ((nr = read (fd, lbuf, sizeof(lbuf))) < 0 && errno == EINTR)
342 ;
343 if (nr == 0)
344 break;
345 else if (nr < 0)
346 {
347 rval = -1;
348 break;
349 }
350 if (zwrite (1, lbuf, nr) < 0)
351 {
352 rval = -1;
353 break;
354 }
355 }
356
357 free (fn);
358 close (fd);
359
360 return (0);
361}