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, the Bourne Again SHell. 6 7 Bash is free software; you can redistribute it and/or modify it 8 under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2, or (at your option) 10 any later version. 11 12 Bash is distributed in the hope that it will be useful, but WITHOUT 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 15 License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with Bash; see the file COPYING. If not, write to the Free 19 Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 20 21#include "config.h" 22 23#if defined (HAVE_UNISTD_H) 24# ifdef _MINIX 25# include <sys/types.h> 26# endif 27# include <unistd.h> 28#endif 29 30#include "bashansi.h" 31#include <stdio.h> 32 33#include "bashintl.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 44#if defined (HISTORY) 45# include "bashhist.h" 46#endif 47 48extern int EOF_reached; 49extern int indirection_level; 50extern int posixly_correct; 51extern int subshell_environment, running_under_emacs; 52extern int last_command_exit_value, stdin_redir; 53extern int need_here_doc; 54extern int current_command_number, current_command_line_count, line_number; 55extern int expand_aliases; 56 57static void send_pwd_to_eterm __P((void)); 58static sighandler alrm_catcher __P((int)); 59 60/* Read and execute commands until EOF is reached. This assumes that 61 the input source has already been initialized. */ 62int 63reader_loop () 64{ 65 int our_indirection_level; 66 COMMAND * volatile current_command; 67 68 current_command = (COMMAND *)NULL; 69 USE_VAR(current_command); 70 71 our_indirection_level = ++indirection_level; 72 73 while (EOF_Reached == 0) 74 { 75 int code; 76 77 code = setjmp (top_level); 78 79#if defined (PROCESS_SUBSTITUTION) 80 unlink_fifo_list (); 81#endif /* PROCESS_SUBSTITUTION */ 82 83 if (interactive_shell && signal_is_ignored (SIGINT) == 0) 84 set_signal_handler (SIGINT, sigint_sighandler); 85 86 if (code != NOT_JUMPED) 87 { 88 indirection_level = our_indirection_level; 89 90 switch (code) 91 { 92 /* Some kind of throw to top_level has occured. */ 93 case FORCE_EOF: 94 case ERREXIT: 95 case EXITPROG: 96 current_command = (COMMAND *)NULL; 97 if (exit_immediately_on_error) 98 variable_context = 0; /* not in a function */ 99 EOF_Reached = EOF; 100 goto exec_done; 101 102 case DISCARD: 103 last_command_exit_value = 1; 104 if (subshell_environment) 105 { 106 current_command = (COMMAND *)NULL; 107 EOF_Reached = EOF; 108 goto exec_done; 109 } 110 /* Obstack free command elements, etc. */ 111 if (current_command) 112 { 113 dispose_command (current_command); 114 current_command = (COMMAND *)NULL; 115 } 116 break; 117 118 default: 119 command_error ("reader_loop", CMDERR_BADJUMP, code, 0); 120 } 121 } 122 123 executing = 0; 124 if (temporary_env) 125 dispose_used_env_vars (); 126 127#if (defined (ultrix) && defined (mips)) || defined (C_ALLOCA) 128 /* Attempt to reclaim memory allocated with alloca (). */ 129 (void) alloca (0); 130#endif 131 132 if (read_command () == 0) 133 { 134 if (interactive_shell == 0 && read_but_dont_execute) 135 { 136 last_command_exit_value = EXECUTION_SUCCESS; 137 dispose_command (global_command); 138 global_command = (COMMAND *)NULL; 139 } 140 else if (current_command = global_command) 141 { 142 global_command = (COMMAND *)NULL; 143 current_command_number++; 144 145 executing = 1; 146 stdin_redir = 0; 147 execute_command (current_command); 148 149 exec_done: 150 QUIT; 151 152 if (current_command) 153 { 154 dispose_command (current_command); 155 current_command = (COMMAND *)NULL; 156 } 157 } 158 } 159 else 160 { 161 /* Parse error, maybe discard rest of stream if not interactive. */ 162 if (interactive == 0) 163 EOF_Reached = EOF; 164 } 165 if (just_one_command) 166 EOF_Reached = EOF; 167 } 168 indirection_level--; 169 return (last_command_exit_value); 170} 171 172static sighandler 173alrm_catcher(i) 174 int i; 175{ 176 printf (_("\007timed out waiting for input: auto-logout\n")); 177 bash_logout (); /* run ~/.bash_logout if this is a login shell */ 178 jump_to_top_level (EXITPROG); 179 SIGRETURN (0); 180} 181 182/* Send an escape sequence to emacs term mode to tell it the 183 current working directory. */ 184static void 185send_pwd_to_eterm () 186{ 187 char *pwd; 188 189 pwd = get_string_value ("PWD"); 190 if (pwd == 0) 191 pwd = get_working_directory ("eterm"); 192 fprintf (stderr, "\032/%s\n", pwd); 193} 194 195/* Call the YACC-generated parser and return the status of the parse. 196 Input is read from the current input stream (bash_input). yyparse 197 leaves the parsed command in the global variable GLOBAL_COMMAND. 198 This is where PROMPT_COMMAND is executed. */ 199int 200parse_command () 201{ 202 int r; 203 char *command_to_execute; 204 205 need_here_doc = 0; 206 run_pending_traps (); 207 208 /* Allow the execution of a random command just before the printing 209 of each primary prompt. If the shell variable PROMPT_COMMAND 210 is set then the value of it is the command to execute. */ 211 if (interactive && bash_input.type != st_string) 212 { 213 command_to_execute = get_string_value ("PROMPT_COMMAND"); 214 if (command_to_execute) 215 execute_variable_command (command_to_execute, "PROMPT_COMMAND"); 216 217 if (running_under_emacs == 2) 218 send_pwd_to_eterm (); /* Yuck */ 219 } 220 221 current_command_line_count = 0; 222 r = yyparse (); 223 224 if (need_here_doc) 225 gather_here_documents (); 226 227 return (r); 228} 229 230/* Read and parse a command, returning the status of the parse. The command 231 is left in the globval variable GLOBAL_COMMAND for use by reader_loop. 232 This is where the shell timeout code is executed. */ 233int 234read_command () 235{ 236 SHELL_VAR *tmout_var; 237 int tmout_len, result; 238 SigHandler *old_alrm; 239 240 set_current_prompt_level (1); 241 global_command = (COMMAND *)NULL; 242 243 /* Only do timeouts if interactive. */ 244 tmout_var = (SHELL_VAR *)NULL; 245 tmout_len = 0; 246 old_alrm = (SigHandler *)NULL; 247 248 if (interactive) 249 { 250 tmout_var = find_variable ("TMOUT"); 251 252 if (tmout_var && var_isset (tmout_var)) 253 { 254 tmout_len = atoi (value_cell (tmout_var)); 255 if (tmout_len > 0) 256 { 257 old_alrm = set_signal_handler (SIGALRM, alrm_catcher); 258 alarm (tmout_len); 259 } 260 } 261 } 262 263 QUIT; 264 265 current_command_line_count = 0; 266 result = parse_command (); 267 268 if (interactive && tmout_var && (tmout_len > 0)) 269 { 270 alarm(0); 271 set_signal_handler (SIGALRM, old_alrm); 272 } 273 274 return (result); 275} 276