2005-10-08 21:20:51 +10:00
/** \file io.c
Utilities for io redirection .
*/
# include "config.h"
2006-02-28 23:17:16 +10:00
2005-10-08 21:20:51 +10:00
# include <stdlib.h>
# include <stdio.h>
# include <wchar.h>
# include <string.h>
# include <errno.h>
# include <sys/types.h>
2006-08-10 08:53:38 +10:00
# ifdef HAVE_SYS_TERMIOS_H
# include <sys/termios.h>
# endif
# ifdef HAVE_SYS_IOCTL_H
2005-10-08 21:20:51 +10:00
# include <sys/ioctl.h>
2006-08-10 08:53:38 +10:00
# endif
2005-10-08 21:20:51 +10:00
# 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
2006-01-19 22:22:07 +10:00
# if HAVE_TERM_H
2005-10-08 21:20:51 +10:00
# include <term.h>
2006-01-19 22:22:07 +10:00
# elif HAVE_NCURSES_TERM_H
# include <ncurses/term.h>
# endif
2005-10-08 21:20:51 +10:00
2006-02-28 23:17:16 +10:00
# include "fallback.h"
2005-10-08 21:20:51 +10:00
# include "util.h"
2006-02-28 23:17:16 +10:00
2005-10-08 21:20:51 +10:00
# include "wutil.h"
# include "exec.h"
# include "common.h"
# include "io.h"
2006-07-20 08:55:49 +10:00
2006-02-07 01:18:17 +10:00
# include "halloc.h"
2005-10-08 21:20:51 +10:00
void io_buffer_read ( io_data_t * d )
{
2005-10-12 05:31:16 +10:00
exec_close ( d - > param1 . pipe_fd [ 1 ] ) ;
2005-10-08 21:20:51 +10:00
if ( d - > io_mode = = IO_BUFFER )
{
2005-12-12 08:27:30 +10:00
/* if( fcntl( d->param1.pipe_fd[0], F_SETFL, 0 ) )
2005-10-08 21:20:51 +10:00
{
wperror ( L " fcntl " ) ;
return ;
2005-12-12 08:27:30 +10:00
} */
debug ( 4 , L " io_buffer_read: blocking read on fd %d " , d - > param1 . pipe_fd [ 0 ] ) ;
2005-10-08 21:20:51 +10:00
while ( 1 )
{
char b [ 4096 ] ;
int l ;
2005-10-12 05:31:16 +10:00
l = read_blocked ( d - > param1 . pipe_fd [ 0 ] , b , 4096 ) ;
2005-10-08 21:20:51 +10:00
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 ,
2006-01-12 00:17:35 +10:00
_ ( L " An error occured while reading output from code block on file descriptor %d " ) ,
2005-10-12 05:31:16 +10:00
d - > param1 . pipe_fd [ 0 ] ) ;
2005-12-12 08:27:30 +10:00
wperror ( L " io_buffer_read " ) ;
2005-10-08 21:20:51 +10:00
}
break ;
}
else
{
2005-10-12 05:31:16 +10:00
b_append ( d - > param2 . out_buffer , b , l ) ;
2005-10-08 21:20:51 +10:00
}
}
}
}
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 ;
2005-10-12 05:31:16 +10:00
buffer_redirect - > param2 . out_buffer = malloc ( sizeof ( buffer_t ) ) ;
b_init ( buffer_redirect - > param2 . out_buffer ) ;
2005-10-08 21:20:51 +10:00
buffer_redirect - > fd = 1 ;
2005-10-12 05:31:16 +10:00
if ( exec_pipe ( buffer_redirect - > param1 . pipe_fd ) = = - 1 )
2005-10-08 21:20:51 +10:00
{
debug ( 1 , PIPE_ERROR ) ;
wperror ( L " pipe " ) ;
2005-10-12 05:31:16 +10:00
free ( buffer_redirect - > param2 . out_buffer ) ;
2005-10-08 21:20:51 +10:00
free ( buffer_redirect ) ;
return 0 ;
}
2005-10-12 05:31:16 +10:00
else if ( fcntl ( buffer_redirect - > param1 . pipe_fd [ 0 ] ,
2005-10-08 21:20:51 +10:00
F_SETFL ,
O_NONBLOCK ) )
{
debug ( 1 , PIPE_ERROR ) ;
wperror ( L " fcntl " ) ;
2005-10-12 05:31:16 +10:00
free ( buffer_redirect - > param2 . out_buffer ) ;
2005-10-08 21:20:51 +10:00
free ( buffer_redirect ) ;
return 0 ;
}
return buffer_redirect ;
}
void io_buffer_destroy ( io_data_t * io_buffer )
{
2005-10-12 05:31:16 +10:00
exec_close ( io_buffer - > param1 . pipe_fd [ 0 ] ) ;
2005-10-08 21:20:51 +10:00
/*
Dont free fd for writing . This should already be free ' d before
calling exec_read_io_buffer on the buffer
*/
2005-10-12 05:31:16 +10:00
b_destroy ( io_buffer - > param2 . out_buffer ) ;
2005-10-08 21:20:51 +10:00
2005-10-12 05:31:16 +10:00
free ( io_buffer - > param2 . out_buffer ) ;
2005-10-08 21:20:51 +10:00
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 ;
}
2006-02-07 00:25:02 +10:00
io_data_t * io_duplicate ( void * context , io_data_t * l )
2005-10-08 21:20:51 +10:00
{
io_data_t * res ;
if ( l = = 0 )
return 0 ;
2006-02-07 00:25:02 +10:00
res = halloc ( context , sizeof ( io_data_t ) ) ;
2005-10-08 21:20:51 +10:00
if ( ! res )
{
2006-07-03 20:39:57 +10:00
DIE_MEM ( ) ;
2005-10-08 21:20:51 +10:00
}
memcpy ( res , l , sizeof ( io_data_t ) ) ;
2006-02-07 00:25:02 +10:00
res - > next = io_duplicate ( context , l - > next ) ;
2005-10-08 21:20:51 +10:00
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 ;
}
2006-05-15 08:29:05 +10:00
void io_print ( io_data_t * io )
2005-10-09 21:48:16 +10:00
{
if ( ! io )
{
return ;
}
2006-05-15 08:29:05 +10:00
debug ( 1 , L " IO fd %d, type " ,
2005-10-09 21:48:16 +10:00
io - > fd ) ;
switch ( io - > io_mode )
{
case IO_PIPE :
2006-05-15 08:29:05 +10:00
debug ( 1 , L " PIPE, data %d " , io - > param1 . pipe_fd [ io - > fd ? 1 : 0 ] ) ;
2005-10-09 21:48:16 +10:00
break ;
case IO_FD :
2006-05-15 08:29:05 +10:00
debug ( 1 , L " FD, copy %d " , io - > param1 . old_fd ) ;
2005-10-09 21:48:16 +10:00
break ;
case IO_BUFFER :
2006-05-15 08:29:05 +10:00
debug ( 1 , L " BUFFER " ) ;
2005-10-09 21:48:16 +10:00
break ;
default :
2006-05-15 08:29:05 +10:00
debug ( 1 , L " OTHER " ) ;
2005-10-09 21:48:16 +10:00
}
io_print ( io - > next ) ;
}