diff options
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | src/argument.cpp | 81 | ||||
-rw-r--r-- | src/argument.hpp | 50 | ||||
-rw-r--r-- | src/main.cpp | 55 |
4 files changed, 182 insertions, 6 deletions
diff --git a/Makefile.am b/Makefile.am index 50f4683..caa13dc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -11,7 +11,7 @@ libmapper_la_SOURCES = libmapper/mapper.c libmapper_la_LDFLAGS = $(SYSTEMD_LIBS) -version-info 1:0:0 -shared libmapper_la_CFLAGS = $(SYSTEMD_CFLAGS) -mapperx_SOURCES = src/main.cpp +mapperx_SOURCES = src/main.cpp src/argument.cpp mapperx_LDFLAGS = $(SDBUSPLUS_LIBS) -pthread -ltinyxml2 mapperx_CXXFLAGS = $(SYSTEMD_CFLAGS) -DBOOST_SYSTEM_NO_DEPRECATED -DBOOST_ERROR_CODE_HEADER_ONLY -DBOOST_ALL_NO_LIB diff --git a/src/argument.cpp b/src/argument.cpp new file mode 100644 index 0000000..80bddef --- /dev/null +++ b/src/argument.cpp @@ -0,0 +1,81 @@ +/** + * Copyright © 2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "argument.hpp" + +#include <algorithm> +#include <cassert> +#include <iostream> +#include <iterator> + +const std::string ArgumentParser::true_string = "true"; +const std::string ArgumentParser::empty_string = ""; + +const char* ArgumentParser::optionstr = "s:b:i:?h"; +const option ArgumentParser::options[] = { + {"service-namespaces", required_argument, nullptr, 's'}, + {"service-blacklists", required_argument, nullptr, 'b'}, + {"interface-namespaces", required_argument, nullptr, 'i'}, + {"help", no_argument, nullptr, 'h'}, + {0, 0, 0, 0}, +}; + +ArgumentParser::ArgumentParser(int argc, char** argv) +{ + int option = 0; + while (-1 != + (option = getopt_long(argc, argv, optionstr, options, nullptr))) + { + if ((option == '?') || (option == 'h')) + { + usage(argv); + exit(-1); + } + + auto i = &options[0]; + while ((i->val != option) && (i->val != 0)) + ++i; + + if (i->val) + arguments[i->name] = (i->has_arg ? optarg : true_string); + } +} + +const std::string& ArgumentParser::operator[](const std::string& opt) +{ + auto i = arguments.find(opt); + if (i == arguments.end()) + { + return empty_string; + } + else + { + return i->second; + } +} + +void ArgumentParser::usage(char** argv) +{ + std::cerr << "Usage: " << argv[0] << " [options]" << std::endl; + std::cerr << "Options:" << std::endl; + std::cerr << " --help Print this menu" << std::endl; + std::cerr << " --service-namespaces=<services> Space separated list of "; + std::cerr << "service namespaces to whitelist\n"; + std::cerr << " --service-blacklists=<services> Space separated list of "; + std::cerr << "service names to blacklist\n"; + std::cerr << " --interface-namespaces=<ifaces> Space separated list of "; + std::cerr << "interface namespaces to whitelist\n"; +} diff --git a/src/argument.hpp b/src/argument.hpp new file mode 100644 index 0000000..71a2c76 --- /dev/null +++ b/src/argument.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include <getopt.h> + +#include <map> +#include <string> + +/** @brief Class - Encapsulates parsing command line options and + * populating arguments + */ +class ArgumentParser +{ + public: + ArgumentParser() = delete; + ~ArgumentParser() = default; + ArgumentParser(const ArgumentParser&) = delete; + ArgumentParser& operator=(const ArgumentParser&) = delete; + ArgumentParser(ArgumentParser&&) = default; + ArgumentParser& operator=(ArgumentParser&&) = default; + + /** @brief Constructs Argument object + * + * @param argc - the main function's argc passed as is + * @param argv - the main function's argv passed as is + * @return Object constructed + */ + ArgumentParser(int argc, char** argv); + + /** @brief Given a option, returns its argument(optarg) */ + const std::string& operator[](const std::string& opt); + + /** @brief Displays usage */ + static void usage(char** argv); + + /** @brief Set to 'true' when an option is passed */ + static const std::string true_string; + + /** @brief Set to '' when an option is not passed */ + static const std::string empty_string; + + private: + /** @brief Option to argument mapping */ + std::map<const std::string, std::string> arguments; + + /** @brief Array of struct options as needed by getopt_long */ + static const option options[]; + + /** @brief optstring as needed by getopt_long */ + static const char* optionstr; +}; diff --git a/src/main.cpp b/src/main.cpp index e00e920..c291250 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,3 +1,5 @@ +#include "src/argument.hpp" + #include <tinyxml2.h> #include <atomic> @@ -29,6 +31,10 @@ boost::container::flat_map<std::string, std::shared_ptr<sdbusplus::asio::dbus_interface>> associationInterfaces; +static boost::container::flat_set<std::string> service_whitelist; +static boost::container::flat_set<std::string> service_blacklist; +static boost::container::flat_set<std::string> iface_whitelist; + /** Exception thrown when a path is not found in the object list. */ struct NotFoundException final : public sdbusplus::exception_t { @@ -302,8 +308,16 @@ void do_introspect(sdbusplus::asio::connection* system_bus, continue; } - if (ignored_interfaces.find(std::string(iface_name)) == - ignored_interfaces.end()) + std::string iface{iface_name}; + + if (((ignored_interfaces.find(iface) == + ignored_interfaces.end()) && + (std::find_if(iface_whitelist.begin(), + iface_whitelist.end(), + [iface](const auto& prefix) { + return boost::starts_with(iface, prefix); + }) != iface_whitelist.end())) || + (iface == "org.freedesktop.DBus.ObjectManager")) { thisPathMap[transaction->process_name].emplace(iface_name); } @@ -357,9 +371,17 @@ void do_introspect(sdbusplus::asio::connection* system_bus, bool need_to_introspect(const std::string& process_name) { - return boost::starts_with(process_name, "xyz.openbmc_project.") || - boost::starts_with(process_name, "org.openbmc.") || - boost::starts_with(process_name, "com.intel."); + auto inWhitelist = + std::find_if(service_whitelist.begin(), service_whitelist.end(), + [&process_name](const auto& prefix) { + return boost::starts_with(process_name, prefix); + }) != service_whitelist.end(); + + // This holds full service names, not prefixes + auto inBlacklist = + service_blacklist.find(process_name) != service_blacklist.end(); + + return inWhitelist && !inBlacklist; } void start_new_introspect( @@ -442,13 +464,36 @@ void doListNames( "ListNames"); } +void splitArgs(const std::string& stringArgs, + boost::container::flat_set<std::string>& listArgs) +{ + std::istringstream args; + std::string arg; + + args.str(stringArgs); + + while (!args.eof()) + { + args >> arg; + if (!arg.empty()) + { + listArgs.insert(arg); + } + } +} + int main(int argc, char** argv) { std::cerr << "started\n"; + auto options = ArgumentParser(argc, argv); boost::asio::io_service io; std::shared_ptr<sdbusplus::asio::connection> system_bus = std::make_shared<sdbusplus::asio::connection>(io); + splitArgs(options["service-namespaces"], service_whitelist); + splitArgs(options["interface-namespaces"], iface_whitelist); + splitArgs(options["service-blacklists"], service_blacklist); + system_bus->request_name(OBJECT_MAPPER_DBUS_NAME); sdbusplus::asio::object_server server(system_bus); |