Imported from ../bash-2.05.tar.gz.
[platform/upstream/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
44 #if defined (HISTORY)
45 #  include "../bashhist.h"
46 #endif
47
48 #include "common.h"
49
50 #if !defined (errno)
51 extern int errno;
52 #endif
53
54 #define IS_BUILTIN(s)   (builtin_address_internal(s, 0) != (struct builtin *)NULL)
55
56 extern void run_trap_cleanup ();
57 extern int zwrite ();
58
59 extern int interactive, interactive_shell;
60 extern int indirection_level, startup_state, subshell_environment;
61 extern int line_number;
62 extern int last_command_exit_value;
63 extern int running_trap;
64 extern int posixly_correct;
65 extern COMMAND *global_command;
66
67 int parse_and_execute_level = 0;
68
69 static int cat_file ();
70
71 /* How to force parse_and_execute () to clean up after itself. */
72 void
73 parse_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
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
92 int
93 parse_and_execute (string, from_file, flags)
94      char *string;
95      char *from_file;
96      int flags;
97 {
98   int code, x;
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);
110   if (flags & (SEVAL_NONINT|SEVAL_INTERACT))
111     unwind_protect_int (interactive);
112
113 #if defined (HISTORY)
114   unwind_protect_int (remember_on_history);     /* can be used in scripts */
115 #  if defined (BANG_HISTORY)
116   if (interactive_shell)
117     {
118       unwind_protect_int (history_expansion_inhibited);
119     }
120 #  endif /* BANG_HISTORY */
121 #endif /* HISTORY */
122
123   if (interactive_shell)
124     {
125       x = get_current_prompt_level ();
126       add_unwind_protect (set_current_prompt_level, x);
127     }
128   
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++;
137   if (flags & (SEVAL_NONINT|SEVAL_INTERACT))
138     interactive = (flags & SEVAL_NONINT) ? 0 : 1;
139
140 #if defined (HISTORY)
141   if (flags & SEVAL_NOHIST)
142     bash_history_disable ();
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_result = last_command_exit_value = EXECUTION_FAILURE; /* XXX */
179               if (subshell_environment)
180                 {
181                   should_jump_to_top_level = 1;
182                   goto out;
183                 }
184               else
185                 {
186 #if 0
187                   dispose_command (command);    /* pe_dispose does this */
188 #endif
189                   continue;
190                 }
191
192             default:
193               command_error ("parse_and_execute", CMDERR_BADJUMP, code, 0);
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);
213               add_unwind_protect (dispose_command, command);    /* XXX */
214
215               global_command = (COMMAND *)NULL;
216
217 #if defined (ONESHOT)
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 &&
232                   ((command->flags & CMD_TIME_PIPELINE) == 0))
233                 {
234                   command->flags |= CMD_NO_FORK;
235                   command->value.Simple->flags |= CMD_NO_FORK;
236                 }
237 #endif /* ONESHOT */
238
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
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 }
291
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. */
295 static int
296 cat_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     {
329       nr = zread (fd, lbuf, sizeof(lbuf));
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 }