libzypp 9.41.1
|
00001 /*---------------------------------------------------------------------\ 00002 | ____ _ __ __ ___ | 00003 | |__ / \ / / . \ . \ | 00004 | / / \ V /| _/ _/ | 00005 | / /__ | | | | | | | 00006 | /_____||_| |_| |_| | 00007 | | 00008 \---------------------------------------------------------------------*/ 00011 #include <iostream> 00012 #include "zypp/base/LogTools.h" 00013 #include "zypp/base/NonCopyable.h" 00014 00015 #include "zypp/ZConfig.h" 00016 #include "zypp/PathInfo.h" 00017 #include "zypp/PluginExecutor.h" 00018 00019 using std::endl; 00020 00021 #undef ZYPP_BASE_LOGGER_LOGGROUP 00022 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::plugin" 00023 00025 namespace zypp 00026 { 00031 class PluginExecutor::Impl : private base::NonCopyable 00032 { 00033 public: 00034 Impl() 00035 {} 00036 00037 ~Impl() 00038 { 00039 if ( ! empty() ) 00040 send( PluginFrame( "PLUGINEND" ) ); 00041 // ~PluginScript will disconnect all remaining plugins! 00042 } 00043 00044 bool empty() const 00045 { return _scripts.empty(); } 00046 00047 size_t size() const 00048 { return _scripts.size(); } 00049 00050 void load( const Pathname & path_r ) 00051 { 00052 PathInfo pi( path_r ); 00053 DBG << "+++++++++++++++ load " << pi << endl; 00054 if ( pi.isDir() ) 00055 { 00056 std::list<Pathname> entries; 00057 if ( filesystem::readdir( entries, pi.path(), false ) != 0 ) 00058 { 00059 WAR << "Plugin dir is not readable: " << pi << endl; 00060 return; 00061 } 00062 for_( it, entries.begin(), entries.end() ) 00063 { 00064 PathInfo pii( *it ); 00065 if ( pii.isFile() && pii.userMayRX() ) 00066 doLoad( pii ); 00067 } 00068 } 00069 else if ( pi.isFile() ) 00070 { 00071 if ( pi.userMayRX() ) 00072 doLoad( pi ); 00073 else 00074 WAR << "Plugin file is not executable: " << pi << endl; 00075 } 00076 else 00077 { 00078 WAR << "Plugin path is neither dir nor file: " << pi << endl; 00079 } 00080 DBG << "--------------- load " << pi << endl; 00081 } 00082 00083 void send( const PluginFrame & frame_r ) 00084 { 00085 DBG << "+++++++++++++++ send " << frame_r << endl; 00086 for ( std::list<PluginScript>::iterator it = _scripts.begin(); it != _scripts.end(); ) 00087 { 00088 doSend( *it, frame_r ); 00089 if ( it->isOpen() ) 00090 ++it; 00091 else 00092 it = _scripts.erase( it ); 00093 } 00094 DBG << "--------------- send " << frame_r << endl; 00095 } 00096 00097 const std::list<PluginScript> scripts() const 00098 { return _scripts; } 00099 00100 private: 00102 void doLoad( const PathInfo & pi_r ) 00103 { 00104 MIL << "Load plugin: " << pi_r << endl; 00105 try { 00106 PluginScript plugin( pi_r.path() ); 00107 plugin.open(); 00108 00109 PluginFrame frame( "PLUGINBEGIN" ); 00110 if ( ZConfig::instance().hasUserData() ) 00111 frame.setHeader( "userdata", ZConfig::instance().userData() ); 00112 00113 doSend( plugin, frame ); // closes on error 00114 if ( plugin.isOpen() ) 00115 _scripts.push_back( plugin ); 00116 } 00117 catch( const zypp::Exception & e ) 00118 { 00119 WAR << "Failed to load plugin " << pi_r << endl; 00120 } 00121 } 00122 00123 PluginFrame doSend( PluginScript & script_r, const PluginFrame & frame_r ) 00124 { 00125 PluginFrame ret; 00126 00127 try { 00128 script_r.send( frame_r ); 00129 ret = script_r.receive(); 00130 } 00131 catch( const zypp::Exception & e ) 00132 { 00133 ZYPP_CAUGHT(e); 00134 WAR << e.asUserHistory() << endl; 00135 } 00136 00137 // Allow using "/bin/cat" as reflector-script for testing 00138 if ( ! ( ret.isAckCommand() || ret.isEnomethodCommand() || ( script_r.script() == "/bin/cat" && frame_r.command() != "ERROR" ) ) ) 00139 { 00140 WAR << "Bad plugin response from " << script_r << ": " << ret << endl; 00141 WAR << "(Expected " << PluginFrame::ackCommand() << " or " << PluginFrame::enomethodCommand() << ")" << endl; 00142 script_r.close(); 00143 } 00144 00145 return ret; 00146 } 00147 private: 00148 std::list<PluginScript> _scripts; 00149 }; 00150 00152 // 00153 // CLASS NAME : PluginExecutor 00154 // 00156 00157 PluginExecutor::PluginExecutor() 00158 : _pimpl( new Impl() ) 00159 {} 00160 00161 PluginExecutor::~PluginExecutor() 00162 {} 00163 00164 bool PluginExecutor::empty() const 00165 { return _pimpl->empty(); } 00166 00167 size_t PluginExecutor::size() const 00168 { return _pimpl->size(); } 00169 00170 void PluginExecutor::load( const Pathname & path_r ) 00171 { _pimpl->load( path_r ); } 00172 00173 void PluginExecutor::send( const PluginFrame & frame_r ) 00174 { _pimpl->send( frame_r ); } 00175 00176 std::ostream & operator<<( std::ostream & str, const PluginExecutor & obj ) 00177 { return str << obj._pimpl->scripts(); } 00178 00179 } // namespace zypp