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 bool active() {
00039 return fd != -1 && !_eof;
00040 }
00041
00042 bool eof() {
00043 return _eof;
00044 }
00045
00046 int readMore() {
00047 char _buffer[1024];
00048 int r = ::read( fd, _buffer, 1023 );
00049 if ( r == -1 && errno != EAGAIN )
00050 throw wexcept::System( "reading from pipe" );
00051 else if ( r == -1 )
00052 return 0;
00053 if ( r == 0 )
00054 _eof = true;
00055 else
00056 std::copy( _buffer, _buffer + r, std::back_inserter( buffer ) );
00057 return r;
00058 }
00059
00060 std::string nextLine() {
00061 Buffer::iterator nl =
00062 std::find( buffer.begin(), buffer.end(), '\n' );
00063 while ( nl == buffer.end() && readMore() );
00064 nl = std::find( buffer.begin(), buffer.end(), '\n' );
00065 if ( nl == buffer.end() )
00066 return "";
00067
00068 std::string line( buffer.begin(), nl );
00069 ++ nl;
00070 buffer.erase( buffer.begin(), nl );
00071 return line;
00072 }
00073
00074 std::string nextLineBlocking() {
00075 fd_set fds;
00076 FD_ZERO( &fds );
00077 std::string l;
00078 while ( !eof() ) {
00079 l = nextLine();
00080 if ( !l.empty() )
00081 return l;
00082 FD_SET( fd, &fds );
00083 select( fd + 1, &fds, 0, 0, 0 );
00084 }
00085 return l;
00086 }
00087
00088 };
00089
00090 }
00091 }
00092
00093 #endif