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