Imported from ../bash-2.05b.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 #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 }