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;
172 return str <<
"PluginScript[" << obj.
getPid() <<
"] " << obj.
script();
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;
199 PathInfo pi( script_r );
200 if ( ! ( pi.isFile() && pi.isX() ) )
207 args.reserve( args_r.size()+1 );
208 args.push_back( script_r.asString() );
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 ) )
513 {
return str << *obj.
_pimpl; }