Add support for buffering of input to a command, the first step to piping data to fish_pager instead of using the argument list

darcs-hash:20060813013803-ac50b-f8000d4c96162023411f84643f47221860b350b2.gz
This commit is contained in:
axel 2006-08-13 11:38:03 +10:00
parent 72ad4e0d3b
commit 0a4819be27
5 changed files with 106 additions and 25 deletions

View file

@ -540,7 +540,7 @@ static void event_fire_delayed()
free( blocked ); free( blocked );
blocked = new_blocked; blocked = new_blocked;
} }
while( sig_list[active_list].count > 0 ) while( sig_list[active_list].count > 0 )
{ {
signal_list_t *lst; signal_list_t *lst;

97
exec.c
View file

@ -676,11 +676,39 @@ void exec( job_t *j )
if( no_exec ) if( no_exec )
return; return;
sigemptyset( &chldset ); sigemptyset( &chldset );
sigaddset( &chldset, SIGCHLD ); sigaddset( &chldset, SIGCHLD );
debug( 4, L"Exec job '%ls' with id %d", j->command, j->job_id ); 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 ) if( j->first_process->type==INTERNAL_EXEC )
{ {
/* /*
@ -705,7 +733,7 @@ void exec( job_t *j )
j->first_process->completed=1; j->first_process->completed=1;
return; return;
} }
} }
pipe_read.fd=0; pipe_read.fd=0;
@ -718,20 +746,14 @@ void exec( job_t *j )
pipe_write.next=0; pipe_write.next=0;
pipe_write.param1.pipe_fd[0]=pipe_write.param1.pipe_fd[1]=-1; 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 ) //fwprintf( stderr, L"Run command %ls\n", j->command );
{
if( j->io )
j->io = io_add( io_duplicate( j, block_io), j->io );
else
j->io=io_duplicate( j, block_io);
}
j->io = io_add( j->io, &pipe_write ); j->io = io_add( j->io, &pipe_write );
signal_block(); signal_block();
/* /*
This loop loops over every process_t in the job, starting it as This loop loops over every process_t in the job, starting it as
appropriate. This turns out to be rather complex, since a 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. The loop also has to handle pipelining between the jobs.
*/ */
for( p=j->first_process; p; p = p->next ) for( p=j->first_process; p; p = p->next )
{ {
mypipe[1]=-1; mypipe[1]=-1;
skip_fork=0; skip_fork=0;
pipe_write.fd = p->pipe_fd; pipe_write.fd = p->pipe_fd;
/* /*
@ -813,7 +835,7 @@ void exec( job_t *j )
if( p->next ) if( p->next )
{ {
io_buffer = io_buffer_create(); io_buffer = io_buffer_create( 0 );
j->io = io_add( j->io, io_buffer ); j->io = io_add( j->io, io_buffer );
} }
@ -829,7 +851,7 @@ void exec( job_t *j )
{ {
if( p->next ) if( p->next )
{ {
io_buffer = io_buffer_create(); io_buffer = io_buffer_create( 0 );
j->io = io_add( j->io, io_buffer ); j->io = io_add( j->io, io_buffer );
} }
@ -837,7 +859,7 @@ void exec( job_t *j )
break; break;
} }
case INTERNAL_BUILTIN: case INTERNAL_BUILTIN:
{ {
int builtin_stdin=0; int builtin_stdin=0;
@ -947,6 +969,7 @@ void exec( job_t *j )
switch( p->type ) switch( p->type )
{ {
case INTERNAL_BLOCK: case INTERNAL_BLOCK:
case INTERNAL_FUNCTION: case INTERNAL_FUNCTION:
{ {
@ -1027,6 +1050,48 @@ void exec( job_t *j )
break; 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: case INTERNAL_BUILTIN:
{ {
@ -1224,7 +1289,7 @@ int exec_subshell( const wchar_t *cmd,
} }
is_subshell=1; is_subshell=1;
io_buffer= io_buffer_create(); io_buffer= io_buffer_create( 0 );
prev_status = proc_get_last_status(); prev_status = proc_get_last_status();

View file

@ -36,7 +36,7 @@ Implementation file for the low level input library
/** /**
Characters that have been read and returned by the sequence matching code 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 Number of entries in lookahead_arr

10
io.c
View file

@ -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 )); io_data_t *buffer_redirect = malloc( sizeof( io_data_t ));
buffer_redirect->io_mode=IO_BUFFER; buffer_redirect->io_mode=IO_BUFFER;
buffer_redirect->next=0; buffer_redirect->next=0;
buffer_redirect->param2.out_buffer= malloc( sizeof(buffer_t)); buffer_redirect->param2.out_buffer= malloc( sizeof(buffer_t));
buffer_redirect->param3.is_input = is_input;
b_init( buffer_redirect->param2.out_buffer ); 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 ) if( exec_pipe( buffer_redirect->param1.pipe_fd ) == -1 )
{ {
debug( 1, PIPE_ERROR ); debug( 1, PIPE_ERROR );
@ -229,8 +230,7 @@ void io_print( io_data_t *io )
return; return;
} }
debug( 1, L"IO fd %d, type ", debug( 1, L"IO fd %d, type ", io->fd );
io->fd );
switch( io->io_mode ) switch( io->io_mode )
{ {
case IO_PIPE: case IO_PIPE:

20
io.h
View file

@ -44,6 +44,17 @@ typedef struct io_data
} param2 } 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 */ /** Pointer to the next IO redirection */
struct io_data *next; 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 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. Close output pipe, and read from input pipe until eof.