Go to the documentation of this file.
12 #include <sys/types.h>
30 #undef ZYPP_BASE_LOGGER_LOGGROUP
31 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::plugin"
39 const char * PLUGIN_DEBUG = getenv(
"ZYPP_PLUGIN_DEBUG" );
44 struct PluginDebugBuffer
46 PluginDebugBuffer(
const std::string & buffer_r ) :
_buffer( buffer_r ) {}
53 L_DBG(
"PLUGIN") <<
"< (empty)" << endl;
57 std::istringstream datas(
_buffer );
68 struct PluginDumpStderr
70 PluginDumpStderr( ExternalProgramWithStderr & prog_r ) :
_prog( prog_r ) {}
74 while (
_prog.stderrGetline( line ) )
75 L_WAR(
"PLUGIN") <<
"! " << line << endl;
77 ExternalProgramWithStderr &
_prog;
80 inline void setBlocking( FILE * file_r,
bool yesno_r =
true )
83 ZYPP_THROW( PluginScriptException(
"setNonBlocking" ) );
85 int fd = ::fileno( file_r );
87 ZYPP_THROW( PluginScriptException(
"setNonBlocking" ) );
89 int flags = ::fcntl( fd, F_GETFL );
91 ZYPP_THROW( PluginScriptException(
"setNonBlocking" ) );
95 else if ( flags & O_NONBLOCK )
98 flags = ::fcntl( fd, F_SETFL, flags );
100 ZYPP_THROW( PluginScriptException(
"setNonBlocking" ) );
103 inline void setNonBlocking( FILE * file_r,
bool yesno_r =
true )
104 { setBlocking( file_r, !yesno_r ); }
123 {
try {
close(); }
catch(...) {} }
143 {
return _cmd !=
nullptr; }
163 scoped_ptr<ExternalProgramWithStderr>
_cmd;
179 const long PLUGIN_TIMEOUT = str::strtonum<long>( getenv(
"ZYPP_PLUGIN_TIMEOUT" ) );
180 const long PLUGIN_SEND_TIMEOUT = str::strtonum<long>( getenv(
"ZYPP_PLUGIN_SEND_TIMEOUT" ) );
181 const long PLUGIN_RECEIVE_TIMEOUT = str::strtonum<long>( getenv(
"ZYPP_PLUGIN_RECEIVE_TIMEOUT" ) );
185 : ( PLUGIN_TIMEOUT > 0 ? PLUGIN_TIMEOUT : 30 ) );
187 : ( PLUGIN_TIMEOUT > 0 ? PLUGIN_TIMEOUT : 30 ) );
193 dumpRangeLine(
DBG <<
"Open " << script_r, args_r.begin(), args_r.end() ) << endl;
207 args.reserve( args_r.size()+1 );
209 args.insert(
args.end(), args_r.begin(), args_r.end() );
213 setNonBlocking(
_cmd->outputFile() );
214 setNonBlocking(
_cmd->inputFile() );
229 DBG <<
"Close:" << *
this << endl;
239 _lastExecError = ret.
body();
248 _lastReturn = _cmd->close();
249 _lastExecError = _cmd->execError();
251 DBG << *
this <<
" -> [" << _lastReturn <<
"] " << _lastExecError << endl;
262 if ( frame_r.
command().empty() )
263 WAR <<
"Send: No command in frame" << frame_r << endl;
268 std::ostringstream datas;
270 datas.str().swap( data );
272 DBG << *
this <<
" ->send " << frame_r << endl;
276 std::istringstream datas( data );
281 FILE * filep = _cmd->outputFile();
285 int fd = ::fileno( filep );
291 PluginDumpStderr _dump( *_cmd );
293 const char * buffer = data.c_str();
294 ssize_t buffsize = data.size();
301 tv.tv_sec = _sendTimeout;
304 int retval = select( fd+1, NULL, &wfds, NULL, &tv );
308 ssize_t ret =
::write( fd, buffer, buffsize );
309 if ( ret == buffsize )
324 if ( errno != EINTR )
326 ERR <<
"write(): " <<
Errno() << endl;
327 if ( errno == EPIPE )
334 else if ( retval == 0 )
336 WAR <<
"Not ready to write within timeout." << endl;
337 ZYPP_THROW( PluginScriptSendTimeout(
"Not ready to write within timeout." ) );
341 if ( errno != EINTR )
343 ERR <<
"select(): " <<
Errno() << endl;
357 FILE * filep = _cmd->inputFile();
361 int fd = ::fileno( filep );
368 PluginDebugBuffer _debug( data );
369 PluginDumpStderr _dump( *_cmd );
371 int ch = fgetc( filep );
374 data.push_back( ch );
378 else if ( ::feof( filep ) )
380 WAR <<
"Unexpected EOF" << endl;
383 else if ( errno != EINTR )
385 if ( errno == EWOULDBLOCK )
393 tv.tv_sec = _receiveTimeout;
396 int retval = select( fd+1, &rfds, NULL, NULL, &tv );
401 else if ( retval == 0 )
403 WAR <<
"Not ready to read within timeout." << endl;
404 ZYPP_THROW( PluginScriptReceiveTimeout(
"Not ready to read within timeout." ) );
408 if ( errno != EINTR )
410 ERR <<
"select(): " <<
Errno() << endl;
417 ERR <<
"read(): " <<
Errno() << endl;
424 std::istringstream datas( data );
426 DBG << *
this <<
" <-" << ret << endl;
467 : _pimpl( new
Impl( script_r ) )
471 : _pimpl( new
Impl( script_r, args_r ) )
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.
ExternalProgram extended to offer reading programs stderr.
std::vector< std::string > Arguments
Commandline arguments passed to a script on open.
long receiveTimeout() const
Local default timeout (sec.) when receiving data.
int close()
Close any open connection.
const std::string & body() const
Return the frame body.
void send(const PluginFrame &frame_r) const
DefaultIntegral & reset()
Reset to the defined initial value.
RW_pointer< Impl > _pimpl
Pointer to implementation.
int lastReturn() const
Remembers a scripts return value after close until next open.
PluginScript implementation.
const Arguments & args() const
std::string _lastExecError
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 "> " ).
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
void open(const Pathname &script_r=Pathname(), const Arguments &args_r=Arguments())
static long _defaultSendTimeout
const Pathname & script() const
std::ostream & dumpRangeLine(std::ostream &str, TIterator begin, TIterator end)
Print range defined by iterators (single line style).
const std::string & lastExecError() const
bool write(const Pathname &path_r, const std::string &key_r, const std::string &val_r, const std::string &newcomment_r)
Add or change a value in sysconfig file path_r.
static long _defaultReceiveTimeout
Wrapper class for ::stat/::lstat.
PluginScript()
Default ctor.
bool isOpen() const
Whether we are connected to a script.
Easy-to use interface to the ZYPP dependency resolver.
const std::string & command() const
Return the frame command.
PluginFrame receive() const
Command frame for communication with PluginScript.
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
DefaultIntegral< int, 0 > _lastReturn
ExternalProgramWithStderr & _prog
std::ostream & writeTo(std::ostream &stream_r) const
Write frame to stream.
const Arguments & args() const
Return the script arguments if set.
static const pid_t NotConnected
pid_t(-1) constant indicating no connection.
static long defaultReceiveTimeout()
Global default timeout (sec.) when receiving data.
Exception safe signal handler save/restore.
std::ostream & operator<<(std::ostream &str, const Exception &obj)
Impl(const Pathname &script_r=Pathname(), const Arguments &args_r=Arguments())
void send(const PluginFrame &frame_r) const
Send a PluginFrame.
const Pathname & script() const
Return the script path if set.
Convenience errno wrapper.
PluginFrame receive() const
Receive a PluginFrame.
const std::string & lastExecError() const
Remembers a scripts execError string after close until next open.
String related utilities and Regular expression matching.
Base class for PluginScript Exception.
long sendTimeout() const
Local default timeout (sec.) when sending data.
scoped_ptr< ExternalProgramWithStderr > _cmd
const std::string & asString() const
String representation.
static long defaultSendTimeout()
Global default timeout (sec.) when sending data.
pid_t getPid() const
Return a connected scripts pid or NotConnected.
Interface to plugin scripts using a Stomp inspired communication protocol.
const std::string & _buffer
void open()
Setup connection and execute script.
TInt strtonum(const C_Str &str)
Parsing numbers from string.
bool isAckCommand() const
Convenience to identify an ACK command.