diff --git a/event.c b/event.c index ef1e464b7..2df1e79d7 100644 --- a/event.c +++ b/event.c @@ -540,7 +540,7 @@ static void event_fire_delayed() free( blocked ); blocked = new_blocked; } - + while( sig_list[active_list].count > 0 ) { signal_list_t *lst; diff --git a/exec.c b/exec.c index a3d77d62d..eac0e11ce 100644 --- a/exec.c +++ b/exec.c @@ -676,11 +676,39 @@ void exec( job_t *j ) if( no_exec ) return; + + sigemptyset( &chldset ); sigaddset( &chldset, SIGCHLD ); debug( 4, L"Exec job '%ls' with id %d", j->command, j->job_id ); + if( block_io ) + { + if( j->io ) + j->io = io_add( io_duplicate( j, block_io), j->io ); + else + j->io=io_duplicate( j, block_io); + } + + io_data_t *input_redirect = io_get( j->io, 0 ); + + if( input_redirect && + (input_redirect->io_mode == IO_BUFFER) && + input_redirect->param3.is_input ) + { + /* + Input redirection - create a new gobetween process to take + care of buffering + */ + + process_t *fake = halloc( j, sizeof(process_t) ); + fake->type = INTERNAL_BUFFER; + fake->pipe_fd = 1; + fake->next = j->first_process; + j->first_process = fake; + } + if( j->first_process->type==INTERNAL_EXEC ) { /* @@ -705,7 +733,7 @@ void exec( job_t *j ) j->first_process->completed=1; return; } - + } pipe_read.fd=0; @@ -718,20 +746,14 @@ void exec( job_t *j ) pipe_write.next=0; pipe_write.param1.pipe_fd[0]=pipe_write.param1.pipe_fd[1]=-1; - //fwprintf( stderr, L"Run command %ls\n", j->command ); + - if( block_io ) - { - if( j->io ) - j->io = io_add( io_duplicate( j, block_io), j->io ); - else - j->io=io_duplicate( j, block_io); - } + //fwprintf( stderr, L"Run command %ls\n", j->command ); j->io = io_add( j->io, &pipe_write ); signal_block(); - + /* This loop loops over every process_t in the job, starting it as appropriate. This turns out to be rather complex, since a @@ -739,12 +761,12 @@ void exec( job_t *j ) The loop also has to handle pipelining between the jobs. */ - + for( p=j->first_process; p; p = p->next ) { mypipe[1]=-1; skip_fork=0; - + pipe_write.fd = p->pipe_fd; /* @@ -813,7 +835,7 @@ void exec( job_t *j ) if( p->next ) { - io_buffer = io_buffer_create(); + io_buffer = io_buffer_create( 0 ); j->io = io_add( j->io, io_buffer ); } @@ -829,7 +851,7 @@ void exec( job_t *j ) { if( p->next ) { - io_buffer = io_buffer_create(); + io_buffer = io_buffer_create( 0 ); j->io = io_add( j->io, io_buffer ); } @@ -837,7 +859,7 @@ void exec( job_t *j ) break; } - + case INTERNAL_BUILTIN: { int builtin_stdin=0; @@ -947,6 +969,7 @@ void exec( job_t *j ) switch( p->type ) { + case INTERNAL_BLOCK: case INTERNAL_FUNCTION: { @@ -1027,6 +1050,48 @@ void exec( job_t *j ) break; } + + + case INTERNAL_BUFFER: + { + + debug( 0, L"fork internal buffer" ); + + pid = fork(); + + if( pid == 0 ) + { + /* + This is the child process. Write out the contents of the pipeline. + */ + p->pid = getpid(); + setup_child_process( j, p ); + + write( 1, + input_redirect->param2.out_buffer->buff, + input_redirect->param2.out_buffer->used ); + exit( 0 ); + } + else if( pid < 0 ) + { + /* The fork failed. */ + debug( 0, FORK_ERROR ); + wperror (L"fork"); + exit (1); + } + else + { + /* + This is the parent process. Store away + information on the child, and possibly give + it control over the terminal. + */ + p->pid = pid; + set_child_group( j, p, 0 ); + } + + break; + } case INTERNAL_BUILTIN: { @@ -1224,7 +1289,7 @@ int exec_subshell( const wchar_t *cmd, } is_subshell=1; - io_buffer= io_buffer_create(); + io_buffer= io_buffer_create( 0 ); prev_status = proc_get_last_status(); diff --git a/input_common.c b/input_common.c index ebc4b9eca..c06ac4277 100644 --- a/input_common.c +++ b/input_common.c @@ -36,7 +36,7 @@ Implementation file for the low level input library /** Characters that have been read and returned by the sequence matching code */ -static wint_t lookahead_arr[32]; +static wint_t lookahead_arr[1024]; /** Number of entries in lookahead_arr diff --git a/io.c b/io.c index d907a1725..e5afa06b4 100644 --- a/io.c +++ b/io.c @@ -101,16 +101,17 @@ void io_buffer_read( io_data_t *d ) } -io_data_t *io_buffer_create() +io_data_t *io_buffer_create( int is_input ) { io_data_t *buffer_redirect = malloc( sizeof( io_data_t )); buffer_redirect->io_mode=IO_BUFFER; buffer_redirect->next=0; buffer_redirect->param2.out_buffer= malloc( sizeof(buffer_t)); + buffer_redirect->param3.is_input = is_input; b_init( buffer_redirect->param2.out_buffer ); - buffer_redirect->fd=1; - + buffer_redirect->fd=is_input?0:1; + if( exec_pipe( buffer_redirect->param1.pipe_fd ) == -1 ) { debug( 1, PIPE_ERROR ); @@ -229,8 +230,7 @@ void io_print( io_data_t *io ) return; } - debug( 1, L"IO fd %d, type ", - io->fd ); + debug( 1, L"IO fd %d, type ", io->fd ); switch( io->io_mode ) { case IO_PIPE: diff --git a/io.h b/io.h index bba953170..38b87e3d9 100644 --- a/io.h +++ b/io.h @@ -44,6 +44,17 @@ typedef struct io_data } param2 ; + + union + { + /** + This will be non-zero if this is a buffer of input, not + output + */ + int is_input; + } + param3; + /** Pointer to the next IO redirection */ struct io_data *next; @@ -80,9 +91,14 @@ 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. + buffer_t for output. The default file descriptor used is 1 for + output buffering and 0 for input buffering. + + \param is_input set this parameter to zero if the buffer should be + used to buffer the output of a command, or non-zero to buffer the + input to a command. */ -io_data_t *io_buffer_create(); +io_data_t *io_buffer_create( int is_input ); /** Close output pipe, and read from input pipe until eof.