i-bash/eval.c

298 lines
7 KiB
C
Raw Normal View History

1996-12-23 17:02:34 +00:00
/* eval.c -- reading and evaluating commands.
Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of GNU Bash.
Bash is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY. No author or distributor accepts responsibility to
anyone for the consequences of using it or for whether it serves
any particular purpose or works at all, unless he says so in
writing. Refer to the GNU Emacs General Public License for full
details.
Everyone is granted permission to copy, modify and redistribute
Bash, but only under the conditions described in the GNU General
Public License. A copy of this license is supposed to have been
given to you along with GNU Emacs so you can know your rights and
responsibilities. It should be in a file named COPYING.
Among other things, the copyright notice and this notice must be
preserved on all copies. */
#include "config.h"
#if defined (HAVE_UNISTD_H)
1998-04-17 19:52:44 +00:00
# ifdef _MINIX
# include <sys/types.h>
# endif
1996-12-23 17:02:34 +00:00
# include <unistd.h>
#endif
#include "bashansi.h"
#include <stdio.h>
#include "shell.h"
#include "flags.h"
#include "trap.h"
#include "builtins/common.h"
#include "input.h"
#include "execute_cmd.h"
extern int yyparse ();
extern int EOF_reached;
extern int indirection_level, interactive, interactive_shell;
extern int subshell_environment, running_under_emacs;
1997-06-05 14:59:13 +00:00
extern int last_command_exit_value, stdin_redir;
1996-12-23 17:02:34 +00:00
extern int need_here_doc;
extern int current_command_number, current_command_line_count, line_number;
extern char *ps1_prompt, **prompt_string_pointer;
extern int expand_aliases;
/* Read and execute commands until EOF is reached. This assumes that
the input source has already been initialized. */
int
reader_loop ()
{
int our_indirection_level;
COMMAND *current_command = (COMMAND *)NULL;
our_indirection_level = ++indirection_level;
while (EOF_Reached == 0)
{
int code;
code = setjmp (top_level);
#if defined (PROCESS_SUBSTITUTION)
unlink_fifo_list ();
#endif /* PROCESS_SUBSTITUTION */
if (interactive_shell && signal_is_ignored (SIGINT) == 0)
set_signal_handler (SIGINT, sigint_sighandler);
if (code != NOT_JUMPED)
{
indirection_level = our_indirection_level;
switch (code)
{
/* Some kind of throw to top_level has occured. */
case FORCE_EOF:
case EXITPROG:
current_command = (COMMAND *)NULL;
EOF_Reached = EOF;
goto exec_done;
case DISCARD:
last_command_exit_value = 1;
if (subshell_environment)
{
current_command = (COMMAND *)NULL;
EOF_Reached = EOF;
goto exec_done;
}
/* Obstack free command elements, etc. */
if (current_command)
{
dispose_command (current_command);
current_command = (COMMAND *)NULL;
}
break;
default:
programming_error ("reader_loop: bad jump: code %d", code);
}
}
executing = 0;
dispose_used_env_vars ();
#if (defined (ultrix) && defined (mips)) || defined (C_ALLOCA)
/* Attempt to reclaim memory allocated with alloca (). */
(void) alloca (0);
#endif
if (read_command () == 0)
{
if (interactive_shell == 0 && read_but_dont_execute)
{
last_command_exit_value = EXECUTION_SUCCESS;
dispose_command (global_command);
global_command = (COMMAND *)NULL;
}
else if (current_command = global_command)
{
global_command = (COMMAND *)NULL;
current_command_number++;
executing = 1;
1997-06-05 14:59:13 +00:00
stdin_redir = 0;
1996-12-23 17:02:34 +00:00
execute_command (current_command);
exec_done:
if (current_command)
{
dispose_command (current_command);
current_command = (COMMAND *)NULL;
}
QUIT;
}
}
else
{
/* Parse error, maybe discard rest of stream if not interactive. */
if (interactive == 0)
EOF_Reached = EOF;
}
if (just_one_command)
EOF_Reached = EOF;
}
indirection_level--;
return (last_command_exit_value);
}
static sighandler
alrm_catcher(i)
int i;
{
printf ("%ctimed out waiting for input: auto-logout\n", '\07');
jump_to_top_level (EXITPROG);
SIGRETURN (0);
}
/* Send an escape sequence to emacs term mode to tell it the
current working directory. */
static void
send_pwd_to_eterm ()
{
char *pwd;
pwd = get_string_value ("PWD");
if (pwd == 0)
pwd = get_working_directory ("eterm");
fprintf (stderr, "\032/%s\n", pwd);
}
/* Call the YACC-generated parser and return the status of the parse.
Input is read from the current input stream (bash_input). yyparse
leaves the parsed command in the global variable GLOBAL_COMMAND.
This is where PROMPT_COMMAND is executed. */
int
parse_command ()
{
int r;
char *command_to_execute;
need_here_doc = 0;
run_pending_traps ();
/* Allow the execution of a random command just before the printing
of each primary prompt. If the shell variable PROMPT_COMMAND
is set then the value of it is the command to execute. */
if (interactive && bash_input.type != st_string)
{
command_to_execute = get_string_value ("PROMPT_COMMAND");
if (command_to_execute)
execute_prompt_command (command_to_execute);
if (running_under_emacs == 2)
send_pwd_to_eterm (); /* Yuck */
}
current_command_line_count = 0;
r = yyparse ();
if (need_here_doc)
gather_here_documents ();
return (r);
}
/* Read and parse a command, returning the status of the parse. The command
is left in the globval variable GLOBAL_COMMAND for use by reader_loop.
This is where the shell timeout code is executed. */
int
read_command ()
{
SHELL_VAR *tmout_var;
int tmout_len, result;
SigHandler *old_alrm;
prompt_string_pointer = &ps1_prompt;
global_command = (COMMAND *)NULL;
/* Only do timeouts if interactive. */
tmout_var = (SHELL_VAR *)NULL;
tmout_len = 0;
if (interactive)
{
tmout_var = find_variable ("TMOUT");
old_alrm = (SigHandler *)NULL;
if (tmout_var && tmout_var->value)
{
tmout_len = atoi (tmout_var->value);
if (tmout_len > 0)
{
old_alrm = set_signal_handler (SIGALRM, alrm_catcher);
alarm (tmout_len);
}
}
}
QUIT;
current_command_line_count = 0;
result = parse_command ();
if (interactive && tmout_var && (tmout_len > 0))
{
alarm(0);
set_signal_handler (SIGALRM, old_alrm);
}
return (result);
}
1998-04-17 19:52:44 +00:00
/* Take a string and run it through the shell parser, returning the
resultant word list. Used by compound array assignment. */
WORD_LIST *
parse_string_to_word_list (s, whom)
char *s, *whom;
{
WORD_LIST *wl;
COMMAND *saved_global;
push_stream (1);
saved_global = global_command;
global_command = (COMMAND *)0;
with_input_from_string (s, whom);
if (parse_command () != 0 || global_command == 0 || global_command->type != cm_simple)
{
if (global_command)
dispose_command (global_command);
wl = (WORD_LIST *)NULL;
}
else
{
wl = global_command->value.Simple->words;
free (global_command->value.Simple);
free (global_command);
}
global_command = saved_global;
pop_stream ();
return (wl);
}