#include <utils/PluginsLoader.hpp> #include <dlfcn.h> #include <rang.hpp> #include <filesystem> #include <iostream> #include <sstream> #include <unistd.h> #include <vector> std::vector<std::string> split(const std::string& full_string) { std::vector<std::string> split_string; std::stringstream is(full_string); std::string segment; while (std::getline(is, segment, ';')) { if (segment.size() > 0) { split_string.push_back(segment); } } return split_string; } void PluginsLoader::_open(const std::string& plugin) { auto handle = dlopen(plugin.c_str(), RTLD_NOW); if (handle != nullptr) { m_dl_handler_stack.push(handle); std::cout << " * \"" << rang::fgB::green << plugin << rang::fg::reset << "\"\n"; } else { std::cout << " " << rang::fgB::red << "cannot load " << rang::fg::reset << '\"' << rang::fgB::yellow << plugin << rang::fg::reset << "\"\n"; } } PluginsLoader::PluginsLoader() { std::vector<std::string> plugin_vector; { char* env = getenv("PUGS_PLUGIN"); if (env != nullptr) { std::string plugins = env; plugin_vector = split(plugins); } } { char* env = getenv("PUGS_PLUGIN_DIR"); if (env != nullptr) { std::string paths = env; std::vector<std::string> path_vector = split(paths); for (auto&& path : path_vector) { if (access(path.c_str(), R_OK) == -1) { std::cout << ' ' << rang::fgB::red << 'X' << rang::fg::reset << " cannot access plugin dir \"" << rang::fgB::yellow << path << rang::fg::reset << "\"\n"; } else { for (auto&& entry : std::filesystem::directory_iterator(path, (std::filesystem::directory_options::follow_directory_symlink | std::filesystem::directory_options::skip_permission_denied))) { if (entry.path().extension() == ".so") { plugin_vector.push_back(entry.path().string()); } } } } } } // keep unique entries std::sort(plugin_vector.begin(), plugin_vector.end()); plugin_vector.resize(std::distance(plugin_vector.begin(), std::unique(plugin_vector.begin(), plugin_vector.end()))); if (plugin_vector.size() > 0) { std::cout << rang::style::bold << "Loading plugins" << rang::style::reset << '\n'; for (auto&& plugin : plugin_vector) { this->_open(plugin); } std::cout << "-------------------------------------------------------\n"; } } PluginsLoader::~PluginsLoader() { while (not m_dl_handler_stack.empty()) { dlclose(m_dl_handler_stack.top()); m_dl_handler_stack.pop(); } }