22#include <zypp-core/base/DefaultIntegral> 
   33#undef  ZYPP_BASE_LOGGER_LOGGROUP 
   34#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::plugin" 
   42    const char * PLUGIN_DEBUG = getenv( 
"ZYPP_PLUGIN_DEBUG" );
 
   47    struct PluginDebugBuffer
 
   49      PluginDebugBuffer(
const std::string &buffer_r) : _buffer(buffer_r) {}
 
   50      PluginDebugBuffer(
const PluginDebugBuffer &) = 
delete;
 
   51      PluginDebugBuffer(PluginDebugBuffer &&) = 
delete;
 
   52      PluginDebugBuffer &operator=(
const PluginDebugBuffer &) = 
delete;
 
   53      PluginDebugBuffer &operator=(PluginDebugBuffer &&) = 
delete;
 
   58          if ( _buffer.empty() )
 
   60            L_DBG(
"PLUGIN") << 
"< (empty)" << endl;
 
   64            std::istringstream datas( _buffer );
 
   69      const std::string & _buffer;
 
   75    struct PluginDumpStderr
 
   77      PluginDumpStderr(ExternalProgramWithStderr &prog_r) : _prog(prog_r) {}
 
   78      PluginDumpStderr(
const PluginDumpStderr &) = 
delete;
 
   79      PluginDumpStderr(PluginDumpStderr &&) = 
delete;
 
   80      PluginDumpStderr &operator=(
const PluginDumpStderr &) = 
delete;
 
   81      PluginDumpStderr &operator=(PluginDumpStderr &&) = 
delete;
 
   85        while ( _prog.stderrGetline( line ) )
 
   86          L_WAR(
"PLUGIN") << 
"! " << line << endl;
 
   88      ExternalProgramWithStderr & _prog;
 
   91    inline void setBlocking( FILE * file_r, 
bool yesno_r = 
true )
 
   94        ZYPP_THROW( PluginScriptException( 
"setNonBlocking" ) );
 
   96      int fd = ::fileno( file_r );
 
   98        ZYPP_THROW( PluginScriptException( 
"setNonBlocking" ) );
 
  100      int flags = ::fcntl( fd, F_GETFL );
 
  102        ZYPP_THROW( PluginScriptException( 
"setNonBlocking" ) );
 
  106      else if ( flags & O_NONBLOCK )
 
  109      flags = ::fcntl( fd, F_SETFL, flags );
 
  111        ZYPP_THROW( PluginScriptException( 
"setNonBlocking" ) );
 
  114    inline void setNonBlocking( FILE * file_r, 
bool yesno_r = 
true )
 
  115    { setBlocking( file_r, !yesno_r ); }
 
  163      { 
return _cmd != 
nullptr; }
 
 
 
  200    const long PLUGIN_SEND_TIMEOUT =    
str::strtonum<long>( getenv( 
"ZYPP_PLUGIN_SEND_TIMEOUT" ) );
 
  201    const long PLUGIN_RECEIVE_TIMEOUT = 
str::strtonum<long>( getenv( 
"ZYPP_PLUGIN_RECEIVE_TIMEOUT" ) );
 
  205                                                                                 : ( PLUGIN_TIMEOUT > 0 ? PLUGIN_TIMEOUT : 30 ) );
 
  207                                                                                 : ( PLUGIN_TIMEOUT > 0 ? PLUGIN_TIMEOUT : 30 ) );
 
  213    dumpRangeLine( 
DBG << 
"Open " << script_r, args_r.begin(), args_r.end() ) << endl;
 
  227    args.reserve( args_r.size()+1 );
 
  229    args.insert( 
args.end(), args_r.begin(), args_r.end() );
 
  233    setNonBlocking( 
_cmd->outputFile() );
 
  234    setNonBlocking( 
_cmd->inputFile() );
 
 
  249      DBG << 
"Close:" << *
this << endl;
 
 
  282    if ( frame_r.
command().empty() )
 
  283      WAR << 
"Send: No command in frame" << frame_r << endl;
 
  288      std::ostringstream datas;
 
  290      datas.str().swap( data );
 
  292    DBG << *
this << 
" ->send " << frame_r << endl;
 
  296      std::istringstream datas( data );
 
  301    FILE * filep = 
_cmd->outputFile();
 
  305    int fd = ::fileno( filep );
 
  311      PluginDumpStderr _dump( *
_cmd ); 
 
  313      const char * buffer = data.c_str();
 
  314      ssize_t buffsize = data.size();
 
  318        watchFd.events =  G_IO_OUT | G_IO_ERR;
 
  322        int retval = g_poll( &watchFd, 1, 
_sendTimeout * 1000 );
 
  326          ssize_t ret = ::write( fd, buffer, buffsize );
 
  327          if ( ret == buffsize )
 
  342            if ( errno != EINTR )
 
  344              ERR << 
"write(): " << 
Errno() << endl;
 
  345              if ( errno == EPIPE )
 
  352        else if ( retval == 0 )
 
  354          WAR << 
"Not ready to write within timeout." << endl;
 
  355          ZYPP_THROW( PluginScriptSendTimeout( 
"Not ready to write within timeout." ) );
 
  359          if ( errno != EINTR )
 
  361            ERR << 
"select(): " << 
Errno() << endl;
 
 
  375    FILE * filep = 
_cmd->inputFile();
 
  379    int fd = ::fileno( filep );
 
  386      PluginDebugBuffer _debug( data ); 
 
  387      PluginDumpStderr _dump( *
_cmd ); 
 
  389        int ch = fgetc( filep );
 
  392          data.push_back( ch );
 
  396        else if ( ::feof( filep ) )
 
  398          WAR << 
"Unexpected EOF" << endl;
 
  401        else if ( errno != EINTR )
 
  403          if ( errno == EWOULDBLOCK )
 
  408            rfd.events =  G_IO_IN | G_IO_HUP | G_IO_ERR;
 
  416            else if ( retval == 0 )
 
  418              WAR << 
"Not ready to read within timeout." << endl;
 
  419              ZYPP_THROW( PluginScriptReceiveTimeout( 
"Not ready to read within timeout." ) );
 
  423              if ( errno != EINTR )
 
  425                ERR << 
"select(): " << 
Errno() << endl;
 
  432            ERR << 
"read(): " << 
Errno() << endl;
 
  439    std::istringstream datas( data );
 
  441    DBG << *
this << 
" <-" << ret << endl;
 
 
  466  { 
return _pimpl->_sendTimeout; }
 
 
  469  { 
return _pimpl->_receiveTimeout; }
 
 
  472  { 
_pimpl->_sendTimeout = newval_r > 0 ? newval_r : 0; }
 
 
  475  { 
_pimpl->_receiveTimeout = newval_r > 0 ? newval_r : 0; }
 
 
  490  { 
return _pimpl->script(); }
 
 
  493  { 
return _pimpl->args(); }
 
 
  496  { 
return _pimpl->isOpen(); }
 
 
  499  { 
return _pimpl->getPid(); }
 
 
  502  { 
return _pimpl->lastReturn(); }
 
 
  505  { 
return _pimpl->lastExecError(); }
 
 
  511  { 
_pimpl->open( script_r ); }
 
 
  514  { 
_pimpl->open( script_r, args_r ); }
 
 
  517  { 
return _pimpl->close(); }
 
 
  520  { 
_pimpl->send( frame_r ); }
 
 
  523  { 
return _pimpl->receive(); }
 
 
std::string asString() const
Integral type with defined initial value when default constructed.
Convenience errno wrapper.
ExternalProgram extended to offer reading programs stderr.
Command frame for communication with PluginScript.
const ByteArray & body() const
Return the frame body.
const std::string & command() const
Return the frame command.
const std::string & getHeaderNT(const std::string &key_r, const std::string &default_r=std::string()) const
Not throwing version returing one of the matching header values or default_r string.
bool isAckCommand() const
Convenience to identify an ACK command.
std::ostream & writeTo(std::ostream &stream_r) const
Write frame to stream.
Base class for PluginScript Exception.
PluginFrame receive() const
Receive a PluginFrame.
std::vector< std::string > Arguments
Commandline arguments passed to a script on open.
long sendTimeout() const
Local default timeout (sec.) when sending data.
void send(const PluginFrame &frame_r) const
Send a PluginFrame.
PluginScript()
Default ctor.
RW_pointer< Impl > _pimpl
Pointer to implementation.
int lastReturn() const
Remembers a scripts return value after close until next open.
static long defaultReceiveTimeout()
Global default timeout (sec.) when receiving data.
static const pid_t NotConnected
pid_t(-1) constant indicating no connection.
int close()
Close any open connection.
const std::string & lastExecError() const
Remembers a scripts execError string after close until next open.
pid_t getPid() const
Return a connected scripts pid or NotConnected.
void open()
Setup connection and execute script.
const Pathname & script() const
Return the script path if set.
static long defaultSendTimeout()
Global default timeout (sec.) when sending data.
bool isOpen() const
Whether we are connected to a script.
long receiveTimeout() const
Local default timeout (sec.) when receiving data.
const Arguments & args() const
Return the script arguments if set.
Exception safe signal handler save/restore.
Wrapper class for stat/lstat.
const std::string & asString() const
String representation.
String related utilities and Regular expression matching.
std::ostream & copyIndent(std::istream &from_r, std::ostream &to_r, const std::string &indent_r="> ")
Copy istream to ostream, prefixing each line with indent_r (default "> " ).
TInt strtonum(const C_Str &str)
Parsing numbers from string.
Easy-to use interface to the ZYPP dependency resolver.
std::ostream & dumpRangeLine(std::ostream &str, TIterator begin, TIterator end)
Print range defined by iterators (single line style).
std::ostream & operator<<(std::ostream &str, const SerialNumber &obj)
PluginScript implementation.
PluginFrame receive() const
std::string _lastExecError
static long _defaultSendTimeout
Impl(const Impl &)=delete
DefaultIntegral< int, 0 > _lastReturn
Impl & operator=(const Impl &)=delete
const Pathname & script() const
scoped_ptr< ExternalProgramWithStderr > _cmd
void open(const Pathname &script_r=Pathname(), const Arguments &args_r=Arguments())
void send(const PluginFrame &frame_r) const
Impl & operator=(Impl &&)=delete
static long _defaultReceiveTimeout
const std::string & lastExecError() const
Impl(Pathname &&script_r=Pathname(), Arguments &&args_r=Arguments())
const Arguments & args() const
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.