]> git.ipfire.org Git - thirdparty/bash.git/blame - eval.c
Imported from ../bash-2.01.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)
26# include <unistd.h>
27#endif
28
29#include "bashansi.h"
30#include <stdio.h>
31
32#include "shell.h"
33#include "flags.h"
34#include "trap.h"
35
36#include "builtins/common.h"
37
38#include "input.h"
39#include "execute_cmd.h"
40
41extern int yyparse ();
42
43extern int EOF_reached;
44extern int indirection_level, interactive, interactive_shell;
45extern int subshell_environment, running_under_emacs;
d166f048 46extern int last_command_exit_value, stdin_redir;
ccc6cda3
JA
47extern int need_here_doc;
48extern int current_command_number, current_command_line_count, line_number;
49extern char *ps1_prompt, **prompt_string_pointer;
50extern int expand_aliases;
51
52/* Read and execute commands until EOF is reached. This assumes that
53 the input source has already been initialized. */
54int
55reader_loop ()
56{
57 int our_indirection_level;
58 COMMAND *current_command = (COMMAND *)NULL;
59
60 our_indirection_level = ++indirection_level;
61
62 while (EOF_Reached == 0)
63 {
64 int code;
65
66 code = setjmp (top_level);
67
68#if defined (PROCESS_SUBSTITUTION)
69 unlink_fifo_list ();
70#endif /* PROCESS_SUBSTITUTION */
71
72 if (interactive_shell && signal_is_ignored (SIGINT) == 0)
73 set_signal_handler (SIGINT, sigint_sighandler);
74
75 if (code != NOT_JUMPED)
76 {
77 indirection_level = our_indirection_level;
78
79 switch (code)
80 {
81 /* Some kind of throw to top_level has occured. */
82 case FORCE_EOF:
83 case EXITPROG:
84 current_command = (COMMAND *)NULL;
85 EOF_Reached = EOF;
86 goto exec_done;
87
88 case DISCARD:
89 last_command_exit_value = 1;
90 if (subshell_environment)
91 {
92 current_command = (COMMAND *)NULL;
93 EOF_Reached = EOF;
94 goto exec_done;
95 }
96 /* Obstack free command elements, etc. */
97 if (current_command)
98 {
99 dispose_command (current_command);
100 current_command = (COMMAND *)NULL;
101 }
102 break;
103
104 default:
105 programming_error ("reader_loop: bad jump: code %d", code);
106 }
107 }
108
109 executing = 0;
110 dispose_used_env_vars ();
111
112#if (defined (ultrix) && defined (mips)) || defined (C_ALLOCA)
113 /* Attempt to reclaim memory allocated with alloca (). */
114 (void) alloca (0);
115#endif
116
117 if (read_command () == 0)
118 {
119 if (interactive_shell == 0 && read_but_dont_execute)
120 {
121 last_command_exit_value = EXECUTION_SUCCESS;
122 dispose_command (global_command);
123 global_command = (COMMAND *)NULL;
124 }
125 else if (current_command = global_command)
126 {
127 global_command = (COMMAND *)NULL;
128 current_command_number++;
129
130 executing = 1;
d166f048 131 stdin_redir = 0;
ccc6cda3
JA
132 execute_command (current_command);
133
134 exec_done:
135 if (current_command)
136 {
137 dispose_command (current_command);
138 current_command = (COMMAND *)NULL;
139 }
140
141 QUIT;
142 }
143 }
144 else
145 {
146 /* Parse error, maybe discard rest of stream if not interactive. */
147 if (interactive == 0)
148 EOF_Reached = EOF;
149 }
150 if (just_one_command)
151 EOF_Reached = EOF;
152 }
153 indirection_level--;
154 return (last_command_exit_value);
155}
156
157static sighandler
158alrm_catcher(i)
159 int i;
160{
161 printf ("%ctimed out waiting for input: auto-logout\n", '\07');
162 jump_to_top_level (EXITPROG);
163 SIGRETURN (0);
164}
165
166/* Send an escape sequence to emacs term mode to tell it the
167 current working directory. */
168static void
169send_pwd_to_eterm ()
170{
171 char *pwd;
172
173 pwd = get_string_value ("PWD");
174 if (pwd == 0)
175 pwd = get_working_directory ("eterm");
176 fprintf (stderr, "\032/%s\n", pwd);
177}
178
179/* Call the YACC-generated parser and return the status of the parse.
180 Input is read from the current input stream (bash_input). yyparse
181 leaves the parsed command in the global variable GLOBAL_COMMAND.
182 This is where PROMPT_COMMAND is executed. */
183int
184parse_command ()
185{
186 int r;
187 char *command_to_execute;
188
189 need_here_doc = 0;
190 run_pending_traps ();
191
192 /* Allow the execution of a random command just before the printing
193 of each primary prompt. If the shell variable PROMPT_COMMAND
194 is set then the value of it is the command to execute. */
195 if (interactive && bash_input.type != st_string)
196 {
197 command_to_execute = get_string_value ("PROMPT_COMMAND");
198 if (command_to_execute)
199 execute_prompt_command (command_to_execute);
200
201 if (running_under_emacs == 2)
202 send_pwd_to_eterm (); /* Yuck */
203 }
204
205 current_command_line_count = 0;
206 r = yyparse ();
207
208 if (need_here_doc)
209 gather_here_documents ();
210
211 return (r);
212}
213
214/* Read and parse a command, returning the status of the parse. The command
215 is left in the globval variable GLOBAL_COMMAND for use by reader_loop.
216 This is where the shell timeout code is executed. */
217int
218read_command ()
219{
220 SHELL_VAR *tmout_var;
221 int tmout_len, result;
222 SigHandler *old_alrm;
223
224 prompt_string_pointer = &ps1_prompt;
225 global_command = (COMMAND *)NULL;
226
227 /* Only do timeouts if interactive. */
228 tmout_var = (SHELL_VAR *)NULL;
229 tmout_len = 0;
230
231 if (interactive)
232 {
233 tmout_var = find_variable ("TMOUT");
234 old_alrm = (SigHandler *)NULL;
235
236 if (tmout_var && tmout_var->value)
237 {
238 tmout_len = atoi (tmout_var->value);
239 if (tmout_len > 0)
240 {
241 old_alrm = set_signal_handler (SIGALRM, alrm_catcher);
242 alarm (tmout_len);
243 }
244 }
245 }
246
247 QUIT;
248
249 current_command_line_count = 0;
250 result = parse_command ();
251
252 if (interactive && tmout_var && (tmout_len > 0))
253 {
254 alarm(0);
255 set_signal_handler (SIGALRM, old_alrm);
256 }
257
258 return (result);
259}