diff --git a/complete.c b/complete.c index f7e9a1f6d..f5e3fe333 100644 --- a/complete.c +++ b/complete.c @@ -334,7 +334,7 @@ void complete_destroy() complete_free_entry( prev ); } first_entry = 0; - + if( suffix_hash ) { hash_foreach( suffix_hash, &clear_hash_entry ); @@ -342,9 +342,9 @@ void complete_destroy() free( suffix_hash ); suffix_hash=0; } - + path = env_get( L"fish_complete_path" ); - + if( path ) parse_util_load_reset( path ); @@ -1338,17 +1338,16 @@ static void complete_from_args( const wchar_t *str, const wchar_t *desc, array_list_t *comp_out ) { - int was_interactive = is_interactive; array_list_t possible_comp; int i; al_init( &possible_comp ); - is_interactive=0; + proc_push_interactive(0); eval_args( args, &possible_comp ); - is_interactive=was_interactive; - + proc_pop_interactive(); + /* We need to unescape these strings before matching them */ for( i=0; i< al_get_count( &possible_comp ); i++ ) { diff --git a/event.c b/event.c index e81eb3ce5..d7004ba2f 100644 --- a/event.c +++ b/event.c @@ -385,8 +385,6 @@ static void event_fire_internal( event_t *event ) int i, j; string_buffer_t *b=0; array_list_t *fire=0; - - int was_interactive = is_interactive; /* First we free all events that have been removed @@ -462,19 +460,14 @@ static void event_fire_internal( event_t *event ) Event handlers are not part of the main flow of code, so they are marked as non-interactive and as a subshell */ - is_interactive=0; + proc_push_interactive(0); parser_push_block( EVENT ); current_block->param1.event = event; eval( (wchar_t *)b->buff, 0, TOP ); parser_pop_block(); - + proc_pop_interactive(); } - /* - Restore interactivity flags - */ - is_interactive = was_interactive; - if( b ) { sb_destroy( b ); diff --git a/parser.c b/parser.c index 4cd9b3930..205dc2ef3 100644 --- a/parser.c +++ b/parser.c @@ -917,9 +917,9 @@ int eval_args( const wchar_t *line, array_list_t *args ) tokenizer *previous_tokenizer=current_tokenizer; int previous_pos=current_tokenizer_pos; int do_loop=1; - int was_interactive = is_interactive; - is_interactive = 0; + proc_push_interactive(0); + current_tokenizer_pos = 0; tok_init( &tok, line, 0 ); @@ -978,7 +978,7 @@ int eval_args( const wchar_t *line, array_list_t *args ) current_tokenizer=previous_tokenizer; current_tokenizer_pos = previous_pos; - is_interactive = was_interactive; + proc_pop_interactive(); return 1; } diff --git a/proc.c b/proc.c index f804e8bf8..6fe85395a 100644 --- a/proc.c +++ b/proc.c @@ -54,6 +54,8 @@ Some of the code in this file is based on code from the Glibc manual. #include "event.h" #include "translate.h" #include "halloc.h" +#include "halloc_util.h" +#include "output.h" /** Size of message buffer @@ -76,7 +78,7 @@ static int last_status=0; static sig_atomic_t got_signal=0; job_t *first_job=0; -int is_interactive=0; +int is_interactive=-1; int is_interactive_session=0; int is_subshell=0; int is_block=0; @@ -101,9 +103,12 @@ static string_buffer_t event_pid; */ static string_buffer_t event_status; +static array_list_t *interactive_stack; void proc_init() { + interactive_stack = al_halloc( global_context ); + proc_push_interactive( 0 ); al_init( &event.arguments ); sb_init( &event_pid ); sb_init( &event_status ); @@ -1077,3 +1082,19 @@ void proc_sanity_check() } } +void proc_push_interactive( int value ) +{ + int old = is_interactive; + al_push( interactive_stack, (void *)(long)is_interactive ); + is_interactive = value; + if( old != value ) + signal_set_handlers(); +} + +void proc_pop_interactive() +{ + int old = is_interactive; + is_interactive= (int)(long)al_pop(interactive_stack); + if( is_interactive != old ) + signal_set_handlers(); +} diff --git a/proc.h b/proc.h index 4e46b2ae6..405d4d45e 100644 --- a/proc.h +++ b/proc.h @@ -337,4 +337,16 @@ void proc_init(); */ void proc_destroy(); +/** + Set new value for is_interactive flag, saving previous value. If + needed, update signal handlers. +*/ +void proc_push_interactive( int value ); + +/** + Set is_interactive flag to the previous value. If needed, update + signal handlers. +*/ +void proc_pop_interactive(); + #endif diff --git a/reader.c b/reader.c index 3023f2c3b..47f23d042 100644 --- a/reader.c +++ b/reader.c @@ -606,7 +606,6 @@ void reader_write_title() wchar_t *title; array_list_t l; wchar_t *term = env_get( L"TERM" ); - int was_interactive = is_interactive; /* This is a pretty lame heuristic for detecting terminals that do @@ -628,7 +627,7 @@ void reader_write_title() al_init( &l ); - is_interactive = 0; + proc_push_interactive(0); if( exec_subshell( title, &l ) != -1 ) { int i; @@ -639,8 +638,8 @@ void reader_write_title() } writestr( L"\7" ); } - is_interactive = was_interactive; - + proc_pop_interactive(); + al_foreach( &l, (void (*)(const void *))&free ); al_destroy( &l ); set_color( FISH_COLOR_RESET, FISH_COLOR_RESET ); @@ -790,8 +789,8 @@ static void write_prompt() if( data->prompt ) { - int was_interactive = is_interactive; - is_interactive = 0; + proc_push_interactive( 0 ); + if( exec_subshell( data->prompt, &prompt_list ) == -1 ) { /* If executing the prompt fails, make sure we at least don't print any junk */ @@ -799,7 +798,7 @@ static void write_prompt() al_destroy( &prompt_list ); al_init( &prompt_list ); } - is_interactive = was_interactive; + proc_pop_interactive(); } data->prompt_width=calc_prompt_width( &prompt_list ); @@ -1472,7 +1471,7 @@ static void run_pager( wchar_t *prefix, int is_quoted, array_list_t *comp ) the prefix. - If the list contains multiple elements without a common prefix, call run_pager to display a list of completions - + \param comp the list of completion strings */ @@ -1480,7 +1479,7 @@ static void run_pager( wchar_t *prefix, int is_quoted, array_list_t *comp ) static int handle_completions( array_list_t *comp ) { int i; - + if( al_get_count( comp ) == 0 ) { if( flash_screen != 0 ) @@ -2967,11 +2966,9 @@ int reader_read( int fd ) we need to preserve is_interactive, so we save the original state. We also update the signal handlers. */ - int shell_was_interactive = is_interactive; - - is_interactive = ((fd == 0) && isatty(STDIN_FILENO)); - signal_set_handlers(); + proc_push_interactive( ((fd == 0) && isatty(STDIN_FILENO))); + res= is_interactive?read_i():read_ni( fd ); /* @@ -2982,7 +2979,6 @@ int reader_read( int fd ) data->end_loop = 0; end_loop = 0; - is_interactive = shell_was_interactive; - signal_set_handlers(); + proc_pop_interactive(); return res; } diff --git a/signal.c b/signal.c index dbd3b701a..108af53e0 100644 --- a/signal.c +++ b/signal.c @@ -387,7 +387,6 @@ static void handle_winch( int sig, siginfo_t *info, void *context ) static void handle_int( int sig, siginfo_t *info, void *context ) { reader_handle_int( sig ); - default_handler( sig, info, context); } @@ -422,6 +421,10 @@ void signal_reset_handlers() void signal_set_handlers() { struct sigaction act; + + if( is_interactive == -1 ) + return; + sigemptyset( & act.sa_mask ); act.sa_flags=SA_SIGINFO; act.sa_sigaction = &default_handler; @@ -442,7 +445,7 @@ void signal_set_handlers() recover. */ sigaction( SIGPIPE, &act, 0); - + if( is_interactive ) { /*