1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/PluginExecutor.cc
12 #include "zypp/base/LogTools.h"
13 #include "zypp/base/NonCopyable.h"
15 #include "zypp/ZConfig.h"
16 #include "zypp/PathInfo.h"
17 #include "zypp/PluginExecutor.h"
21 #undef ZYPP_BASE_LOGGER_LOGGROUP
22 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::plugin"
24 ///////////////////////////////////////////////////////////////////
27 ///////////////////////////////////////////////////////////////////
28 /// \class PluginExecutor::Impl
29 /// \brief PluginExecutor implementation.
30 ///////////////////////////////////////////////////////////////////
31 class PluginExecutor::Impl : private base::NonCopyable
40 send( PluginFrame( "PLUGINEND" ) );
41 // ~PluginScript will disconnect all remaining plugins!
45 { return _scripts.empty(); }
48 { return _scripts.size(); }
50 void load( const Pathname & path_r )
52 PathInfo pi( path_r );
53 DBG << "+++++++++++++++ load " << pi << endl;
56 std::list<Pathname> entries;
57 if ( filesystem::readdir( entries, pi.path(), false ) != 0 )
59 WAR << "Plugin dir is not readable: " << pi << endl;
62 for_( it, entries.begin(), entries.end() )
65 if ( pii.isFile() && pii.userMayRX() )
69 else if ( pi.isFile() )
74 WAR << "Plugin file is not executable: " << pi << endl;
78 WAR << "Plugin path is neither dir nor file: " << pi << endl;
80 DBG << "--------------- load " << pi << endl;
83 void send( const PluginFrame & frame_r )
85 DBG << "+++++++++++++++ send " << frame_r << endl;
86 for ( auto it = _scripts.begin(); it != _scripts.end(); )
88 doSend( *it, frame_r );
92 it = _scripts.erase( it );
94 DBG << "--------------- send " << frame_r << endl;
97 const std::list<PluginScript> scripts() const
101 /** Launch a plugin sending PLUGINSTART message. */
102 void doLoad( const PathInfo & pi_r )
104 MIL << "Load plugin: " << pi_r << endl;
106 PluginScript plugin( pi_r.path() );
109 PluginFrame frame( "PLUGINBEGIN" );
110 if ( ZConfig::instance().hasUserData() )
111 frame.setHeader( "userdata", ZConfig::instance().userData() );
113 doSend( plugin, frame ); // closes on error
114 if ( plugin.isOpen() )
115 _scripts.push_back( plugin );
117 catch( const zypp::Exception & e )
119 WAR << "Failed to load plugin " << pi_r << endl;
123 PluginFrame doSend( PluginScript & script_r, const PluginFrame & frame_r )
128 script_r.send( frame_r );
129 ret = script_r.receive();
131 catch( const zypp::Exception & e )
134 WAR << e.asUserHistory() << endl;
137 // Allow using "/bin/cat" as reflector-script for testing
138 if ( ! ( ret.isAckCommand() || ret.isEnomethodCommand() || ( script_r.script() == "/bin/cat" && frame_r.command() != "ERROR" ) ) )
140 WAR << "Bad plugin response from " << script_r << ": " << ret << endl;
141 WAR << "(Expected " << PluginFrame::ackCommand() << " or " << PluginFrame::enomethodCommand() << ")" << endl;
148 std::list<PluginScript> _scripts;
151 ///////////////////////////////////////////////////////////////////
153 // CLASS NAME : PluginExecutor
155 ///////////////////////////////////////////////////////////////////
157 PluginExecutor::PluginExecutor()
158 : _pimpl( new Impl() )
161 PluginExecutor::~PluginExecutor()
164 bool PluginExecutor::empty() const
165 { return _pimpl->empty(); }
167 size_t PluginExecutor::size() const
168 { return _pimpl->size(); }
170 void PluginExecutor::load( const Pathname & path_r )
171 { _pimpl->load( path_r ); }
173 void PluginExecutor::send( const PluginFrame & frame_r )
174 { _pimpl->send( frame_r ); }
176 std::ostream & operator<<( std::ostream & str, const PluginExecutor & obj )
177 { return str << obj._pimpl->scripts(); }
180 ///////////////////////////////////////////////////////////////////