]> git.ipfire.org Git - thirdparty/bash.git/blame - eval.c
Imported from ../bash-2.02.tar.gz.
[thirdparty/bash.git] / eval.c
CommitLineData
ccc6cda3
JA
1/* eval.c -- reading and evaluating commands.
2
3 Copyright (C) 1996 Free Software Foundation, Inc.
4
5 This file is part of GNU Bash.
6
7 Bash is distributed in the hope that it will be useful, but WITHOUT
8 ANY WARRANTY. No author or distributor accepts responsibility to
9 anyone for the consequences of using it or for whether it serves
10 any particular purpose or works at all, unless he says so in
11 writing. Refer to the GNU Emacs General Public License for full
12 details.
13
14 Everyone is granted permission to copy, modify and redistribute
15 Bash, but only under the conditions described in the GNU General
16 Public License. A copy of this license is supposed to have been
17 given to you along with GNU Emacs so you can know your rights and
18 responsibilities. It should be in a file named COPYING.
19
20 Among other things, the copyright notice and this notice must be
21 preserved on all copies. */
22
23#include "config.h"
24
25#if defined (HAVE_UNISTD_H)
cce855bc
JA
26# ifdef _MINIX
27# include <sys/types.h>
28# endif
ccc6cda3
JA
29# include <unistd.h>
30#endif
31
32#include "bashansi.h"
33#include <stdio.h>
34
35#include "shell.h"
36#include "flags.h"
37#include "trap.h"
38
39#include "builtins/common.h"
40
41#include "input.h"
42#include "execute_cmd.h"
43
44extern int yyparse ();
45
46extern int EOF_reached;
47extern int indirection_level, interactive, interactive_shell;
48extern int subshell_environment, running_under_emacs;
d166f048 49extern int last_command_exit_value, stdin_redir;
ccc6cda3
JA
50extern int need_here_doc;
51extern int current_command_number, current_command_line_count, line_number;
52extern char *ps1_prompt, **prompt_string_pointer;
53extern int expand_aliases;
54
55/* Read and execute commands until EOF is reached. This assumes that
56 the input source has already been initialized. */
57int
58reader_loop ()
59{
60 int our_indirection_level;
61 COMMAND *current_command = (COMMAND *)NULL;
62
63 our_indirection_level = ++indirection_level;
64
65 while (EOF_Reached == 0)
66 {
67 int code;
68
69 code = setjmp (top_level);
70
71#if defined (PROCESS_SUBSTITUTION)
72 unlink_fifo_list ();
73#endif /* PROCESS_SUBSTITUTION */
74
75 if (interactive_shell && signal_is_ignored (SIGINT) == 0)
76 set_signal_handler (SIGINT, sigint_sighandler);
77
78 if (code != NOT_JUMPED)
79 {
80 indirection_level = our_indirection_level;
81
82 switch (code)
83 {
84 /* Some kind of throw to top_level has occured. */
85 case FORCE_EOF:
86 case EXITPROG:
87 current_command = (COMMAND *)NULL;
88 EOF_Reached = EOF;
89 goto exec_done;
90
91 case DISCARD:
92 last_command_exit_value = 1;
93 if (subshell_environment)
94 {
95 current_command = (COMMAND *)NULL;
96 EOF_Reached = EOF;
97 goto exec_done;
98 }
99 /* Obstack free command elements, etc. */
100 if (current_command)
101 {
102 dispose_command (current_command);
103 current_command = (COMMAND *)NULL;
104 }
105 break;
106
107 default:
108 programming_error ("reader_loop: bad jump: code %d", code);
109 }
110 }
111
112 executing = 0;
113 dispose_used_env_vars ();
114
115#if (defined (ultrix) && defined (mips)) || defined (C_ALLOCA)
116 /* Attempt to reclaim memory allocated with alloca (). */
117 (void) alloca (0);
118#endif
119
120 if (read_command () == 0)
121 {
122 if (interactive_shell == 0 && read_but_dont_execute)
123 {
124 last_command_exit_value = EXECUTION_SUCCESS;
125 dispose_command (global_command);
126 global_command = (COMMAND *)NULL;
127 }
128 else if (current_command = global_command)
129 {
130 global_command = (COMMAND *)NULL;
131 current_command_number++;
132
133 executing = 1;
d166f048 134 stdin_redir = 0;
ccc6cda3
JA
135 execute_command (current_command);
136
137 exec_done:
138 if (current_command)
139 {
140 dispose_command (current_command);
141 current_command = (COMMAND *)NULL;
142 }
143
144 QUIT;
145 }
146 }
147 else
148 {
149 /* Parse error, maybe discard rest of stream if not interactive. */
150 if (interactive == 0)
151 EOF_Reached = EOF;
152 }
153 if (just_one_command)
154 EOF_Reached = EOF;
155 }
156 indirection_level--;
157 return (last_command_exit_value);
158}
159
160static sighandler
161alrm_catcher(i)
162 int i;
163{
164 printf ("%ctimed out waiting for input: auto-logout\n", '\07');
165 jump_to_top_level (EXITPROG);
166 SIGRETURN (0);
167}
168
169/* Send an escape sequence to emacs term mode to tell it the
170 current working directory. */
171static void
172send_pwd_to_eterm ()
173{
174 char *pwd;
175
176 pwd = get_string_value ("PWD");
177 if (pwd == 0)
178 pwd = get_working_directory ("eterm");
179 fprintf (stderr, "\032/%s\n", pwd);
180}
181
182/* Call the YACC-generated parser and return the status of the parse.
183 Input is read from the current input stream (bash_input). yyparse
184 leaves the parsed command in the global variable GLOBAL_COMMAND.
185 This is where PROMPT_COMMAND is executed. */
186int
187parse_command ()
188{
189 int r;
190 char *command_to_execute;
191
192 need_here_doc = 0;
193 run_pending_traps ();
194
195 /* Allow the execution of a random command just before the printing
196 of each primary prompt. If the shell variable PROMPT_COMMAND
197 is set then the value of it is the command to execute. */
198 if (interactive && bash_input.type != st_string)
199 {
200 command_to_execute = get_string_value ("PROMPT_COMMAND");
201 if (command_to_execute)
202 execute_prompt_command (command_to_execute);
203
204 if (running_under_emacs == 2)
205 send_pwd_to_eterm (); /* Yuck */
206 }
207
208 current_command_line_count = 0;
209 r = yyparse ();
210
211 if (need_here_doc)
212 gather_here_documents ();
213
214 return (r);
215}
216
217/* Read and parse a command, returning the status of the parse. The command
218 is left in the globval variable GLOBAL_COMMAND for use by reader_loop.
219 This is where the shell timeout code is executed. */
220int
221read_command ()
222{
223 SHELL_VAR *tmout_var;
224 int tmout_len, result;
225 SigHandler *old_alrm;
226
227 prompt_string_pointer = &ps1_prompt;
228 global_command = (COMMAND *)NULL;
229
230 /* Only do timeouts if interactive. */
231 tmout_var = (SHELL_VAR *)NULL;
232 tmout_len = 0;
233
234 if (interactive)
235 {
236 tmout_var = find_variable ("TMOUT");
237 old_alrm = (SigHandler *)NULL;
238
239 if (tmout_var && tmout_var->value)
240 {
241 tmout_len = atoi (tmout_var->value);
242 if (tmout_len > 0)
243 {
244 old_alrm = set_signal_handler (SIGALRM, alrm_catcher);
245 alarm (tmout_len);
246 }
247 }
248 }
249
250 QUIT;
251
252 current_command_line_count = 0;
253 result = parse_command ();
254
255 if (interactive && tmout_var && (tmout_len > 0))
256 {
257 alarm(0);
258 set_signal_handler (SIGALRM, old_alrm);
259 }
260
261 return (result);
262}
cce855bc
JA
263
264/* Take a string and run it through the shell parser, returning the
265 resultant word list. Used by compound array assignment. */
266WORD_LIST *
267parse_string_to_word_list (s, whom)
268 char *s, *whom;
269{
270 WORD_LIST *wl;
271 COMMAND *saved_global;
272
273 push_stream (1);
274
275 saved_global = global_command;
276 global_command = (COMMAND *)0;
277
278 with_input_from_string (s, whom);
279 if (parse_command () != 0 || global_command == 0 || global_command->type != cm_simple)
280 {
281 if (global_command)
282 dispose_command (global_command);
283 wl = (WORD_LIST *)NULL;
284 }
285 else
286 {
287 wl = global_command->value.Simple->words;
288 free (global_command->value.Simple);
289 free (global_command);
290 }
291
292 global_command = saved_global;
293
294 pop_stream ();
295
296 return (wl);
297}