aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--builtin.c2
-rw-r--r--common.c57
-rw-r--r--common.h43
-rw-r--r--env.c38
-rw-r--r--env.h8
-rw-r--r--event.c19
-rw-r--r--exec.c112
-rw-r--r--fish_tests.c2
-rw-r--r--main.c2
-rw-r--r--parser.c26
-rw-r--r--proc.c140
-rw-r--r--proc.h15
-rw-r--r--reader.c59
-rw-r--r--reader.h17
-rw-r--r--signal.c48
-rw-r--r--signal.h15
-rw-r--r--wutil.c48
17 files changed, 357 insertions, 294 deletions
diff --git a/builtin.c b/builtin.c
index be14bdb1..2908e19b 100644
--- a/builtin.c
+++ b/builtin.c
@@ -946,7 +946,7 @@ static int builtin_function( wchar_t **argv )
{
wchar_t *nxt = names_arr[i];
int l = wcslen( nxt + 2 );
- if( chars+l > reader_get_width() )
+ if( chars+l > common_get_width() )
{
chars = 0;
sb_append(sb_err, L"\n" );
diff --git a/common.c b/common.c
index 14ea3356..a819845f 100644
--- a/common.c
+++ b/common.c
@@ -87,6 +87,11 @@ wchar_t *program_name;
int debug_level=1;
+/**
+ This struct should be continually updated by signals as the term resizes, and as such always contain the correct current size.
+*/
+static struct winsize termsize;
+
static int block_count=0;
@@ -799,7 +804,7 @@ void debug( int level, wchar_t *msg, ... )
wchar_t *start, *pos;
int line_width = 0;
int tok_width = 0;
- int screen_width = 80;
+ int screen_width = common_get_width();
if( level > debug_level )
return;
@@ -817,35 +822,51 @@ void debug( int level, wchar_t *msg, ... )
int overflow = 0;
tok_width=0;
-
+
+ /*
+ Tokenize on whitespace, and also calculate the width of the token
+ */
while( *pos && ( !wcschr( L" \n\r\t", *pos ) ) )
{
- if((tok_width + wcwidth(*pos)) >= (screen_width-1))
+
+ /*
+ Check is token is wider than one line.
+ If so we mark it as an overflow and break the token.
+ */
+ if((tok_width + wcwidth(*pos)) > (screen_width-1))
{
overflow = 1;
- break;
-
+ break;
}
tok_width += wcwidth( *pos );
pos++;
}
+ /*
+ If token is zero character long, we don't do anything
+ */
if( pos == start )
{
start = pos = pos+1;
}
else if( overflow )
{
+ /*
+ In case of overflow, we print a newline, except if we alreade are at position 0
+ */
wchar_t *token = wcsndup( start, pos-start );
if( line_width != 0 )
- putwc( L'\n', stderr );
+ putwc( L'\n', stderr );
fwprintf( stderr, L"%ls-\n", token );
free( token );
line_width=0;
}
else
{
+ /*
+ Print the token
+ */
wchar_t *token = wcsndup( start, pos-start );
if( (line_width + (line_width!=0?1:0) + tok_width) > screen_width )
{
@@ -856,7 +877,9 @@ void debug( int level, wchar_t *msg, ... )
free( token );
line_width += (line_width!=0?1:0) + tok_width;
}
-
+ /*
+ Break on end of string
+ */
if( !*pos )
break;
@@ -1383,3 +1406,23 @@ int acquire_lock_file( const char *lockfile, const int timeout, int force )
free( linkfile );
return ret;
}
+
+void common_handle_winch( int signal )
+{
+ if (ioctl(1,TIOCGWINSZ,&termsize)!=0)
+ {
+ return;
+ }
+}
+
+int common_get_width()
+{
+ return termsize.ws_col;
+}
+
+
+int common_get_height()
+{
+ return termsize.ws_row;
+}
+
diff --git a/common.h b/common.h
index d23d3a07..c554f52e 100644
--- a/common.h
+++ b/common.h
@@ -231,15 +231,23 @@ void die_mem();
void common_destroy();
/**
- Issue a debug message
+ Issue a debug message with printf-style string formating and
+ automatic line breaking. The string will begin with the string \c
+ program_name, followed by a colon and a whitespace.
- \param level the priority of the message. Lower number means higher priority. Messages with too high priority number will be discarded.
- \param the message.
+ \param level the priority of the message. Lower number means higher priority. Messages with a priority_number higher than \c debug_level will be ignored..
+ \param the message format string.
+
+ Example:
+
+ <code>debug( 1, L"Pi = %.3f", M_PI );</code>
+
+ will print the string 'fish: Pi = 3.141', given that debug_level is 1 or higher, and that program_name is 'fish'.
*/
void debug( int level, wchar_t *msg, ... );
/**
- Replace special characters with escape sequences. Newline is
+ Replace special characters with backslash escape sequences. Newline is
replaced with \n, etc.
\param in The string to be escaped
@@ -255,6 +263,31 @@ wchar_t *unescape( const wchar_t * in, int escape_special );
void block();
void unblock();
+int acquire_lock_file( const char *lockfile, const int timeout, int force );
+
+/**
+ Returns the width of the terminal window, so that not all
+ functions that use these values continually have to keep track of
+ it.
+
+ Only works if common_handle_winch is registered to handle winch signals.
+*/
+int common_get_width();
+/**
+ Returns the height of the terminal window, so that not all
+ functions that use these values continually have to keep track of
+ it.
+
+ Only works if common_handle_winch is registered to handle winch signals.
+*/
+int common_get_height();
+
+/*
+ Handle a window change event by looking up the new window size and
+ saving it in an internal variable used by common_get_wisth and
+ common_get_height().
+*/
+void common_handle_winch( int signal );
+
#endif
-int acquire_lock_file( const char *lockfile, const int timeout, int force );
diff --git a/env.c b/env.c
index 0971840f..8fda3a7d 100644
--- a/env.c
+++ b/env.c
@@ -251,7 +251,7 @@ void env_init()
hash_put( &env_read_only, L"LINES", L"" );
hash_put( &env_read_only, L"COLUMNS", L"" );
hash_put( &env_read_only, L"PWD", L"" );
-
+
/*
HOME should be writeable by root, since this is often a
convenient way to install software.
@@ -620,6 +620,24 @@ wchar_t *env_get( const wchar_t *key )
}
return (wchar_t *)dyn_var.buff;
}
+ else if( wcscmp( key, L"COLUMNS" )==0 )
+ {
+ sb_clear( &dyn_var );
+ sb_printf( &dyn_var, L"%d", common_get_width() );
+ return (wchar_t *)dyn_var.buff;
+ }
+ else if( wcscmp( key, L"LINES" )==0 )
+ {
+ sb_clear( &dyn_var );
+ sb_printf( &dyn_var, L"%d", common_get_height() );
+ return (wchar_t *)dyn_var.buff;
+ }
+ else if( wcscmp( key, L"status" )==0 )
+ {
+ sb_clear( &dyn_var );
+ sb_printf( &dyn_var, L"%d", proc_get_last_status() );
+ return (wchar_t *)dyn_var.buff;
+ }
while( env != 0 )
{
@@ -658,10 +676,10 @@ int env_exist( const wchar_t *key )
env_node_t *env = top;
wchar_t *item;
- if( wcscmp( key, L"history" ) == 0 )
- {
- return 1;
- }
+ if( hash_get( &env_read_only, key ) )
+ {
+ return 1;
+ }
while( env != 0 )
{
@@ -809,7 +827,17 @@ void env_get_names( array_list_t *l, int flags )
add_key_to_hash,
&names );
if( get_names_show_unexported )
+ {
al_push( l, L"history" );
+ al_push( l, L"status" );
+ }
+
+ if( get_names_show_exported )
+ {
+ al_push( l, L"COLUMNS" );
+ al_push( l, L"LINES" );
+ }
+
}
if( show_universal )
diff --git a/env.h b/env.h
index b982fa36..bd43e3ca 100644
--- a/env.h
+++ b/env.h
@@ -69,9 +69,11 @@ void env_set( const wchar_t *key,
/**
- Return the value of the variable with the specified name.
- Returns 0 if the key does not exist.
- The returned string should not be modified or freed.
+ Return the value of the variable with the specified name. Returns 0
+ if the key does not exist. The returned string should not be
+ modified or freed. The returned string is only guaranteed to be
+ valid until the next call to env_get(), env_set(), env_push() or
+ env_pop() takes place.
*/
wchar_t *env_get( const wchar_t *key );
diff --git a/event.c b/event.c
index 3c2ff486..669f6beb 100644
--- a/event.c
+++ b/event.c
@@ -374,10 +374,16 @@ static void event_fire_signal_events()
array_list_t a;
al_init( &a );
+ /*
+ Switch signal lists
+ */
sig_list[1-active_list].count=0;
sig_list[1-active_list].overflow=0;
active_list=1-active_list;
-
+
+ /*
+ Set up
+ */
e.type=EVENT_SIGNAL;
e.function_name=0;
@@ -385,16 +391,19 @@ static void event_fire_signal_events()
if( lst->overflow )
{
- debug( 0, L"Signal overflow. Signals have been ignored" );
+ debug( 0, L"Signal list overflow. Signals have been ignored" );
}
-
+
+ /*
+ Send all signals in our private list
+ */
for( i=0; i<lst->count; i++ )
{
e.param1.signal = lst->signal[i];
al_set( &a, 0, sig2wcs( e.param1.signal ) );
event_fire_internal( &e, &a );
- }
-
+ }
+
al_destroy( &a );
}
diff --git a/exec.c b/exec.c
index 08ec35a4..ec5b35d9 100644
--- a/exec.c
+++ b/exec.c
@@ -259,17 +259,7 @@ static void handle_child_io( io_data_t *io )
We don't mind if this fails, it is just a speculative close
to make sure no unexpected untracked fd causes us to fail
*/
- while( close(io->fd) == -1 )
- {
- if( errno != EINTR )
- break;
-
-/* debug( 1,
- FD_ERROR,
- io->fd );
- wperror( L"close" );
- exit(1);*/
- }
+ close(io->fd);
switch( io->io_mode )
{
@@ -400,13 +390,12 @@ static void setup_child_process( job_t *j )
/* Set the handling for job control signals back to the default. */
signal_reset_handlers();
-
- sigset_t chldset;
- sigemptyset( &chldset );
- sigaddset( &chldset, SIGCHLD );
- sigprocmask(SIG_UNBLOCK, &chldset, 0);
-
+
handle_child_io( j->io );
+
+ /* Remove all signal blocks */
+ signal_unblock();
+
}
@@ -539,8 +528,13 @@ static int internal_exec_helper( const wchar_t *def,
io_data_t *io_internal = io_transmogrify( io );
int is_block_old=is_block;
is_block=1;
+
+ signal_unblock();
eval( def, io_internal, block_type );
+
+ signal_block();
+
/*
io_data_t *buff = io_get( io, 1 );
if( buff && buff->io_mode == IO_BUFFER )
@@ -583,56 +577,37 @@ static int handle_new_child( job_t *j, process_t *p )
j->pgid );
wperror( L"setpgid" );
}
-
}
if( j->fg )
{
- while( 1)
+ if( tcsetpgrp (0, j->pgid) )
{
- if( tcsetpgrp (0, j->pgid) )
- {
- if( errno != EINTR )
- {
- debug( 1, L"Could not send job %d ('%ls')to foreground",
- j->job_id,
- j->command );
- wperror( L"tcsetpgrp" );
- return -1;
- }
- }
- else
- break;
+ debug( 1, L"Could not send job %d ('%ls')to foreground",
+ j->job_id,
+ j->command );
+ wperror( L"tcsetpgrp" );
+ return -1;
}
}
if( j->fg && new_pgid)
{
- while( 1 )
+ if( tcsetpgrp (0, j->pgid) )
{
- if( tcsetpgrp (0, j->pgid) )
- {
- if( errno != EINTR )
- {
- debug( 1, L"Could not send job %d ('%ls')to foreground",
- j->job_id,
- j->command );
- wperror( L"tcsetpgrp" );
- return -1;
- }
- }
- else
- break;
+ debug( 1, L"Could not send job %d ('%ls')to foreground",
+ j->job_id,
+ j->command );
+ wperror( L"tcsetpgrp" );
+ return -1;
}
- }
-
+ }
}
else
{
j->pgid = getpid();
}
return 0;
-
}
@@ -659,6 +634,11 @@ void exec( job_t *j )
/*
Do a regular launch - but without forking first...
*/
+ signal_block();
+
+ /*
+ setup_child_process make sure signals are propelry set up
+ */
setup_child_process( j );
launch_process( j->first_process );
/*
@@ -689,6 +669,8 @@ void exec( job_t *j )
j->io = io_add( j->io, &pipe_write );
+ signal_block();
+
for (p = j->first_process; p; p = p->next)
{
mypipe[1]=-1;
@@ -890,8 +872,13 @@ void exec( job_t *j )
builtin_err_redirect = has_fd( j->io, 2 );
fg = j->fg;
j->fg = 0;
+
+ signal_unblock();
+
p->status = builtin_run( p->argv );
-
+
+ signal_block();
+
/*
Restore the fg flag, which is temporarily set to
false during builtin execution so as not to confuse
@@ -939,8 +926,7 @@ void exec( job_t *j )
if( io_buffer->param2.out_buffer->used != 0 )
{
- /*Temporary signal block for SIGCHLD */
- sigprocmask(SIG_BLOCK, &chldset, 0);
+
pid = fork ();
if (pid == 0)
{
@@ -965,12 +951,13 @@ void exec( job_t *j )
{
/*
This is the parent process. Store away
- information on the child, and possibly fice
+ information on the child, and possibly give
it control over the terminal.
*/
p->pid = pid;
if( handle_new_child( j, p ) )
- return;
+ exit(1);
+
}
}
@@ -1029,8 +1016,7 @@ void exec( job_t *j )
}
- /*Temporary signal block for SIGCHLD */
- sigprocmask(SIG_BLOCK, &chldset, 0);
+
pid = fork ();
if (pid == 0)
{
@@ -1064,7 +1050,8 @@ void exec( job_t *j )
p->pid = pid;
if( handle_new_child( j, p ) )
- return;
+ exit( 1 );
+
}
break;
@@ -1072,8 +1059,6 @@ void exec( job_t *j )
case EXTERNAL:
{
- /*Temporary signal block for SIGCHLD */
- sigprocmask(SIG_BLOCK, &chldset, 0);
// fwprintf( stderr,
// L"fork on %ls\n", j->command );
@@ -1108,7 +1093,8 @@ void exec( job_t *j )
p->pid = pid;
if( handle_new_child( j, p ) )
- return;
+ exit( 1 );
+
}
break;
@@ -1120,7 +1106,7 @@ void exec( job_t *j )
if(p->type == INTERNAL_BUILTIN)
builtin_pop_io();
- sigprocmask(SIG_UNBLOCK, &chldset, 0);
+
/*
Close the pipe the current process uses to read from the previous process_t
@@ -1143,6 +1129,8 @@ void exec( job_t *j )
}
}
+ signal_unblock();
+
debug( 3, L"Job is constructed" );
j->io = io_remove( j->io, &pipe_read );
@@ -1179,7 +1167,7 @@ int exec_subshell( const wchar_t *cmd,
PACKAGE_BUGREPORT );
return 0;
}
-
+
is_subshell=1;
io_buffer= io_buffer_create();
diff --git a/fish_tests.c b/fish_tests.c
index ad37c4c8..6eaae62b 100644
--- a/fish_tests.c
+++ b/fish_tests.c
@@ -616,6 +616,7 @@ int main( int argc, char **argv )
say( L"Testing low-level functionality");
say( L"Lines beginning with '(ignore):' are not errors, they are warning messages\ngenerated by the fish parser library when given broken input, and can be\nignored. All actual errors begin with 'Error:'." );
+ proc_init();
output_init();
event_init();
exec_init();
@@ -649,5 +650,6 @@ int main( int argc, char **argv )
exec_destroy();
event_destroy();
output_destroy();
+ proc_destroy();
}
diff --git a/main.c b/main.c
index 8fecbdef..98737f35 100644
--- a/main.c
+++ b/main.c
@@ -207,6 +207,7 @@ int main( int argc, char **argv )
if( force_interactive )
is_interactive_session=1;
+ proc_init();
output_init();
event_init();
exec_init();
@@ -306,7 +307,6 @@ int main( int argc, char **argv )
event_destroy();
output_destroy();
-
intern_free_all();
return res;
diff --git a/parser.c b/parser.c
index f0ca2f27..b3d063dd 100644
--- a/parser.c
+++ b/parser.c
@@ -477,7 +477,7 @@ wchar_t *parser_cdpath_get( wchar_t *dir )
{
die_mem();
}
-
+
for( nxt_path = wcstok( path_cpy, ARRAY_SEP_STR, &state );
nxt_path != 0;
nxt_path = wcstok( 0, ARRAY_SEP_STR, &state) )
@@ -1658,7 +1658,7 @@ static void eval_job( tokenizer *tok )
job_t *j;
int start_pos = job_start_pos = tok_get_pos( tok );
- debug( 2, L"begin eval_job()\n" );
+ debug( 2, L"begin eval_job()" );
long long t1=0, t2=0, t3=0;
profile_element_t *p=0;
int skip = 0;
@@ -1755,7 +1755,6 @@ static void eval_job( tokenizer *tok )
if( current_block->type == WHILE )
{
-// debug( 2, L"We are at begining of a while block\n" );
switch( current_block->param1.while_state )
{
@@ -1773,8 +1772,6 @@ static void eval_job( tokenizer *tok )
if( (!current_block->param1.if_state) &&
(!current_block->skip) )
{
-// debug( 2, L"Result of if block is %d\n", proc_get_last_status() );
-
current_block->skip = proc_get_last_status()!= 0;
current_block->param1.if_state++;
}
@@ -1840,7 +1837,7 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type )
if( !cmd )
{
debug( 1,
- L"Tried to evaluate null pointer\n" BUGREPORT_MSG,
+ L"Tried to evaluate null pointer. " BUGREPORT_MSG,
PACKAGE_BUGREPORT );
return 1;
}
@@ -1850,7 +1847,7 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type )
(block_type != SUBST))
{
debug( 1,
- L"Tried to evaluate buffer using invalid block scope of type '%ls'\n" BUGREPORT_MSG,
+ L"Tried to evaluate buffer using invalid block scope of type '%ls'. " BUGREPORT_MSG,
parser_get_block_desc( block_type ),
PACKAGE_BUGREPORT );
return 1;
@@ -1866,11 +1863,16 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type )
tok_init( current_tokenizer, cmd, 0 );
error_code = 0;
+ event_fire( 0, 0 );
+
while( tok_has_next( current_tokenizer ) &&
!error_code &&
!sanity_check() &&
!exit_status() )
+ {
eval_job( current_tokenizer );
+ event_fire( 0, 0 );
+ }
int prev_block_type = current_block->type;
parser_pop_block();
@@ -1880,7 +1882,7 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type )
if( current_block == 0 )
{
debug( 0,
- L"End of block mismatch\n"
+ L"End of block mismatch. "
L"Program terminating. "
BUGREPORT_MSG,
PACKAGE_BUGREPORT );
@@ -2300,8 +2302,8 @@ int parser_test( wchar_t * buff,
print_errors();
}
}
-
-
+
+
if( babble && count>0 )
{
error( SYNTAX_ERROR,
@@ -2309,9 +2311,9 @@ int parser_test( wchar_t * buff,
block_pos[count-1] );
print_errors();
}
-
+
tok_destroy( &tok );
-
+
current_tokenizer=previous_tokenizer;
current_tokenizer_pos = previous_pos;
diff --git a/proc.c b/proc.c
index c23da4fb..3f188ad8 100644
--- a/proc.c
+++ b/proc.c
@@ -75,6 +75,27 @@ int is_event=0;
int proc_had_barrier;
pid_t proc_last_bg_pid = 0;
+/**
+ List used to store arguments when firing events
+*/
+static array_list_t event_arg;
+/**
+ Stringbuffer used to create arguments when firing events
+*/
+static string_buffer_t event_pid;
+/**
+ Stringbuffer used to create arguments when firing events
+*/
+static string_buffer_t event_status;
+
+
+void proc_init()
+{
+ al_init( &event_arg );
+ sb_init( &event_pid );
+ sb_init( &event_status );
+}
+
/**
Recursively free a process and those following it
@@ -164,6 +185,9 @@ void job_free( job_t * j )
void proc_destroy()
{
+ al_destroy( &event_arg );
+ sb_destroy( &event_pid );
+ sb_destroy( &event_status );
while( first_job )
{
debug( 2, L"freeing leaked job %ls", first_job->command );
@@ -174,9 +198,6 @@ void proc_destroy()
void proc_set_last_status( int s )
{
last_status = s;
- wchar_t stat[16];
- swprintf( stat, 16, L"%d", s );
- env_set( L"status", stat, ENV_GLOBAL );
// fwprintf( stderr, L"Set last status to %d\n", s );
}
@@ -464,19 +485,8 @@ static void format_job_info( const job_t *j, const wchar_t *status )
static void fire_process_event( const wchar_t *msg, pid_t pid, int status )
{
static event_t ev;
- static array_list_t event_arg;
- static string_buffer_t event_pid, event_status;
- static int init=0;
-
event_t e;
- if( !init )
- {
- al_init( &event_arg );
- sb_init( &event_pid );
- sb_init( &event_status );
- init=1;
- }
e.function_name=0;
@@ -832,49 +842,34 @@ void job_continue (job_t *j, int cont)
{
if( !is_subshell && is_interactive && !is_block)
{
-
+
/* Put the job into the foreground. */
if( j->fg )
{
- while( 1 )
+ signal_block();
+ if( tcsetpgrp (0, j->pgid) )
{
- if( tcsetpgrp (0, j->pgid) )
- {
- if( errno != EINTR )
- {
- debug( 1,
- L"Could not send job %d ('%ls') to foreground",
- j->job_id,
- j->command );
- wperror( L"tcsetpgrp" );
- return;
- }
- }
- else
- break;
+ debug( 1,
+ L"Could not send job %d ('%ls') to foreground",
+ j->job_id,
+ j->command );
+ wperror( L"tcsetpgrp" );
+ return;
}
if( cont )
{
- while( 1 )
+ if( tcsetattr (0, TCSADRAIN, &j->tmodes))
{
- if( tcsetattr (0, TCSADRAIN, &j->tmodes))
- {
- if( errno != EINTR )
- {
- debug( 1,
- L"Could not send job %d ('%ls') to foreground",
- j->job_id,
- j->command );
- wperror( L"tcsetattr" );
- return;
- }
- }
- else
- break;
- }
-
+ debug( 1,
+ L"Could not send job %d ('%ls') to foreground",
+ j->job_id,
+ j->command );
+ wperror( L"tcsetattr" );
+ return;
+ }
}
+ signal_unblock();
}
}
@@ -976,57 +971,34 @@ void job_continue (job_t *j, int cont)
*/
if( !is_subshell && is_interactive && !is_block)
{
-
- while( 1 )
+ signal_block();
+ if( tcsetpgrp (0, getpid()) )
{
-
- if( tcsetpgrp (0, getpid()) )
- {
- if( errno != EINTR )
- {
- debug( 1, L"Could not return shell to foreground" );
- wperror( L"tcsetpgrp" );
- return;
- }
- }
- else break;
+ debug( 1, L"Could not return shell to foreground" );
+ wperror( L"tcsetpgrp" );
+ return;
}
/*
Save jobs terminal modes.
*/
- while( 1 )
+ if( tcgetattr (0, &j->tmodes) )
{
- if( tcgetattr (0, &j->tmodes) )
- {
- if( errno != EINTR )
- {
- debug( 1, L"Could not return shell to foreground" );
- wperror( L"tcgetattr" );
- return;
- }
- }
- else
- break;
+ debug( 1, L"Could not return shell to foreground" );
+ wperror( L"tcgetattr" );
+ return;
}
/*
Restore the shell's terminal modes.
*/
- while( 1 )
+ if( tcsetattr (0, TCSADRAIN, &shell_modes))
{
- if( tcsetattr (0, TCSADRAIN, &shell_modes))
- {
- if( errno != EINTR )
- {
- debug( 1, L"Could not return shell to foreground" );
- wperror( L"tcsetattr" );
- return;
- }
- }
- else
- break;
+ debug( 1, L"Could not return shell to foreground" );
+ wperror( L"tcsetattr" );
+ return;
}
+ signal_unblock();
}
}
}
diff --git a/proc.h b/proc.h
index 9c11a386..67539f71 100644
--- a/proc.h
+++ b/proc.h
@@ -196,11 +196,6 @@ int job_reap( int interactive );
*/
void job_handle_signal( int signal, siginfo_t *info, void *con );
-/**
- Clean up before exiting
-*/
-void proc_destroy();
-
#ifdef HAVE__PROC_SELF_STAT
/**
@@ -225,4 +220,14 @@ void proc_update_jiffies();
*/
void proc_sanity_check();
+/*
+ Initializations
+*/
+void proc_init();
+
+/**
+ Clean up before exiting
+*/
+void proc_destroy();
+
#endif
diff --git a/reader.c b/reader.c
index 5586c270..b74805e6 100644
--- a/reader.c
+++ b/reader.c
@@ -239,11 +239,6 @@ static reader_data_t *data=0;
static int end_loop = 0;
-/**
- This struct should be continually updated by signals as the term resizes, and as such always contain the correct current size.
-*/
-static struct winsize termsize;
-
static int new_size=0;
/**
@@ -285,8 +280,6 @@ static int interupted=0;
static void reader_save_status();
static void reader_check_status();
static void reader_super_highlight_me_plenty( wchar_t * buff, int *color, int pos, array_list_t *error );
-static void check_winch();
-
static struct termios old_modes;
@@ -332,8 +325,7 @@ static void term_steal()
break;
}
- reader_handle_winch(0 );
- check_winch();
+ common_handle_winch(0 );
if( tcsetattr(0,TCSANOW,&old_modes)) /* return to previous mode */
{
@@ -372,19 +364,6 @@ void reader_handle_int( int sig )
}
-
-int reader_get_width()
-{
- return termsize.ws_col;
-}
-
-
-int reader_get_height()
-{
- return termsize.ws_row;
-}
-
-
wchar_t *reader_current_filename()
{
return (wchar_t *)al_peek( &current_filename );
@@ -444,7 +423,7 @@ static int check_size()
*/
static int force_repaint()
{
- int max_width = reader_get_width() - data->prompt_width;
+ int max_width = common_get_width() - data->prompt_width;
int pref_width = my_wcswidth( data->buff ) + (data->buff_pos==data->buff_len);
return pref_width >= max_width;
}
@@ -457,7 +436,7 @@ static int force_repaint()
*/
static int calc_output()
{
- int max_width = reader_get_width() - data->prompt_width;
+ int max_width = common_get_width() - data->prompt_width;
int pref_width = my_wcswidth( data->buff ) + (data->buff_pos==data->buff_len);
if( pref_width <= max_width )
{
@@ -1405,7 +1384,7 @@ static int handle_completions( array_list_t *comp )
len = &data->buff[data->buff_pos]-prefix_start;
-
+
if( len <= PREFIX_MAX_LEN )
{
prefix = malloc( sizeof(wchar_t)*(len+1) );
@@ -1457,30 +1436,6 @@ static int handle_completions( array_list_t *comp )
}
}
-void reader_handle_winch( int signal )
-{
-
- if (ioctl(1,TIOCGWINSZ,&termsize)!=0)
- {
- return;
- }
- new_size=1;
-}
-
-static void check_winch()
-{
- if( new_size )
- {
- wchar_t tmp[64];
- new_size=0;
- swprintf(tmp, 64, L"%d", termsize.ws_row );
- env_set( L"LINES", tmp, ENV_GLOBAL );
- swprintf(tmp, 64, L"%d", termsize.ws_col );
- env_set( L"COLUMNS", tmp, ENV_GLOBAL );
- }
-}
-
-
/**
Reset the terminal. This function is placed in the list of
functions to call when exiting by using the atexit function. It
@@ -1539,8 +1494,7 @@ static void reader_interactive_init()
history_init();
- reader_handle_winch(0);
- check_winch();
+ common_handle_winch(0);
tcgetattr(0,&shell_modes); /* get the current terminal modes */
memcpy( &saved_modes,
@@ -2487,7 +2441,6 @@ wchar_t *reader_readline()
but it should be ignored. (Example: Trying to add a tilde
(~) to digit)
*/
- check_winch();
while( 1 )
{
c=input_readch();
@@ -2529,8 +2482,6 @@ wchar_t *reader_readline()
break;
}
-
- check_winch();
reader_check_status();
if( (last_char == R_COMPLETE) && (c != R_COMPLETE) && (!comp_empty) )
diff --git a/reader.h b/reader.h
index ac61098d..c152bd9a 100644
--- a/reader.h
+++ b/reader.h
@@ -54,19 +54,6 @@ void reader_push_current_filename( wchar_t *fn );
*/
wchar_t *reader_pop_current_filename();
-/**
- Returns the width of the terminal window, so that not all
- functions that use these values continually have to keep track of
- it.
-*/
-int reader_get_width();
-/**
- Returns the height of the terminal window, so that not all
- functions that use these values continually have to keep track of
- it.
-*/
-int reader_get_height();
-
/**
Write the title to the titlebar. This function is called just
before a new application starts executing and just after it
@@ -191,7 +178,9 @@ void reader_current_token_extent( wchar_t **a, wchar_t **b, wchar_t **pa, wchar_
*/
void reader_replace_current_token( wchar_t *new_token );
-void reader_handle_winch( int signal );
+/**
+ The readers interupt signal handler. Cancels all currently running blocks.
+*/
void reader_handle_int( int signal );
diff --git a/signal.c b/signal.c
index b31a1390..115e3837 100644
--- a/signal.c
+++ b/signal.c
@@ -313,7 +313,7 @@ static void default_handler(int signal, siginfo_t *info, void *context)
*/
static void handle_winch( int sig, siginfo_t *info, void *context )
{
- reader_handle_winch( sig );
+ common_handle_winch( sig );
default_handler( sig, 0, 0 );
}
@@ -395,7 +395,7 @@ void signal_set_handlers()
sigaction( SIGTTIN, &act, 0);
sigaction( SIGTTOU, &act, 0);
- act.sa_handler = &handle_int;
+ act.sa_sigaction = &handle_int;
act.sa_flags = SA_SIGINFO;
if( sigaction( SIGINT, &act, 0) )
{
@@ -412,7 +412,7 @@ void signal_set_handlers()
}
act.sa_flags = SA_SIGINFO;
- act.sa_handler= &handle_winch;
+ act.sa_sigaction= &handle_winch;
if( sigaction( SIGWINCH, &act, 0 ) )
{
wperror( L"sigaction" );
@@ -459,8 +459,46 @@ void signal_handle( int sig, int do_handle )
return;
sigemptyset( & act.sa_mask );
- act.sa_flags=SA_SIGINFO;
- act.sa_sigaction = (do_handle?&default_handler:SIG_DFL);
+ if( do_handle )
+ {
+ act.sa_flags=SA_SIGINFO;
+ act.sa_sigaction = &default_handler;
+ }
+ else
+ {
+ act.sa_flags=0;
+ act.sa_handler = SIG_DFL;
+ }
+
sigaction( sig, &act, 0);
}
+void signal_block()
+{
+ int i;
+ sigset_t chldset;
+ sigemptyset( &chldset );
+
+ for( i=0; lookup[i].desc ; i++ )
+ {
+ sigaddset( &chldset, lookup[i].signal );
+ }
+
+ sigprocmask(SIG_BLOCK, &chldset, 0);
+}
+
+void signal_unblock()
+{
+ int i;
+ sigset_t chldset;
+ sigemptyset( &chldset );
+
+ for( i=0; lookup[i].desc ; i++ )
+ {
+ sigaddset( &chldset, lookup[i].signal );
+ }
+
+ sigprocmask(SIG_UNBLOCK, &chldset, 0);
+}
+
+
diff --git a/signal.h b/signal.h
index ef491a14..d7878ae1 100644
--- a/signal.h
+++ b/signal.h
@@ -31,6 +31,19 @@ void signal_reset_handlers();
void signal_set_handlers();
/**
- Tell fish to catch the specified signal and fire an event, instead of performing the default action
+ Tell fish what to do on the specified signal.
+
+ \param sig The signal to specify the action of
+ \param do_handle If true fish will catch the specified signal and fire an event, otherwise the default action (SIG_DFL) will be set
*/
void signal_handle( int sig, int do_handle );
+
+/*
+ Block all signals
+*/
+void signal_block();
+
+/**
+ Unblock all signals
+*/
+void signal_unblock();
diff --git a/wutil.c b/wutil.c
index 09b26d76..7f8b0984 100644
--- a/wutil.c
+++ b/wutil.c
@@ -194,23 +194,26 @@ void wperror(const wchar_t *s)
#if !HAVE_WPRINTF
-/*
- Here is my own implementation of *wprintf, included since NetBSD does
- not provide one of it's own.
-*/
/**
- This function is defined to help vgwprintf when it wants to call
- itself recursively
-*/
-static int gwprintf( void (*writer)(wchar_t),
- const wchar_t *filter,
- ... );
-
-
-/**
- Generic formatting function. All other formatting functions are
- secretly a wrapper around this function.
+ Generic formatting function. All other string formatting functions
+ are secretly a wrapper around this function. vgprintf does not
+ implement all the filters supported by printf, only those that are
+ currently used by fish. vgprintf internally uses snprintf to
+ implement the %f %d and %u filters.
+
+ Currently supported functionality:
+
+ - precision specification, both through .* and .N
+ - width specification through *
+ - long versions of all filters thorugh l and ll prefix
+ - Character outout using %c
+ - String output through %s
+ - Floating point number output through %f
+ - Integer output through %d or %i
+ - Unsigned integer output through %u
+
+ For a full description on the usage of *printf, see use 'man 3 printf'.
*/
static int vgwprintf( void (*writer)(wchar_t),
const wchar_t *filter,
@@ -530,21 +533,6 @@ static int vgwprintf( void (*writer)(wchar_t),
return count;
}
-static int gwprintf( void (*writer)(wchar_t),
- const wchar_t *filter,
- ... )
-{
- va_list va;
- int written;
-
- va_start( va, filter );
- written=vgwprintf( writer,
- filter,
- va );
- va_end( va );
- return written;
-}
-
/**
Holds data for swprintf writer
*/