From 9ae7fa5831cbc0a7d221c566bcd8633e609b9670 Mon Sep 17 00:00:00 2001 From: axel Date: Sat, 8 Oct 2005 21:20:51 +1000 Subject: Move io redirection functions to their own library darcs-hash:20051008112051-ac50b-113caa4cba470a739e4bfbed9f479e2fed357be7.gz --- Makefile.in | 2 +- builtin.c | 3 +- exec.c | 172 ++++++++++--------------------------------------- exec.h | 19 +++--- io.c | 209 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ io.h | 87 +++++++++++++++++++++++++ proc.c | 81 ----------------------- proc.h | 67 +------------------ reader.c | 6 +- 9 files changed, 347 insertions(+), 299 deletions(-) create mode 100644 io.c create mode 100644 io.h diff --git a/Makefile.in b/Makefile.in index e3c242cd..3c44c2ec 100644 --- a/Makefile.in +++ b/Makefile.in @@ -52,7 +52,7 @@ COMMON_OBJS := function.o builtin.o common.o complete.o env.o exec.o \ expand.o highlight.o history.o kill.o parser.o proc.o reader.o \ sanity.o tokenizer.o util.o wildcard.o wgetopt.o wutil.o input.o \ output.o intern.o env_universal.o env_universal_common.o \ - input_common.o event.o signal.o + input_common.o event.o signal.o io.o # builtin_help.h exists, but builtin_help.c is autogenerated COMMON_OBJS_WITH_HEADER := builtin_help.o diff --git a/builtin.c b/builtin.c index aaa3db58..f621611a 100644 --- a/builtin.c +++ b/builtin.c @@ -58,6 +58,7 @@ #include "input.h" #include "intern.h" #include "event.h" +#include "signal.h" /** The default prompt for the read command @@ -2500,8 +2501,6 @@ static int builtin_end( wchar_t **argv ) case FUNCTION_DEF: { - int i; - /** Copy the text from the beginning of the function until the end command and use as the new definition diff --git a/exec.c b/exec.c index ba58fc56..d4025ebb 100644 --- a/exec.c +++ b/exec.c @@ -34,6 +34,7 @@ #include "wildcard.h" #include "sanity.h" #include "expand.h" +#include "signal.h" #include "env_universal.h" /** @@ -52,10 +53,6 @@ pid_t getpgid( pid_t pid ); file redirection error message */ #define FILE_ERROR L"An error occurred while redirecting file '%ls'" -/** - pipe redirection error message -*/ -#define PIPE_ERROR L"An error occurred while setting up pipe" /** fork error message */ @@ -68,11 +65,7 @@ pid_t getpgid( pid_t pid ); */ array_list_t *open_fds=0; -/** - Loops over close until thesyscall was run without beeing - interrupted. Thenremoves the fd from the open_fds list. -*/ -static void close_loop( int fd ) +void exec_close( int fd ) { int i; @@ -105,13 +98,19 @@ static void close_loop( int fd ) } -/** - Call pipe(), and add resulting fds to open_fds, the list of opend - file descriptors for pipes. -*/ -static int internal_pipe( int fd[2]) +int exec_pipe( int fd[2]) { - int res = pipe( fd ); + int res; + + while( ( res=pipe( fd ) ) ) + { + if( errno != EINTR ) + { + wperror(L"pipe"); + return res; + } + } + if( open_fds == 0 ) { open_fds = malloc( sizeof( array_list_t ) ); @@ -172,7 +171,7 @@ static void close_unused_internal_pipes( io_data_t *io ) if( !use_fd_in_pipe( n, io) ) { debug( 4, L"Close fd %d, used in other context", n ); - close_loop( n ); + exec_close( n ); i--; } } @@ -237,7 +236,7 @@ static void handle_child_io( io_data_t *io ) close_unused_internal_pipes( io ); if( env_universal_server.fd >= 0 ) - close_loop( env_universal_server.fd ); + exec_close( env_universal_server.fd ); for( ; io; io=io->next ) { @@ -296,7 +295,7 @@ static void handle_child_io( io_data_t *io ) wperror( L"dup2" ); exit(1); } - close_loop( tmp ); + exec_close( tmp ); } break; case IO_FD: @@ -337,11 +336,11 @@ static void handle_child_io( io_data_t *io ) if( fd_to_dup != 0 ) { - close_loop( io->pipe_fd[0]); - close_loop( io->pipe_fd[1]); + exec_close( io->pipe_fd[0]); + exec_close( io->pipe_fd[1]); } else - close_loop( io->pipe_fd[0] ); + exec_close( io->pipe_fd[0] ); /* if( close( io[i].pipe_fd[ io->fd ] ) == -1 ) @@ -438,109 +437,6 @@ static int has_fd( io_data_t *d, int fd ) } -/** - Read from descriptors until they are empty. -*/ -void exec_read_io_buffer( io_data_t *d ) -{ - - close_loop(d->pipe_fd[1] ); - - if( d->io_mode == IO_BUFFER ) - { - if( fcntl( d->pipe_fd[0], F_SETFL, 0 ) ) - { - wperror( L"fcntl" ); - return; - } - debug( 4, L"exec_read_io_buffer: blocking read on fd %d", d->pipe_fd[0] ); - - while(1) - { - char b[4096]; - int l; - l=read_blocked( d->pipe_fd[0], b, 4096 ); - if( l==0 ) - { - break; - } - else if( l<0 ) - { - /* - exec_read_io_buffer is only called on jobs that have - exited, and will therefore never block. But a broken - pipe seems to cause some flags to reset, causing the - EOF flag to not be set. Therefore, EAGAIN is ignored - and we exit anyway. - */ - if( errno != EAGAIN ) - { - debug( 1, - L"An error occured while reading output from code block on fd %d", - d->pipe_fd[0] ); - wperror( L"exec_read_io_buffer" ); - } - - break; - } - else - { - b_append( d->out_buffer, b, l ); - } - } - } -} - - -io_data_t *exec_make_io_buffer() -{ - io_data_t *buffer_redirect = malloc( sizeof( io_data_t )); - - buffer_redirect->io_mode=IO_BUFFER; - buffer_redirect->next=0; - buffer_redirect->out_buffer= malloc( sizeof(buffer_t)); - b_init( buffer_redirect->out_buffer ); - buffer_redirect->fd=1; - - - if( internal_pipe( buffer_redirect->pipe_fd ) == -1 ) - { - debug( 1, PIPE_ERROR ); - wperror (L"pipe"); - free( buffer_redirect->out_buffer ); - free( buffer_redirect ); - return 0; - } - else if( fcntl( buffer_redirect->pipe_fd[0], - F_SETFL, - O_NONBLOCK ) ) - { - debug( 1, PIPE_ERROR ); - wperror( L"fcntl" ); - free( buffer_redirect->out_buffer ); - free( buffer_redirect ); - return 0; - } - return buffer_redirect; -} - -void exec_free_io_buffer( io_data_t *io_buffer ) -{ - - close_loop( io_buffer->pipe_fd[0] ); - - /* - Dont free fd for writing. This should already be free'd before - calling exec_read_io_buffer on the buffer - */ - - b_destroy( io_buffer->out_buffer ); - - free( io_buffer->out_buffer ); - free( io_buffer ); -} - - /** Make a copy of the specified io redirection chain, but change file redirection into fd redirection. */ @@ -612,7 +508,7 @@ static void io_untransmogrify( io_data_t * in, io_data_t *out ) switch( in->io_mode ) { case IO_FILE: - close_loop( out->old_fd ); + exec_close( out->old_fd ); break; } free(out); @@ -846,7 +742,7 @@ void exec( job_t *j ) if (p->next) { - if (internal_pipe( mypipe ) == -1) + if (exec_pipe( mypipe ) == -1) { debug( 1, PIPE_ERROR ); wperror (L"pipe"); @@ -911,7 +807,7 @@ void exec( job_t *j ) if( p->next ) { // fwprintf( stderr, L"Function %ls\n", def ); - io_buffer = exec_make_io_buffer(); + io_buffer = io_buffer_create(); j->io = io_add( j->io, io_buffer ); } @@ -928,7 +824,7 @@ void exec( job_t *j ) if( p->next ) { // fwprintf( stderr, L"Block %ls\n", p->argv[0] ); - io_buffer = exec_make_io_buffer(); + io_buffer = io_buffer_create(); j->io = io_add( j->io, io_buffer ); } @@ -1034,7 +930,7 @@ void exec( job_t *j ) if( close_stdin ) { // fwprintf( stderr, L"Close builtin_stdin\n" ); - close_loop( builtin_stdin ); + exec_close( builtin_stdin ); } break; } @@ -1062,9 +958,7 @@ void exec( job_t *j ) j->io = io_remove( j->io, io_buffer ); - debug( 3, L"exec_read_io_buffer on block '%ls'", p->argv[0] ); - - exec_read_io_buffer( io_buffer ); + io_buffer_read( io_buffer ); if( io_buffer->out_buffer->used != 0 ) { @@ -1105,7 +999,7 @@ void exec( job_t *j ) } - exec_free_io_buffer( io_buffer ); + io_buffer_destroy( io_buffer ); io_buffer=0; break; @@ -1256,7 +1150,7 @@ void exec( job_t *j ) Close the pipe the current process uses to read from the previous process_t */ if( pipe_read.pipe_fd[0] >= 0 ) - close_loop( pipe_read.pipe_fd[0] ); + exec_close( pipe_read.pipe_fd[0] ); /* Set up the pipe the next process uses to read from the current process_t */ @@ -1269,7 +1163,7 @@ void exec( job_t *j ) */ if( p->next ) { - close_loop(mypipe[1]); + exec_close(mypipe[1]); } } @@ -1309,14 +1203,14 @@ int exec_subshell( const wchar_t *cmd, } is_subshell=1; - io_buffer= exec_make_io_buffer(); + io_buffer= io_buffer_create(); prev_status = proc_get_last_status(); eval( cmd, io_buffer, SUBST ); debug( 4, L"exec_read_io_buffer on cmdsub '%ls'", cmd ); - exec_read_io_buffer( io_buffer ); + io_buffer_read( io_buffer ); status = proc_get_last_status(); proc_set_last_status( prev_status ); @@ -1341,7 +1235,7 @@ int exec_subshell( const wchar_t *cmd, if( el ) al_push( l, el ); } - exec_free_io_buffer( io_buffer ); + io_buffer_destroy( io_buffer ); return status; @@ -1359,6 +1253,6 @@ int exec_subshell( const wchar_t *cmd, } } - exec_free_io_buffer( io_buffer ); + io_buffer_destroy( io_buffer ); return status; } diff --git a/exec.h b/exec.h index 14802636..21a5bac9 100644 --- a/exec.h +++ b/exec.h @@ -10,6 +10,11 @@ #include "proc.h" #include "util.h" +/** + pipe redirection error message +*/ +#define PIPE_ERROR L"An error occurred while setting up pipe" + /** Initialize the exec library */ @@ -57,19 +62,17 @@ void exec( job_t *j ); int exec_subshell( const wchar_t *cmd, array_list_t *l ); -/** - Free all resources used by a IO_BUFFER type io redirection. -*/ -void exec_free_io_buffer( io_data_t *io_buffer ); /** - Create a IO_BUFFER type io redirection. + Loops over close until thesyscall was run without beeing + interrupted. Thenremoves the fd from the open_fds list. */ -io_data_t *exec_make_io_buffer(); +void exec_close( int fd ); /** - Close writing end of IO_BUFFER type io redirection, and fully read the reading end. + Call pipe(), and add resulting fds to open_fds, the list of opend + file descriptors for pipes. */ -void exec_read_io_buffer( io_data_t *d ); +int exec_pipe( int fd[2]); #endif diff --git a/io.c b/io.c new file mode 100644 index 00000000..86397955 --- /dev/null +++ b/io.c @@ -0,0 +1,209 @@ +/** \file io.c + +Utilities for io redirection. + +*/ +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if HAVE_NCURSES_H +#include +#else +#include +#endif + +#if HAVE_TERMIO_H +#include +#endif + +#include + +#include "util.h" +#include "wutil.h" +#include "exec.h" +#include "common.h" +#include "io.h" + + + +void io_buffer_read( io_data_t *d ) +{ + + exec_close(d->pipe_fd[1] ); + + if( d->io_mode == IO_BUFFER ) + { + if( fcntl( d->pipe_fd[0], F_SETFL, 0 ) ) + { + wperror( L"fcntl" ); + return; + } + debug( 4, L"exec_read_io_buffer: blocking read on fd %d", d->pipe_fd[0] ); + + while(1) + { + char b[4096]; + int l; + l=read_blocked( d->pipe_fd[0], b, 4096 ); + if( l==0 ) + { + break; + } + else if( l<0 ) + { + /* + exec_read_io_buffer is only called on jobs that have + exited, and will therefore never block. But a broken + pipe seems to cause some flags to reset, causing the + EOF flag to not be set. Therefore, EAGAIN is ignored + and we exit anyway. + */ + if( errno != EAGAIN ) + { + debug( 1, + L"An error occured while reading output from code block on fd %d", + d->pipe_fd[0] ); + wperror( L"exec_read_io_buffer" ); + } + + break; + } + else + { + b_append( d->out_buffer, b, l ); + } + } + } +} + + +io_data_t *io_buffer_create() +{ + io_data_t *buffer_redirect = malloc( sizeof( io_data_t )); + + buffer_redirect->io_mode=IO_BUFFER; + buffer_redirect->next=0; + buffer_redirect->out_buffer= malloc( sizeof(buffer_t)); + b_init( buffer_redirect->out_buffer ); + buffer_redirect->fd=1; + + + if( exec_pipe( buffer_redirect->pipe_fd ) == -1 ) + { + debug( 1, PIPE_ERROR ); + wperror (L"pipe"); + free( buffer_redirect->out_buffer ); + free( buffer_redirect ); + return 0; + } + else if( fcntl( buffer_redirect->pipe_fd[0], + F_SETFL, + O_NONBLOCK ) ) + { + debug( 1, PIPE_ERROR ); + wperror( L"fcntl" ); + free( buffer_redirect->out_buffer ); + free( buffer_redirect ); + return 0; + } + return buffer_redirect; +} + +void io_buffer_destroy( io_data_t *io_buffer ) +{ + + exec_close( io_buffer->pipe_fd[0] ); + + /* + Dont free fd for writing. This should already be free'd before + calling exec_read_io_buffer on the buffer + */ + + b_destroy( io_buffer->out_buffer ); + + free( io_buffer->out_buffer ); + free( io_buffer ); +} + + + +io_data_t *io_add( io_data_t *list, io_data_t *element ) +{ + io_data_t *curr = list; + if( curr == 0 ) + return element; + while( curr->next != 0 ) + curr = curr->next; + curr->next = element; + return list; +} + +io_data_t *io_remove( io_data_t *list, io_data_t *element ) +{ + io_data_t *curr, *prev=0; + for( curr=list; curr; curr = curr->next ) + { + if( element == curr ) + { + if( prev == 0 ) + { + io_data_t *tmp = element->next; + element->next = 0; + return tmp; + } + else + { + prev->next = element->next; + element->next = 0; + return list; + } + } + prev = curr; + } + return list; +} + +io_data_t *io_duplicate( io_data_t *l ) +{ + io_data_t *res; + + if( l == 0 ) + return 0; + + res = malloc( sizeof( io_data_t) ); + + if( !res ) + { + die_mem(); + + } + + memcpy( res, l, sizeof(io_data_t )); + res->next=io_duplicate( l->next ); + return res; +} + +io_data_t *io_get( io_data_t *io, int fd ) +{ + if( io == 0 ) + return 0; + + io_data_t *res = io_get( io->next, fd ); + if( res ) + return res; + + if( io->fd == fd ) + return io; + + return 0; +} + diff --git a/io.h b/io.h new file mode 100644 index 00000000..6cb103be --- /dev/null +++ b/io.h @@ -0,0 +1,87 @@ +#ifndef FISH_IO_H +#define FISH_IO_H + +/** + Describes what type of IO operation an io_data_t represents +*/ +enum io_mode +{ + IO_FILE, IO_PIPE, IO_FD, IO_BUFFER, IO_CLOSE +} +; + +/** Represents an FD redirection */ +typedef struct io_data +{ + /** Type of redirect */ + int io_mode; + /** FD to redirect */ + int fd; + /** parameter for redirection */ + union + { + /** Fds for IO_PIPE and for IO_BUFFER */ + int pipe_fd[2]; + /** Filename IO_FILE */ + wchar_t *filename; + /** fd to redirect specified fd to, for IO_FD*/ + int old_fd; + } + ; + union + { + /** file creation flags to send to open for IO_FILE */ + int flags; + /** buffer to save output in for IO_BUFFER */ + buffer_t *out_buffer; + /** Whether to close old_fd for IO_FD */ + int close_old; + + } + ; + + /** Pointer to the next IO redirection */ + struct io_data *next; +} +io_data_t; + + +/** + Join two chains of io redirections +*/ +io_data_t *io_add( io_data_t *first_chain, io_data_t *decond_chain ); + +/** + Remove the specified io redirection from the chain +*/ +io_data_t *io_remove( io_data_t *list, io_data_t *element ); + +/** + Make a copy of the specified chain of redirections +*/ +io_data_t *io_duplicate( io_data_t *l ); + +/** + Return the last io redirection in ht e chain for the specified file descriptor. +*/ +io_data_t *io_get( io_data_t *io, int fd ); + + + +/** + Free all resources used by a IO_BUFFER type io redirection. +*/ +void io_buffer_destroy( io_data_t *io_buffer ); + +/** + Create a IO_BUFFER type io redirection, complete with a pipe and a + buffer_t for output. +*/ +io_data_t *io_buffer_create(); + +/** + Close output pipe, and read from input pipe until eof. +*/ +void io_buffer_read( io_data_t *d ); + +#endif diff --git a/proc.c b/proc.c index b4cfd27f..0e73f518 100644 --- a/proc.c +++ b/proc.c @@ -74,77 +74,6 @@ int is_event=0; int proc_had_barrier; pid_t proc_last_bg_pid = 0; -io_data_t *io_add( io_data_t *list, io_data_t *element ) -{ - io_data_t *curr = list; - if( curr == 0 ) - return element; - while( curr->next != 0 ) - curr = curr->next; - curr->next = element; - return list; -} - -io_data_t *io_remove( io_data_t *list, io_data_t *element ) -{ - io_data_t *curr, *prev=0; - for( curr=list; curr; curr = curr->next ) - { - if( element == curr ) - { - if( prev == 0 ) - { - io_data_t *tmp = element->next; - element->next = 0; - return tmp; - } - else - { - prev->next = element->next; - element->next = 0; - return list; - } - } - prev = curr; - } - return list; -} - -io_data_t *io_duplicate( io_data_t *l ) -{ - io_data_t *res; - - if( l == 0 ) - return 0; - - res = malloc( sizeof( io_data_t) ); - - if( !res ) - { - die_mem(); - - } - - memcpy( res, l, sizeof(io_data_t )); - res->next=io_duplicate( l->next ); - return res; -} - -io_data_t *io_get( io_data_t *io, int fd ) -{ - if( io == 0 ) - return 0; - - io_data_t *res = io_get( io->next, fd ); - if( res ) - return res; - - if( io->fd == fd ) - return io; - - return 0; -} - /** Recursively free a process and those following it @@ -368,7 +297,6 @@ static void mark_process_status( job_t *j, else { p->completed = 1; -// fwprintf( stderr, L"Proc %d (%ls) exited\n", p->pid, p->actual_cmd ); if (( !WIFEXITED( status ) ) && (! WIFSIGNALED( status )) ) @@ -743,15 +671,6 @@ static int select_try( job_t *j ) int maxfd=-1; io_data_t *d; - - -/* if( j->stop_reading ) - { - sleep(1); - return; - } -*/ - FD_ZERO(&fds); for( d = j->io; d; d=d->next ) diff --git a/proc.h b/proc.h index 6e67c377..9f8e85d6 100644 --- a/proc.h +++ b/proc.h @@ -16,15 +16,8 @@ #include #include "util.h" +#include "io.h" -/** - Describes what type of IO operation an io_data_t represents -*/ -enum io_mode -{ - IO_FILE, IO_PIPE, IO_FD, IO_BUFFER, IO_CLOSE -} -; /** Types of internal processes @@ -40,44 +33,8 @@ enum ; -/** Represents an FD redirection */ -typedef struct io_data -{ - /** Type of redirect */ - int io_mode; - /** FD to redirect */ - int fd; - /** parameter for redirection */ - union - { - /** Fds for IO_PIPE and for IO_BUFFER */ - int pipe_fd[2]; - /** Filename IO_FILE */ - wchar_t *filename; - /** fd to redirect specified fd to, for IO_FD*/ - int old_fd; - } - ; - union - { - /** file creation flags to send to open for IO_FILE */ - int flags; - /** buffer to save output in for IO_BUFFER */ - buffer_t *out_buffer; - /** Whether to close old_fd for IO_FD */ - int close_old; - - } - ; - - /** Pointer to the next IO redirection */ - struct io_data *next; -} -io_data_t; - - /** - A structore representing a single process. Contains variables for + A structure representing a single process. Contains variables for tracking process state and the process argument list. */ typedef struct process{ @@ -177,26 +134,6 @@ extern int proc_had_barrier; extern pid_t proc_last_bg_pid; -/** - Join two chains of io redirections -*/ -io_data_t *io_add( io_data_t *first_chain, io_data_t *decond_chain ); - -/** - Remove the specified io redirection from the chain -*/ -io_data_t *io_remove( io_data_t *list, io_data_t *element ); - -/** - Make a copy of the specified chain of redirections -*/ -io_data_t *io_duplicate( io_data_t *l ); - -/** - Return the last io redirection in ht e chain for the specified file descriptor. -*/ -io_data_t *io_get( io_data_t *io, int fd ); - /** Sets the status of the last process to exit */ diff --git a/reader.c b/reader.c index 89f2bc64..f1ae2e23 100644 --- a/reader.c +++ b/reader.c @@ -1260,12 +1260,12 @@ static void run_pager( wchar_t *prefix, int is_quoted, array_list_t *comp ) term_donate(); - io_data_t *out = exec_make_io_buffer(); + io_data_t *out = io_buffer_create(); eval( (wchar_t *)cmd.buff, out, TOP); term_steal(); - exec_read_io_buffer( out ); + io_buffer_read( out ); sb_destroy( &cmd ); @@ -1285,7 +1285,7 @@ static void run_pager( wchar_t *prefix, int is_quoted, array_list_t *comp ) free( str ); } - exec_free_io_buffer( out); + io_buffer_destroy( out); } -- cgit v1.2.3