00001
00002
00003 #include <fcntl.h>
00004 #include <sys/select.h>
00005
00006 #include <deque>
00007 #include <cerrno>
00008
00009 #include <wibble/exception.h>
00010
00011 #ifndef WIBBLE_SYS_PIPE_H
00012 #define WIBBLE_SYS_PIPE_H
00013
00014 namespace wibble {
00015 namespace sys {
00016
00017 namespace wexcept = wibble::exception;
00018
00019 struct Pipe {
00020 typedef std::deque< char > Buffer;
00021 Buffer buffer;
00022 int fd;
00023 bool _eof;
00024
00025 Pipe( int p ) : fd( p ), _eof( false )
00026 {
00027 if ( p == -1 )
00028 return;
00029 if ( fcntl( fd, F_SETFL, O_NONBLOCK ) == -1 )
00030 throw wexcept::System( "fcntl on a pipe" );
00031 }
00032 Pipe() : fd( -1 ), _eof( false ) {}
00033
00034 void write( std::string what ) {
00035 ::write( fd, what.c_str(), what.length() );
00036 }
00037
00038 void close() {
00039 ::close( fd );
00040 }
00041
00042 bool active() {
00043 return fd != -1 && !_eof;
00044 }
00045
00046 bool eof() {
00047 return _eof;
00048 }
00049
00050 int readMore() {
00051 char _buffer[1024];
00052 int r = ::read( fd, _buffer, 1023 );
00053 if ( r == -1 && errno != EAGAIN )
00054 throw wexcept::System( "reading from pipe" );
00055 else if ( r == -1 )
00056 return 0;
00057 if ( r == 0 )
00058 _eof = true;
00059 else
00060 std::copy( _buffer, _buffer + r, std::back_inserter( buffer ) );
00061 return r;
00062 }
00063
00064 std::string nextLine() {
00065 Buffer::iterator nl =
00066 std::find( buffer.begin(), buffer.end(), '\n' );
00067 while ( nl == buffer.end() && readMore() );
00068 nl = std::find( buffer.begin(), buffer.end(), '\n' );
00069 if ( nl == buffer.end() )
00070 return "";
00071
00072 std::string line( buffer.begin(), nl );
00073 ++ nl;
00074 buffer.erase( buffer.begin(), nl );
00075 return line;
00076 }
00077
00078 std::string nextLineBlocking() {
00079 fd_set fds;
00080 FD_ZERO( &fds );
00081 std::string l;
00082 while ( !eof() ) {
00083 l = nextLine();
00084 if ( !l.empty() )
00085 return l;
00086 FD_SET( fd, &fds );
00087 select( fd + 1, &fds, 0, 0, 0 );
00088 }
00089 return l;
00090 }
00091
00092 };
00093
00094 }
00095 }
00096
00097 #endif