| 1 | #pragma once
|
|---|
| 2 |
|
|---|
| 3 | #include <boost/program_options.hpp>
|
|---|
| 4 | #include "settings_client.hpp"
|
|---|
| 5 | #include <nsclient/logger.hpp>
|
|---|
| 6 |
|
|---|
| 7 | namespace po = boost::program_options;
|
|---|
| 8 | class cli_parser {
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 | NSClient* core_;
|
|---|
| 12 | po::options_description root;
|
|---|
| 13 | po::options_description common;
|
|---|
| 14 | po::options_description settings;
|
|---|
| 15 | po::options_description service;
|
|---|
| 16 | po::options_description client;
|
|---|
| 17 | po::options_description unittest;
|
|---|
| 18 | po::options_description test;
|
|---|
| 19 |
|
|---|
| 20 | bool help;
|
|---|
| 21 | bool version;
|
|---|
| 22 | bool log_debug;
|
|---|
| 23 | std::wstring log_level;
|
|---|
| 24 | std::wstring settings_store;
|
|---|
| 25 |
|
|---|
| 26 | static nsclient::logging::logger_interface* get_logger() {
|
|---|
| 27 | return nsclient::logging::logger::get_logger();
|
|---|
| 28 | }
|
|---|
| 29 | static void error(unsigned int line, const std::wstring &message) {
|
|---|
| 30 | get_logger()->error(_T("client"), __FILE__, line, message);
|
|---|
| 31 | }
|
|---|
| 32 | static void info(unsigned int line, const std::wstring &message) {
|
|---|
| 33 | get_logger()->info(_T("client"), __FILE__, line, message);
|
|---|
| 34 | }
|
|---|
| 35 |
|
|---|
| 36 | public:
|
|---|
| 37 | cli_parser(NSClient* core)
|
|---|
| 38 | : core_(core)
|
|---|
| 39 | , root("Allowed first option (Mode of operation)")
|
|---|
| 40 | , common("Common options")
|
|---|
| 41 | , settings("Settings options")
|
|---|
| 42 | , service("Service Options")
|
|---|
| 43 | , client("Client Options")
|
|---|
| 44 | , unittest("Unit-test Options")
|
|---|
| 45 | , test("Test Options")
|
|---|
| 46 | , help(false)
|
|---|
| 47 | , version(false)
|
|---|
| 48 | , log_debug(false)
|
|---|
| 49 | {
|
|---|
| 50 | root.add_options()
|
|---|
| 51 | ("help", po::bool_switch(&help), "produce help message")
|
|---|
| 52 | ("version", po::bool_switch(&version), "Show version information")
|
|---|
| 53 | ;
|
|---|
| 54 |
|
|---|
| 55 | common.add_options()
|
|---|
| 56 | ("settings", po::value<std::wstring>(&settings_store), "Override (temporarily) settings subsystem to use")
|
|---|
| 57 | ("help", po::bool_switch(&help), "produce help message")
|
|---|
| 58 | ("debug", po::bool_switch(&log_debug), "Set log level to debug (and show debug information)")
|
|---|
| 59 | ("log", po::value<std::wstring>(&log_level), "The log level to use")
|
|---|
| 60 | ("version", po::bool_switch(&version), "Show version information")
|
|---|
| 61 | ;
|
|---|
| 62 |
|
|---|
| 63 | settings.add_options()
|
|---|
| 64 | ("migrate-to", po::value<std::wstring>(), "Migrate (copy) settings from current store to target store")
|
|---|
| 65 | ("migrate-from", po::value<std::wstring>(), "Migrate (copy) settings from current store to target store")
|
|---|
| 66 | ("generate", po::value<std::wstring>(), "(re)Generate a commented settings store or similar KEY can be trac, settings or the target store.")
|
|---|
| 67 | ("filter", po::value<std::wstring>(), "Filter what to update (only works with generate trac currently).")
|
|---|
| 68 | ("add-defaults", "Add all default (if missing) values.")
|
|---|
| 69 | ("load-all", "Load all plugins (currently only used with generate).")
|
|---|
| 70 | ("path", po::value<std::wstring>()->default_value(_T("")), "Path of key to work with.")
|
|---|
| 71 | ("key", po::value<std::wstring>()->default_value(_T("")), "Key to work with.")
|
|---|
| 72 | ("set", po::value<std::wstring>()->implicit_value(_T("")), "Set a key and path to a given value.")
|
|---|
| 73 | ("switch", po::value<std::wstring>(), "Set default context to use (similar to migrate but does NOT copy values)")
|
|---|
| 74 | ("show", "Set a value given a key and path.")
|
|---|
| 75 | ("list", "Set all keys below the path (or root).")
|
|---|
| 76 | ;
|
|---|
| 77 |
|
|---|
| 78 | service.add_options()
|
|---|
| 79 | ("install", "Install service")
|
|---|
| 80 | ("uninstall", "Uninstall service")
|
|---|
| 81 | ("start", "Start service")
|
|---|
| 82 | ("stop", "Stop service")
|
|---|
| 83 | ("info", "Show information about service")
|
|---|
| 84 | ("run", "Run as a service")
|
|---|
| 85 | ("name", po::value<std::wstring>(), "Name of service")
|
|---|
| 86 | ("description", po::value<std::wstring>()->default_value(_T("")), "Description of service")
|
|---|
| 87 | ;
|
|---|
| 88 |
|
|---|
| 89 | client.add_options()
|
|---|
| 90 | ("exec,e", po::value<std::wstring>()->implicit_value(_T("")), "Run a command (execute)")
|
|---|
| 91 | ("boot,b", "Boot the client before executing command (similar as running the command from test)")
|
|---|
| 92 | ("query,q", po::value<std::wstring>(), "Run a query with a given name")
|
|---|
| 93 | ("submit,s", po::value<std::wstring>(), "Name of query to ask")
|
|---|
| 94 | ("module,M", po::value<std::wstring>(), "Name of module to load (if not specified all modules in ini file will be loaded)")
|
|---|
| 95 | ("argument,a", po::wvalue<std::vector<std::wstring> >(), "List of arguments (gets -- prefixed automatically)")
|
|---|
| 96 | ("raw-argument", po::wvalue<std::vector<std::wstring> >(), "List of arguments (does not get -- prefixed)")
|
|---|
| 97 | ;
|
|---|
| 98 |
|
|---|
| 99 | unittest.add_options()
|
|---|
| 100 | ("language,l", po::value<std::wstring>()->implicit_value(_T("")), "Language tests are written in")
|
|---|
| 101 | ("argument,a", po::wvalue<std::vector<std::wstring> >(), "List of arguments (gets -- prefixed automatically)")
|
|---|
| 102 | ("raw-argument", po::wvalue<std::vector<std::wstring> >(), "List of arguments (does not get -- prefixed)")
|
|---|
| 103 | ;
|
|---|
| 104 |
|
|---|
| 105 | test.add_options()
|
|---|
| 106 | ("log-to-file", "Enable file logger (defaults is console only)")
|
|---|
| 107 | ;
|
|---|
| 108 |
|
|---|
| 109 | }
|
|---|
| 110 |
|
|---|
| 111 | bool process_common_options(std::string context, po::options_description &desc) {
|
|---|
| 112 | nsclient::logging::logger::get_logger()->set_console_log(true);
|
|---|
| 113 | if (log_debug) {
|
|---|
| 114 | log_level = _T("debug");
|
|---|
| 115 | }
|
|---|
| 116 | if (!log_level.empty())
|
|---|
| 117 | nsclient::logging::logger::set_log_level(log_level);
|
|---|
| 118 | if (!settings_store.empty())
|
|---|
| 119 | core_->set_settings_context(settings_store);
|
|---|
| 120 |
|
|---|
| 121 | if (help) {
|
|---|
| 122 | std::cout << desc << std::endl;
|
|---|
| 123 | return true;
|
|---|
| 124 | }
|
|---|
| 125 | if (version) {
|
|---|
| 126 | std::cout << APPLICATION_NAME << _T(", Version: ") << CURRENT_SERVICE_VERSION << _T(", Platform: ") << SZARCH << std::endl;
|
|---|
| 127 | return true;
|
|---|
| 128 | }
|
|---|
| 129 | return false;
|
|---|
| 130 | }
|
|---|
| 131 |
|
|---|
| 132 | typedef boost::function<int(int, wchar_t**)> handler_function;
|
|---|
| 133 | typedef std::map<std::string,handler_function> handler_map;
|
|---|
| 134 | typedef std::map<std::string,std::string> alias_map;
|
|---|
| 135 |
|
|---|
| 136 | handler_map get_handlers() {
|
|---|
| 137 | handler_map handlers;
|
|---|
| 138 | handlers["settings"] = boost::bind(&cli_parser::parse_settings, this, _1, _2);
|
|---|
| 139 | handlers["service"] = boost::bind(&cli_parser::parse_service, this, _1, _2);
|
|---|
| 140 | handlers["client"] = boost::bind(&cli_parser::parse_client, this, _1, _2, _T(""));
|
|---|
| 141 | handlers["test"] = boost::bind(&cli_parser::parse_test, this, _1, _2);
|
|---|
| 142 | handlers["help"] = boost::bind(&cli_parser::parse_help, this, _1, _2);
|
|---|
| 143 | handlers["unit"] = boost::bind(&cli_parser::parse_unittest, this, _1, _2);
|
|---|
| 144 | return handlers;
|
|---|
| 145 | }
|
|---|
| 146 |
|
|---|
| 147 | alias_map get_aliases() {
|
|---|
| 148 | alias_map aliases;
|
|---|
| 149 | aliases["nrpe"] = "NRPEClient";
|
|---|
| 150 | aliases["nscp"] = "NSCPClient";
|
|---|
| 151 | aliases["nsca"] = "NSCAClient";
|
|---|
| 152 | aliases["eventlog"] = "CheckEventLog";
|
|---|
| 153 | aliases["python"] = "PythonScript";
|
|---|
| 154 | aliases["py"] = "PythonScript";
|
|---|
| 155 | aliases["lua"] = "LuaScript";
|
|---|
| 156 | aliases["syslog"] = "SyslogClient";
|
|---|
| 157 | aliases["sys"] = "CheckSystem";
|
|---|
| 158 | aliases["wmi"] = "CheckWMI";
|
|---|
| 159 | return aliases;
|
|---|
| 160 | }
|
|---|
| 161 |
|
|---|
| 162 | int parse(int argc, wchar_t* argv[]) {
|
|---|
| 163 |
|
|---|
| 164 | if (argc > 1 && argv[1][0] != L'-') {
|
|---|
| 165 | handler_map handlers = get_handlers();
|
|---|
| 166 | alias_map aliases = get_aliases();
|
|---|
| 167 |
|
|---|
| 168 | std::string mod = utf8::cvt<std::string>(argv[1]);
|
|---|
| 169 | handler_map::const_iterator it = handlers.find(mod);
|
|---|
| 170 | if (it != handlers.end())
|
|---|
| 171 | return it->second(argc-1, &argv[1]);
|
|---|
| 172 |
|
|---|
| 173 | alias_map::const_iterator alias_it = aliases.find(mod);
|
|---|
| 174 | if (alias_it != aliases.end())
|
|---|
| 175 | return parse_client(argc-1, &argv[1], utf8::cvt<std::wstring>(alias_it->second));
|
|---|
| 176 |
|
|---|
| 177 | parse_help(argc, argv);
|
|---|
| 178 | std::cerr << "Invalid module specified: " << mod << std::endl;
|
|---|
| 179 | return 1;
|
|---|
| 180 | }
|
|---|
| 181 | return parse_help(argc, argv);
|
|---|
| 182 | }
|
|---|
| 183 | int parse_help(int argc, wchar_t* argv[]) {
|
|---|
| 184 | try {
|
|---|
| 185 |
|
|---|
| 186 | po::options_description all("Allowed options");
|
|---|
| 187 | all.add(root).add(common).add(service).add(settings).add(client).add(test).add(unittest);
|
|---|
| 188 | std::cout << all << std::endl;
|
|---|
| 189 |
|
|---|
| 190 | std::cerr << "First argument has to be one of the following: ";
|
|---|
| 191 | handler_map handlers = get_handlers();
|
|---|
| 192 | BOOST_FOREACH(const handler_map::value_type &itm, handlers) {
|
|---|
| 193 | std::cerr << itm.first << ", ";
|
|---|
| 194 | }
|
|---|
| 195 | std::cerr << std::endl;
|
|---|
| 196 | std::cerr << "Or on of the following client aliases: ";
|
|---|
| 197 | alias_map aliases = get_aliases();
|
|---|
| 198 | BOOST_FOREACH(const alias_map::value_type &itm, aliases) {
|
|---|
| 199 | std::cerr << itm.first << ", ";
|
|---|
| 200 | }
|
|---|
| 201 | std::cerr << std::endl;
|
|---|
| 202 | return 1;
|
|---|
| 203 | } catch(std::exception & e) {
|
|---|
| 204 | std::cerr << "Unable to parse root option: " << e.what() << std::endl;
|
|---|
| 205 | return 1;
|
|---|
| 206 | } catch (...) {
|
|---|
| 207 | std::cerr << "Unable to parse root option" << std::endl;
|
|---|
| 208 | return 1;
|
|---|
| 209 | }
|
|---|
| 210 | }
|
|---|
| 211 |
|
|---|
| 212 | int parse_test(int argc, wchar_t* argv[]) {
|
|---|
| 213 | try {
|
|---|
| 214 |
|
|---|
| 215 | po::options_description all("Allowed options (test)");
|
|---|
| 216 | all.add(common).add(test);
|
|---|
| 217 |
|
|---|
| 218 | po::variables_map vm;
|
|---|
| 219 | po::store(po::parse_command_line(argc, argv, all), vm);
|
|---|
| 220 | po::notify(vm);
|
|---|
| 221 |
|
|---|
| 222 | if (log_level.empty())
|
|---|
| 223 | log_level = _T("debug");
|
|---|
| 224 |
|
|---|
| 225 | if (process_common_options("test", all))
|
|---|
| 226 | return 1;
|
|---|
| 227 |
|
|---|
| 228 | if (vm.count("log-to-file") == 0) {
|
|---|
| 229 | nsclient::logging::logger::set_backend("console");
|
|---|
| 230 | }
|
|---|
| 231 |
|
|---|
| 232 | nsclient::simple_client client(core_);
|
|---|
| 233 | client.start(log_level);
|
|---|
| 234 | return 0;
|
|---|
| 235 | } catch(const std::exception & e) {
|
|---|
| 236 | std::cerr << std::string("Unable to parse command line (test): ") << e.what() << "\n";
|
|---|
| 237 | return 1;
|
|---|
| 238 | }
|
|---|
| 239 | }
|
|---|
| 240 |
|
|---|
| 241 | int parse_settings(int argc, wchar_t* argv[]) {
|
|---|
| 242 | try {
|
|---|
| 243 | po::options_description all("Allowed options (settings)");
|
|---|
| 244 | all.add(common).add(settings);
|
|---|
| 245 |
|
|---|
| 246 | po::variables_map vm;
|
|---|
| 247 | po::store(po::parse_command_line(argc, argv, all), vm);
|
|---|
| 248 | po::notify(vm);
|
|---|
| 249 |
|
|---|
| 250 | if (process_common_options("settings", all))
|
|---|
| 251 | return 1;
|
|---|
| 252 |
|
|---|
| 253 | bool def = vm.count("add-defaults")==1;
|
|---|
| 254 | bool load_all = vm.count("load-all")==1;
|
|---|
| 255 | std::wstring filter;
|
|---|
| 256 | if (vm.count("filter"))
|
|---|
| 257 | filter = vm["filter"].as<std::wstring>();
|
|---|
| 258 |
|
|---|
| 259 | nsclient::settings_client client(core_, log_level, def, load_all, filter);
|
|---|
| 260 | int ret = -1;
|
|---|
| 261 |
|
|---|
| 262 | if (vm.count("generate")) {
|
|---|
| 263 | ret = client.generate(vm["generate"].as<std::wstring>());
|
|---|
| 264 | } else if (vm.count("migrate-to")) {
|
|---|
| 265 | ret = client.migrate_to(vm["migrate-to"].as<std::wstring>());
|
|---|
| 266 | } else if (vm.count("migrate-from")) {
|
|---|
| 267 | ret = client.migrate_from(vm["migrate-from"].as<std::wstring>());
|
|---|
| 268 | } else if (vm.count("set")) {
|
|---|
| 269 | ret = client.set(vm["path"].as<std::wstring>(), vm["key"].as<std::wstring>(), vm["set"].as<std::wstring>());
|
|---|
| 270 | } else if (vm.count("list")) {
|
|---|
| 271 | ret = client.list(vm["path"].as<std::wstring>());
|
|---|
| 272 | } else if (vm.count("show")) {
|
|---|
| 273 | ret = client.show(vm["path"].as<std::wstring>(), vm["key"].as<std::wstring>());
|
|---|
| 274 | } else if (vm.count("switch")) {
|
|---|
| 275 | client.switch_context(vm["switch"].as<std::wstring>());
|
|---|
| 276 | ret = 0;
|
|---|
| 277 | } else {
|
|---|
| 278 | std::cout << all << std::endl;
|
|---|
| 279 | return 1;
|
|---|
| 280 | }
|
|---|
| 281 |
|
|---|
| 282 | return ret;
|
|---|
| 283 | } catch(const std::exception & e) {
|
|---|
| 284 | std::cerr << std::string("Unable to parse command line (settings): ") << e.what() << "\n";
|
|---|
| 285 | return 1;
|
|---|
| 286 | }
|
|---|
| 287 | }
|
|---|
| 288 |
|
|---|
| 289 |
|
|---|
| 290 | int parse_service(int argc, wchar_t* argv[]) {
|
|---|
| 291 | try {
|
|---|
| 292 | po::options_description all("Allowed options (service)");
|
|---|
| 293 | all.add(common).add(service);
|
|---|
| 294 |
|
|---|
| 295 | po::variables_map vm;
|
|---|
| 296 | po::store(po::parse_command_line(argc, argv, all), vm);
|
|---|
| 297 | po::notify(vm);
|
|---|
| 298 |
|
|---|
| 299 | if (process_common_options("service", all))
|
|---|
| 300 | return 1;
|
|---|
| 301 |
|
|---|
| 302 | std::wstring name;
|
|---|
| 303 | if (vm.count("name")) {
|
|---|
| 304 | name = vm["name"].as<std::wstring>();
|
|---|
| 305 | } else {
|
|---|
| 306 | info(__LINE__, _T("TODO retrieve name from service here"));
|
|---|
| 307 | }
|
|---|
| 308 | std::wstring desc;
|
|---|
| 309 | if (vm.count("description")) {
|
|---|
| 310 | desc = vm["description"].as<std::wstring>();
|
|---|
| 311 | } else {
|
|---|
| 312 | info(__LINE__, _T("TODO retrieve name from service here"));
|
|---|
| 313 | }
|
|---|
| 314 | if (nsclient::logging::logger::get_logger()->should_log(NSCAPI::log_level::debug)) {
|
|---|
| 315 | info(__LINE__, _T("Service name: ") + name);
|
|---|
| 316 | info(__LINE__, _T("Service description: ") + desc);
|
|---|
| 317 | }
|
|---|
| 318 |
|
|---|
| 319 | if (vm.count("run")) {
|
|---|
| 320 | try {
|
|---|
| 321 | mainClient.start_and_wait(name);
|
|---|
| 322 | } catch (...) {
|
|---|
| 323 | error(__LINE__, _T("Unknown exception in service"));
|
|---|
| 324 | }
|
|---|
| 325 | } else {
|
|---|
| 326 | nsclient::client::service_manager service_manager(name);
|
|---|
| 327 |
|
|---|
| 328 | if (vm.count("install")) {
|
|---|
| 329 | service_manager.install(desc);
|
|---|
| 330 | } else if (vm.count("uninstall")) {
|
|---|
| 331 | service_manager.uninstall();
|
|---|
| 332 | } else if (vm.count("start")) {
|
|---|
| 333 | service_manager.start();
|
|---|
| 334 | } else if (vm.count("stop")) {
|
|---|
| 335 | service_manager.stop();
|
|---|
| 336 | } else if (vm.count("info")) {
|
|---|
| 337 | service_manager.info();
|
|---|
| 338 | } else {
|
|---|
| 339 | std::cerr << "Missing argument" << std::endl;
|
|---|
| 340 | return 1;
|
|---|
| 341 | }
|
|---|
| 342 | }
|
|---|
| 343 | return 0;
|
|---|
| 344 | } catch(std::exception & e) {
|
|---|
| 345 | std::cerr << std::string("Unable to parse command line (settings): ") << e.what() << "\n";
|
|---|
| 346 | return 1;
|
|---|
| 347 | }
|
|---|
| 348 | }
|
|---|
| 349 |
|
|---|
| 350 | struct client_arguments {
|
|---|
| 351 | std::wstring command, combined_query, module;
|
|---|
| 352 | std::vector<std::wstring> arguments;
|
|---|
| 353 | enum modes { exec, query, submit, none, combined};
|
|---|
| 354 | modes mode;
|
|---|
| 355 | bool boot;
|
|---|
| 356 | client_arguments() : mode(none), boot(false) {}
|
|---|
| 357 |
|
|---|
| 358 | void debug() {
|
|---|
| 359 | if (nsclient::logging::logger::get_logger()->should_log(NSCAPI::log_level::debug)) {
|
|---|
| 360 | info(__LINE__, _T("Module: ") + module);
|
|---|
| 361 | info(__LINE__, _T("Command: ") + command);
|
|---|
| 362 | info(__LINE__, _T("Extra Query: ") + combined_query);
|
|---|
| 363 | info(__LINE__, _T("Mode: ") + strEx::itos(mode));
|
|---|
| 364 | info(__LINE__, _T("Boot: ") + strEx::itos(boot));
|
|---|
| 365 | if (!module.empty() && boot)
|
|---|
| 366 | info(__LINE__, _T("Warning module and boot specified only THAT module will be loaded"));
|
|---|
| 367 | std::wstring args;
|
|---|
| 368 | BOOST_FOREACH(std::wstring s, arguments)
|
|---|
| 369 | strEx::append_list(args, s, _T(", "));
|
|---|
| 370 | info(__LINE__, _T("Arguments: ") + args);
|
|---|
| 371 | }
|
|---|
| 372 |
|
|---|
| 373 | }
|
|---|
| 374 | };
|
|---|
| 375 | int parse_client(int argc, wchar_t* argv[], std::wstring module_ = _T("")) {
|
|---|
| 376 | try {
|
|---|
| 377 | client_arguments args;
|
|---|
| 378 |
|
|---|
| 379 | args.module = module_;
|
|---|
| 380 | po::options_description all("Allowed options (client)");
|
|---|
| 381 | all.add(common).add(client);
|
|---|
| 382 |
|
|---|
| 383 | po::positional_options_description p;
|
|---|
| 384 | p.add("arguments", -1);
|
|---|
| 385 |
|
|---|
| 386 | po::variables_map vm;
|
|---|
| 387 | po::wparsed_options parsed =
|
|---|
| 388 | po::wcommand_line_parser(argc, argv).options(all).allow_unregistered().run();
|
|---|
| 389 | po::store(parsed, vm);
|
|---|
| 390 | po::notify(vm);
|
|---|
| 391 |
|
|---|
| 392 | if (process_common_options("client", all))
|
|---|
| 393 | return 1;
|
|---|
| 394 |
|
|---|
| 395 |
|
|---|
| 396 | if (vm.count("exec")) {
|
|---|
| 397 | args.command = vm["exec"].as<std::wstring>();
|
|---|
| 398 | args.mode = client_arguments::exec;
|
|---|
| 399 | if (vm.count("query")) {
|
|---|
| 400 | args.combined_query = vm["query"].as<std::wstring>();
|
|---|
| 401 | args.mode = client_arguments::combined;
|
|---|
| 402 | }
|
|---|
| 403 | } else if (vm.count("query")) {
|
|---|
| 404 | args.command = vm["query"].as<std::wstring>();
|
|---|
| 405 | args.mode = client_arguments::query;
|
|---|
| 406 | } else if (vm.count("submit")) {
|
|---|
| 407 | args.command = vm["submit"].as<std::wstring>();
|
|---|
| 408 | args.mode = client_arguments::submit;
|
|---|
| 409 | }
|
|---|
| 410 |
|
|---|
| 411 | if (vm.count("module"))
|
|---|
| 412 | args.module = vm["module"].as<std::wstring>();
|
|---|
| 413 |
|
|---|
| 414 | if (vm.count("boot"))
|
|---|
| 415 | args.boot = true;
|
|---|
| 416 |
|
|---|
| 417 | std::vector<std::wstring> kvp_args;
|
|---|
| 418 | if (vm.count("argument"))
|
|---|
| 419 | kvp_args = vm["argument"].as<std::vector<std::wstring> >();
|
|---|
| 420 |
|
|---|
| 421 | args.arguments = po::collect_unrecognized(parsed.options, po::include_positional);
|
|---|
| 422 |
|
|---|
| 423 | BOOST_FOREACH(std::wstring s, kvp_args) {
|
|---|
| 424 | std::wstring::size_type pos = s.find(L'=');
|
|---|
| 425 | if (pos == std::wstring::npos)
|
|---|
| 426 | args.arguments.push_back(_T("--") + s);
|
|---|
| 427 | else {
|
|---|
| 428 | args.arguments.push_back(_T("--") + s.substr(0,pos));
|
|---|
| 429 | args.arguments.push_back(s.substr(pos+1));
|
|---|
| 430 | }
|
|---|
| 431 | }
|
|---|
| 432 |
|
|---|
| 433 | if (vm.count("raw-argument"))
|
|---|
| 434 | kvp_args = vm["raw-argument"].as<std::vector<std::wstring> >();
|
|---|
| 435 | BOOST_FOREACH(std::wstring s, kvp_args) {
|
|---|
| 436 | std::wstring::size_type pos = s.find(L'=');
|
|---|
| 437 | if (pos == std::wstring::npos)
|
|---|
| 438 | args.arguments.push_back(s);
|
|---|
| 439 | else {
|
|---|
| 440 | args.arguments.push_back(s.substr(0,pos));
|
|---|
| 441 | args.arguments.push_back(s.substr(pos+1));
|
|---|
| 442 | }
|
|---|
| 443 | }
|
|---|
| 444 | return exec_client_mode(args);
|
|---|
| 445 | } catch(const std::exception & e) {
|
|---|
| 446 | std::wcerr << _T("Client: Unable to parse command line: ") << utf8::to_unicode(e.what()) << std::endl;
|
|---|
| 447 | return 1;
|
|---|
| 448 | } catch(...) {
|
|---|
| 449 | std::wcerr << _T("Client: Unable to parse command line: UNKNOWN") << std::endl;
|
|---|
| 450 | return 1;
|
|---|
| 451 | }
|
|---|
| 452 | }
|
|---|
| 453 |
|
|---|
| 454 | int parse_unittest(int argc, wchar_t* argv[]) {
|
|---|
| 455 | try {
|
|---|
| 456 | client_arguments args;
|
|---|
| 457 | settings_store = _T("dummy");
|
|---|
| 458 | po::options_description all("Allowed options (client)");
|
|---|
| 459 | all.add(common).add(unittest);
|
|---|
| 460 |
|
|---|
| 461 | po::positional_options_description p;
|
|---|
| 462 | p.add("arguments", -1);
|
|---|
| 463 |
|
|---|
| 464 | po::variables_map vm;
|
|---|
| 465 | po::wparsed_options parsed =
|
|---|
| 466 | po::wcommand_line_parser(argc, argv).options(all).allow_unregistered().run();
|
|---|
| 467 | po::store(parsed, vm);
|
|---|
| 468 | po::notify(vm);
|
|---|
| 469 |
|
|---|
| 470 | if (process_common_options("unitest", all))
|
|---|
| 471 | return 1;
|
|---|
| 472 |
|
|---|
| 473 |
|
|---|
| 474 | if (vm.count("language")) {
|
|---|
| 475 | std::wstring lang = vm["language"].as<std::wstring>();
|
|---|
| 476 | if (lang == _T("python") || lang == _T("py")) {
|
|---|
| 477 | args.command = _T("python-script");
|
|---|
| 478 | args.combined_query = _T("py_unittest");
|
|---|
| 479 | args.mode = client_arguments::combined;
|
|---|
| 480 | args.module = _T("PythonScript");
|
|---|
| 481 | } else {
|
|---|
| 482 | std::wcerr << _T("Unknown language: ") << lang << std::endl;
|
|---|
| 483 | return 1;
|
|---|
| 484 | }
|
|---|
| 485 | } else {
|
|---|
| 486 | args.command = _T("python-script");
|
|---|
| 487 | args.combined_query = _T("py_unittest");
|
|---|
| 488 | args.mode = client_arguments::combined;
|
|---|
| 489 | args.module = _T("PythonScript");
|
|---|
| 490 | }
|
|---|
| 491 |
|
|---|
| 492 | std::vector<std::wstring> kvp_args;
|
|---|
| 493 | if (vm.count("argument"))
|
|---|
| 494 | kvp_args = vm["argument"].as<std::vector<std::wstring> >();
|
|---|
| 495 |
|
|---|
| 496 | args.arguments = po::collect_unrecognized(parsed.options, po::include_positional);
|
|---|
| 497 |
|
|---|
| 498 | BOOST_FOREACH(std::wstring s, kvp_args) {
|
|---|
| 499 | std::wstring::size_type pos = s.find(L'=');
|
|---|
| 500 | if (pos == std::wstring::npos)
|
|---|
| 501 | args.arguments.push_back(_T("--") + s);
|
|---|
| 502 | else {
|
|---|
| 503 | args.arguments.push_back(_T("--") + s.substr(0,pos));
|
|---|
| 504 | args.arguments.push_back(s.substr(pos+1));
|
|---|
| 505 | }
|
|---|
| 506 | }
|
|---|
| 507 |
|
|---|
| 508 | if (vm.count("raw-argument"))
|
|---|
| 509 | kvp_args = vm["raw-argument"].as<std::vector<std::wstring> >();
|
|---|
| 510 | BOOST_FOREACH(std::wstring s, kvp_args) {
|
|---|
| 511 | std::wstring::size_type pos = s.find(L'=');
|
|---|
| 512 | if (pos == std::wstring::npos)
|
|---|
| 513 | args.arguments.push_back(s);
|
|---|
| 514 | else {
|
|---|
| 515 | args.arguments.push_back(s.substr(0,pos));
|
|---|
| 516 | args.arguments.push_back(s.substr(pos+1));
|
|---|
| 517 | }
|
|---|
| 518 | }
|
|---|
| 519 | return exec_client_mode(args);
|
|---|
| 520 | } catch(const std::exception & e) {
|
|---|
| 521 | std::wcerr << _T("Client: Unable to parse command line: ") << utf8::to_unicode(e.what()) << std::endl;
|
|---|
| 522 | return 1;
|
|---|
| 523 | } catch(...) {
|
|---|
| 524 | std::wcerr << _T("Client: Unable to parse command line: UNKNOWN") << std::endl;
|
|---|
| 525 | return 1;
|
|---|
| 526 | }
|
|---|
| 527 | }
|
|---|
| 528 |
|
|---|
| 529 | int exec_client_mode(client_arguments &args) {
|
|---|
| 530 | try {
|
|---|
| 531 | args.debug();
|
|---|
| 532 |
|
|---|
| 533 | core_->boot_init(log_level);
|
|---|
| 534 | if (args.module.empty())
|
|---|
| 535 | core_->boot_load_all_plugins();
|
|---|
| 536 | else
|
|---|
| 537 | core_->boot_load_plugin(args.module);
|
|---|
| 538 | core_->boot_start_plugins(args.boot);
|
|---|
| 539 | int ret = 0;
|
|---|
| 540 | std::list<std::wstring> resp;
|
|---|
| 541 | if (args.mode == client_arguments::none) {
|
|---|
| 542 | args.mode = client_arguments::exec;
|
|---|
| 543 | std::wcerr << _T("Since no mode was specified assuming --exec (other options are --query and --submit)") << std::endl;
|
|---|
| 544 | }
|
|---|
| 545 | if (args.mode == client_arguments::query) {
|
|---|
| 546 | ret = mainClient.simple_query(args.module, args.command, args.arguments, resp);
|
|---|
| 547 | } else if (args.mode == client_arguments::exec || args.mode == client_arguments::combined) {
|
|---|
| 548 | ret = mainClient.simple_exec(args.module, args.command, args.arguments, resp);
|
|---|
| 549 | if (ret == NSCAPI::returnIgnored) {
|
|---|
| 550 | ret = 1;
|
|---|
| 551 | std::wcout << _T("Command not found (by module): ") << args.command << std::endl;
|
|---|
| 552 | resp.push_back(_T("Command not found: ") + args.command);
|
|---|
| 553 | mainClient.simple_exec(args.module, _T("help"), args.arguments, resp);
|
|---|
| 554 | } else if (args.mode == client_arguments::combined) {
|
|---|
| 555 | if (ret == NSCAPI::returnOK) {
|
|---|
| 556 | mainClient.reload(_T("service"));
|
|---|
| 557 | ret = mainClient.simple_query(args.module, args.combined_query, args.arguments, resp);
|
|---|
| 558 | } else {
|
|---|
| 559 | std::wcerr << _T("Failed to execute command, will not attempt query") << std::endl;
|
|---|
| 560 | }
|
|---|
| 561 | }
|
|---|
| 562 | } else if (args.mode == client_arguments::submit) {
|
|---|
| 563 | std::wcerr << _T("--submit is currently not supported (but you can use --exec submit which is technically the same)") << std::endl;
|
|---|
| 564 | } else {
|
|---|
| 565 | std::wcerr << _T("Need to specify one of --exec, --query or --submit") << std::endl;
|
|---|
| 566 | }
|
|---|
| 567 | mainClient.stop_unload_plugins_pre();
|
|---|
| 568 | mainClient.stop_exit_pre();
|
|---|
| 569 | mainClient.stop_exit_post();
|
|---|
| 570 |
|
|---|
| 571 | BOOST_FOREACH(std::wstring r, resp) {
|
|---|
| 572 | std::wcout << r << std::endl;
|
|---|
| 573 | }
|
|---|
| 574 | return ret;
|
|---|
| 575 | } catch(const std::exception & e) {
|
|---|
| 576 | std::wcerr << _T("Client: Unable to parse command line: ") << utf8::to_unicode(e.what()) << std::endl;
|
|---|
| 577 | return 1;
|
|---|
| 578 | } catch(...) {
|
|---|
| 579 | std::wcerr << _T("Client: Unable to parse command line: UNKNOWN") << std::endl;
|
|---|
| 580 | return 1;
|
|---|
| 581 | }
|
|---|
| 582 | }
|
|---|
| 583 | };
|
|---|
| 584 |
|
|---|
| 585 |
|
|---|
| 586 |
|
|---|
| 587 |
|
|---|
| 588 |
|
|---|