diff --git a/builtin.c b/builtin.c index 3ba5434..fe59ce2 100644 --- a/builtin.c +++ b/builtin.c @@ -2849,7 +2849,7 @@ static int builtin_source( wchar_t ** argv ) sb_printf( sb_err, _( L"%ls: Error while reading file '%ls'\n" ), argv[0], - fn_intern == L"-" ? L"" : fn_intern ); + fn_intern == intern_static(L"-") ? L"" : fn_intern ); } else { diff --git a/common.c b/common.c index 193783c..2dd125b 100644 --- a/common.c +++ b/common.c @@ -578,6 +578,36 @@ int read_blocked(int fd, void *buf, size_t count) return res; } +ssize_t write_loop(int fd, char *buff, size_t count) +{ + ssize_t out=0; + ssize_t out_cum=0; + while( 1 ) + { + out = write( fd, + &buff[out_cum], + count - out_cum ); + if (out == -1) + { + if( errno != EAGAIN && + errno != EINTR ) + { + return -1; + } + } else + { + out_cum += out; + } + if( out_cum >= count ) + { + break; + } + } + return out_cum; +} + + + void debug( int level, const wchar_t *msg, ... ) { va_list va; @@ -1815,7 +1845,14 @@ double timef() if( time_res ) { - return nan(0); + /* + Fixme: What on earth is the correct parameter value for NaN? + The man pages and the standard helpfully state that this + parameter is implementation defined. Gcc gives a warning if + a null pointer is used. But not even all mighty Google gives + a hint to what value should actually be returned. + */ + return nan(""); } return (double)tv.tv_sec + 0.000001*tv.tv_usec; diff --git a/common.h b/common.h index fc3b637..115785f 100644 --- a/common.h +++ b/common.h @@ -331,6 +331,12 @@ __sentinel int contains_internal( const wchar_t *needle, ... ); */ int read_blocked(int fd, void *buf, size_t count); +/** + Loop a write request while failiure is non-critical. Return -1 and set errno + in case of critical error. + */ +ssize_t write_loop(int fd, char *buff, size_t count); + /** Issue a debug message with printf-style string formating and diff --git a/exec.c b/exec.c index a6b9899..921002e 100644 --- a/exec.c +++ b/exec.c @@ -53,6 +53,11 @@ */ #define FD_ERROR _( L"An error occurred while redirecting file descriptor %d" ) +/** + file descriptor redirection error message +*/ +#define WRITE_ERROR _( L"An error occurred while writing output" ) + /** file redirection error message */ @@ -92,6 +97,18 @@ static array_list_t *open_fds=0; static int set_child_group( job_t *j, process_t *p, int print_errors ); +static void exec_write_and_exit( int fd, char *buff, size_t count, int status ) +{ + if( write_loop(fd, buff, count) == -1 ) + { + debug( 0, WRITE_ERROR); + wperror( L"write" ); + exit(status); + } + exit( status ); +} + + void exec_close( int fd ) { int i; @@ -1426,15 +1443,17 @@ void exec( job_t *j ) if( pid == 0 ) { + /* This is the child process. Write out the contents of the pipeline. */ p->pid = getpid(); setup_child_process( j, p ); - write( io_buffer->fd, - io_buffer->param2.out_buffer->buff, - io_buffer->param2.out_buffer->used ); - exit( status ); + + exec_write_and_exit(io_buffer->fd, + io_buffer->param2.out_buffer->buff, + io_buffer->param2.out_buffer->used, + status); } else { @@ -1480,10 +1499,10 @@ void exec( job_t *j ) p->pid = getpid(); setup_child_process( j, p ); - write( 1, - input_redirect->param2.out_buffer->buff, - input_redirect->param2.out_buffer->used ); - exit( 0 ); + exec_write_and_exit( 1, + input_redirect->param2.out_buffer->buff, + input_redirect->param2.out_buffer->used, + 0); } else { diff --git a/fish_pager.c b/fish_pager.c index 533bc0f..49c154c 100644 --- a/fish_pager.c +++ b/fish_pager.c @@ -351,7 +351,7 @@ static int pager_buffered_writer( char c) */ static void pager_flush() { - write( 1, pager_buffer->buff, pager_buffer->used ); + write_loop( 1, pager_buffer->buff, pager_buffer->used ); pager_buffer->used = 0; } diff --git a/fishd.c b/fishd.c index 0437c09..cb018d7 100644 --- a/fishd.c +++ b/fishd.c @@ -521,7 +521,7 @@ static void load_or_save( int save) if( save ) { - write( c.fd, SAVE_MSG, strlen(SAVE_MSG) ); + write_loop( c.fd, SAVE_MSG, strlen(SAVE_MSG) ); enqueue_all( &c ); } else diff --git a/mimedb.c b/mimedb.c index bad9b87..d63a1ac 100644 --- a/mimedb.c +++ b/mimedb.c @@ -94,6 +94,17 @@ license. Read the source code of the library for more information. */ #define GETOPT_STRING "tfimdalhv" +/** + Error message if system call goes wrong. +*/ +#define ERROR_SYSTEM "%s: Could not execute command \"%s\"\n" + +/** + Exit code if system call goes wrong. +*/ +#define STATUS_ERROR_SYSTEM 1 + + /** All types of input and output possible */ @@ -1127,8 +1138,12 @@ static void launch( char *filter, array_list_t *files, int fileno ) writer( '&' ); writer( '\0' ); -// fprintf( stderr, "mimedb: %s\n", launch_buff ); - system( launch_buff ); + if( system( launch_buff ) == -1 ) + { + fprintf( stderr, _( ERROR_SYSTEM ), MIMEDB, launch_buff ); + exit(STATUS_ERROR_SYSTEM); + } + break; } } diff --git a/output.c b/output.c index eb37933..5ced20e 100644 --- a/output.c +++ b/output.c @@ -362,7 +362,7 @@ void set_color( int c, int c2 ) */ static int writeb_internal( char c ) { - write( 1, &c, 1 ); + write_loop( 1, &c, 1 ); return 0; } diff --git a/parser.c b/parser.c index 7a22f8a..2f21413 100644 --- a/parser.c +++ b/parser.c @@ -436,6 +436,7 @@ typedef struct /** Return the current number of block nestings */ +/* static int block_count( block_t *b ) { @@ -443,7 +444,7 @@ static int block_count( block_t *b ) return 0; return( block_count(b->outer)+1); } - +*/ void parser_push_block( int type ) { diff --git a/print_help.c b/print_help.c index 72344cd..06270d2 100644 --- a/print_help.c +++ b/print_help.c @@ -5,18 +5,26 @@ #include #include - +#include #include "print_help.h" #define CMD_LEN 1024 +#define HELP_ERR "Could not show help message\n" + void print_help( char *c, int fd ) { char cmd[ CMD_LEN]; int printed = snprintf( cmd, CMD_LEN, "fish -c '__fish_print_help %s >&%d'", c, fd ); if( printed < CMD_LEN ) - system( cmd ); + { + if( (system( cmd ) == -1) ) + { + write_loop(2, HELP_ERR, strlen(HELP_ERR)); + } + } + } diff --git a/proc.c b/proc.c index 0b9c4ba..35dff1d 100644 --- a/proc.c +++ b/proc.c @@ -356,6 +356,8 @@ static void mark_process_status( job_t *j, } else { + ssize_t ignore; + /* This should never be reached */ p->completed = 1; @@ -364,8 +366,12 @@ static void mark_process_status( job_t *j, MESS_SIZE, "Process %d exited abnormally\n", (int) p->pid ); - - write( 2, mess, strlen(mess) ); + /* + If write fails, do nothing. We're in a signal handlers error + handler. If things aren't working properly, it's safer to + give up. + */ + ignore = write( 2, mess, strlen(mess) ); } } diff --git a/reader.c b/reader.c index 257fe06..f47a417 100644 --- a/reader.c +++ b/reader.c @@ -1577,9 +1577,9 @@ static int handle_completions( array_list_t *comp ) wchar_t quote; get_param( data->buff, data->buff_pos, "e, 0, 0, 0 ); is_quoted = (quote != L'\0'); - - write(1, "\n", 1 ); - + + write_loop(1, "\n", 1 ); + run_pager( prefix, is_quoted, comp ); } @@ -2650,7 +2650,7 @@ wchar_t *reader_readline() case R_REPAINT: { exec_prompt(); - write( 1, "\r", 1 ); + write_loop( 1, "\r", 1 ); s_reset( &data->screen, 0 ); reader_repaint(); break; diff --git a/screen.c b/screen.c index 949eac4..8ffaeac 100644 --- a/screen.c +++ b/screen.c @@ -337,7 +337,7 @@ static void s_check_status( screen_t *s) */ int prev_line = s->actual_cursor[1]; - write( 1, "\r", 1 ); + write_loop( 1, "\r", 1 ); s_reset( s, 0 ); s->actual_cursor[1] = prev_line; } @@ -756,7 +756,7 @@ static void s_update( screen_t *scr, wchar_t *prompt ) if( output.used ) { - write( 1, output.buff, output.used ); + write_loop( 1, output.buff, output.used ); } b_destroy( &output ); @@ -804,9 +804,9 @@ void s_write( screen_t *s, char *prompt_narrow = wcs2str( prompt ); char *buffer_narrow = wcs2str( b ); - write( 1, "\r", 1 ); - write( 1, prompt_narrow, strlen( prompt_narrow ) ); - write( 1, buffer_narrow, strlen( buffer_narrow ) ); + write_loop( 1, "\r", 1 ); + write_loop( 1, prompt_narrow, strlen( prompt_narrow ) ); + write_loop( 1, buffer_narrow, strlen( buffer_narrow ) ); free( prompt_narrow ); free( buffer_narrow ); @@ -938,7 +938,7 @@ void s_reset( screen_t *s, int reset_cursor ) This should prevent reseting the cursor position during the next repaint. */ - write( 1, "\r", 1 ); + write_loop( 1, "\r", 1 ); s->actual_cursor[1] = prev_line; } fstat( 1, &s->prev_buff_1 );