mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-27 05:13:10 +00:00
Move io redirection functions to their own library
darcs-hash:20051008112051-ac50b-113caa4cba470a739e4bfbed9f479e2fed357be7.gz
This commit is contained in:
parent
93eed7bc35
commit
9ae7fa5831
9 changed files with 347 additions and 299 deletions
|
@ -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 \
|
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 \
|
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 \
|
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
|
# builtin_help.h exists, but builtin_help.c is autogenerated
|
||||||
COMMON_OBJS_WITH_HEADER := builtin_help.o
|
COMMON_OBJS_WITH_HEADER := builtin_help.o
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "intern.h"
|
#include "intern.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
|
#include "signal.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The default prompt for the read command
|
The default prompt for the read command
|
||||||
|
@ -2500,8 +2501,6 @@ static int builtin_end( wchar_t **argv )
|
||||||
|
|
||||||
case FUNCTION_DEF:
|
case FUNCTION_DEF:
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Copy the text from the beginning of the function
|
Copy the text from the beginning of the function
|
||||||
until the end command and use as the new definition
|
until the end command and use as the new definition
|
||||||
|
|
172
exec.c
172
exec.c
|
@ -34,6 +34,7 @@
|
||||||
#include "wildcard.h"
|
#include "wildcard.h"
|
||||||
#include "sanity.h"
|
#include "sanity.h"
|
||||||
#include "expand.h"
|
#include "expand.h"
|
||||||
|
#include "signal.h"
|
||||||
#include "env_universal.h"
|
#include "env_universal.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,10 +53,6 @@ pid_t getpgid( pid_t pid );
|
||||||
file redirection error message
|
file redirection error message
|
||||||
*/
|
*/
|
||||||
#define FILE_ERROR L"An error occurred while redirecting file '%ls'"
|
#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
|
fork error message
|
||||||
*/
|
*/
|
||||||
|
@ -68,11 +65,7 @@ pid_t getpgid( pid_t pid );
|
||||||
*/
|
*/
|
||||||
array_list_t *open_fds=0;
|
array_list_t *open_fds=0;
|
||||||
|
|
||||||
/**
|
void exec_close( int fd )
|
||||||
Loops over close until thesyscall was run without beeing
|
|
||||||
interrupted. Thenremoves the fd from the open_fds list.
|
|
||||||
*/
|
|
||||||
static void close_loop( int fd )
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -105,13 +98,19 @@ static void close_loop( int fd )
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
int exec_pipe( int fd[2])
|
||||||
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 res = pipe( fd );
|
int res;
|
||||||
|
|
||||||
|
while( ( res=pipe( fd ) ) )
|
||||||
|
{
|
||||||
|
if( errno != EINTR )
|
||||||
|
{
|
||||||
|
wperror(L"pipe");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if( open_fds == 0 )
|
if( open_fds == 0 )
|
||||||
{
|
{
|
||||||
open_fds = malloc( sizeof( array_list_t ) );
|
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) )
|
if( !use_fd_in_pipe( n, io) )
|
||||||
{
|
{
|
||||||
debug( 4, L"Close fd %d, used in other context", n );
|
debug( 4, L"Close fd %d, used in other context", n );
|
||||||
close_loop( n );
|
exec_close( n );
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -237,7 +236,7 @@ static void handle_child_io( io_data_t *io )
|
||||||
close_unused_internal_pipes( io );
|
close_unused_internal_pipes( io );
|
||||||
|
|
||||||
if( env_universal_server.fd >= 0 )
|
if( env_universal_server.fd >= 0 )
|
||||||
close_loop( env_universal_server.fd );
|
exec_close( env_universal_server.fd );
|
||||||
|
|
||||||
for( ; io; io=io->next )
|
for( ; io; io=io->next )
|
||||||
{
|
{
|
||||||
|
@ -296,7 +295,7 @@ static void handle_child_io( io_data_t *io )
|
||||||
wperror( L"dup2" );
|
wperror( L"dup2" );
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
close_loop( tmp );
|
exec_close( tmp );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IO_FD:
|
case IO_FD:
|
||||||
|
@ -337,11 +336,11 @@ static void handle_child_io( io_data_t *io )
|
||||||
|
|
||||||
if( fd_to_dup != 0 )
|
if( fd_to_dup != 0 )
|
||||||
{
|
{
|
||||||
close_loop( io->pipe_fd[0]);
|
exec_close( io->pipe_fd[0]);
|
||||||
close_loop( io->pipe_fd[1]);
|
exec_close( io->pipe_fd[1]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
close_loop( io->pipe_fd[0] );
|
exec_close( io->pipe_fd[0] );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if( close( io[i].pipe_fd[ io->fd ] ) == -1 )
|
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.
|
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 )
|
switch( in->io_mode )
|
||||||
{
|
{
|
||||||
case IO_FILE:
|
case IO_FILE:
|
||||||
close_loop( out->old_fd );
|
exec_close( out->old_fd );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
free(out);
|
free(out);
|
||||||
|
@ -846,7 +742,7 @@ void exec( job_t *j )
|
||||||
|
|
||||||
if (p->next)
|
if (p->next)
|
||||||
{
|
{
|
||||||
if (internal_pipe( mypipe ) == -1)
|
if (exec_pipe( mypipe ) == -1)
|
||||||
{
|
{
|
||||||
debug( 1, PIPE_ERROR );
|
debug( 1, PIPE_ERROR );
|
||||||
wperror (L"pipe");
|
wperror (L"pipe");
|
||||||
|
@ -911,7 +807,7 @@ void exec( job_t *j )
|
||||||
if( p->next )
|
if( p->next )
|
||||||
{
|
{
|
||||||
// fwprintf( stderr, L"Function %ls\n", def );
|
// 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 );
|
j->io = io_add( j->io, io_buffer );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -928,7 +824,7 @@ void exec( job_t *j )
|
||||||
if( p->next )
|
if( p->next )
|
||||||
{
|
{
|
||||||
// fwprintf( stderr, L"Block %ls\n", p->argv[0] );
|
// 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 );
|
j->io = io_add( j->io, io_buffer );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1034,7 +930,7 @@ void exec( job_t *j )
|
||||||
if( close_stdin )
|
if( close_stdin )
|
||||||
{
|
{
|
||||||
// fwprintf( stderr, L"Close builtin_stdin\n" );
|
// fwprintf( stderr, L"Close builtin_stdin\n" );
|
||||||
close_loop( builtin_stdin );
|
exec_close( builtin_stdin );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1062,9 +958,7 @@ void exec( job_t *j )
|
||||||
|
|
||||||
j->io = io_remove( j->io, io_buffer );
|
j->io = io_remove( j->io, io_buffer );
|
||||||
|
|
||||||
debug( 3, L"exec_read_io_buffer on block '%ls'", p->argv[0] );
|
io_buffer_read( io_buffer );
|
||||||
|
|
||||||
exec_read_io_buffer( io_buffer );
|
|
||||||
|
|
||||||
if( io_buffer->out_buffer->used != 0 )
|
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;
|
io_buffer=0;
|
||||||
break;
|
break;
|
||||||
|
@ -1256,7 +1150,7 @@ void exec( job_t *j )
|
||||||
Close the pipe the current process uses to read from the previous process_t
|
Close the pipe the current process uses to read from the previous process_t
|
||||||
*/
|
*/
|
||||||
if( pipe_read.pipe_fd[0] >= 0 )
|
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
|
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 )
|
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;
|
is_subshell=1;
|
||||||
io_buffer= exec_make_io_buffer();
|
io_buffer= io_buffer_create();
|
||||||
|
|
||||||
prev_status = proc_get_last_status();
|
prev_status = proc_get_last_status();
|
||||||
|
|
||||||
eval( cmd, io_buffer, SUBST );
|
eval( cmd, io_buffer, SUBST );
|
||||||
|
|
||||||
debug( 4, L"exec_read_io_buffer on cmdsub '%ls'", cmd );
|
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();
|
status = proc_get_last_status();
|
||||||
proc_set_last_status( prev_status );
|
proc_set_last_status( prev_status );
|
||||||
|
@ -1341,7 +1235,7 @@ int exec_subshell( const wchar_t *cmd,
|
||||||
if( el )
|
if( el )
|
||||||
al_push( l, el );
|
al_push( l, el );
|
||||||
}
|
}
|
||||||
exec_free_io_buffer( io_buffer );
|
io_buffer_destroy( io_buffer );
|
||||||
|
|
||||||
return status;
|
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;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
19
exec.h
19
exec.h
|
@ -10,6 +10,11 @@
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
pipe redirection error message
|
||||||
|
*/
|
||||||
|
#define PIPE_ERROR L"An error occurred while setting up pipe"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Initialize the exec library
|
Initialize the exec library
|
||||||
*/
|
*/
|
||||||
|
@ -57,19 +62,17 @@ void exec( job_t *j );
|
||||||
int exec_subshell( const wchar_t *cmd,
|
int exec_subshell( const wchar_t *cmd,
|
||||||
array_list_t *l );
|
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
|
#endif
|
||||||
|
|
209
io.c
Normal file
209
io.c
Normal file
|
@ -0,0 +1,209 @@
|
||||||
|
/** \file io.c
|
||||||
|
|
||||||
|
Utilities for io redirection.
|
||||||
|
|
||||||
|
*/
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#if HAVE_NCURSES_H
|
||||||
|
#include <ncurses.h>
|
||||||
|
#else
|
||||||
|
#include <curses.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_TERMIO_H
|
||||||
|
#include <termio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <term.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
87
io.h
Normal file
87
io.h
Normal file
|
@ -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
|
81
proc.c
81
proc.c
|
@ -74,77 +74,6 @@ int is_event=0;
|
||||||
int proc_had_barrier;
|
int proc_had_barrier;
|
||||||
pid_t proc_last_bg_pid = 0;
|
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
|
Recursively free a process and those following it
|
||||||
|
@ -368,7 +297,6 @@ static void mark_process_status( job_t *j,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
p->completed = 1;
|
p->completed = 1;
|
||||||
// fwprintf( stderr, L"Proc %d (%ls) exited\n", p->pid, p->actual_cmd );
|
|
||||||
|
|
||||||
if (( !WIFEXITED( status ) ) &&
|
if (( !WIFEXITED( status ) ) &&
|
||||||
(! WIFSIGNALED( status )) )
|
(! WIFSIGNALED( status )) )
|
||||||
|
@ -743,15 +671,6 @@ static int select_try( job_t *j )
|
||||||
int maxfd=-1;
|
int maxfd=-1;
|
||||||
io_data_t *d;
|
io_data_t *d;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* if( j->stop_reading )
|
|
||||||
{
|
|
||||||
sleep(1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
|
|
||||||
for( d = j->io; d; d=d->next )
|
for( d = j->io; d; d=d->next )
|
||||||
|
|
67
proc.h
67
proc.h
|
@ -16,15 +16,8 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "util.h"
|
#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
|
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.
|
tracking process state and the process argument list.
|
||||||
*/
|
*/
|
||||||
typedef struct process{
|
typedef struct process{
|
||||||
|
@ -177,26 +134,6 @@ extern int proc_had_barrier;
|
||||||
|
|
||||||
extern pid_t proc_last_bg_pid;
|
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
|
Sets the status of the last process to exit
|
||||||
*/
|
*/
|
||||||
|
|
6
reader.c
6
reader.c
|
@ -1260,12 +1260,12 @@ static void run_pager( wchar_t *prefix, int is_quoted, array_list_t *comp )
|
||||||
|
|
||||||
term_donate();
|
term_donate();
|
||||||
|
|
||||||
io_data_t *out = exec_make_io_buffer();
|
io_data_t *out = io_buffer_create();
|
||||||
|
|
||||||
eval( (wchar_t *)cmd.buff, out, TOP);
|
eval( (wchar_t *)cmd.buff, out, TOP);
|
||||||
term_steal();
|
term_steal();
|
||||||
|
|
||||||
exec_read_io_buffer( out );
|
io_buffer_read( out );
|
||||||
|
|
||||||
sb_destroy( &cmd );
|
sb_destroy( &cmd );
|
||||||
|
|
||||||
|
@ -1285,7 +1285,7 @@ static void run_pager( wchar_t *prefix, int is_quoted, array_list_t *comp )
|
||||||
free( str );
|
free( str );
|
||||||
}
|
}
|
||||||
|
|
||||||
exec_free_io_buffer( out);
|
io_buffer_destroy( out);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue