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