bool parse_options(fscp::logger& logger, int argc, char** argv, cli_configuration& configuration) { namespace po = boost::program_options; po::options_description visible_options; po::options_description all_options; po::options_description generic_options("Generic options"); generic_options.add_options() ("help,h", "Produce help message.") ("version,v", "Get the program version.") ("debug,d", "Enables debug output.") ("threads,t", po::value<unsigned int>(&configuration.thread_count)->default_value(0), "The number of threads to use.") ("configuration_file,c", po::value<std::string>(), "The configuration file to use.") ; visible_options.add(generic_options); all_options.add(generic_options); po::options_description configuration_options("Configuration"); configuration_options.add(get_server_options()); configuration_options.add(get_client_options()); configuration_options.add(get_fscp_options()); configuration_options.add(get_security_options()); configuration_options.add(get_tap_adapter_options()); configuration_options.add(get_switch_options()); configuration_options.add(get_router_options()); visible_options.add(configuration_options); all_options.add(configuration_options); #ifdef WINDOWS po::options_description service_options("Service"); service_options.add_options() ("install", "Install the service.") ("uninstall", "Uninstall the service.") ("reinstall", "Reinstall the service.") ; visible_options.add(service_options); all_options.add(service_options); #else po::options_description daemon_options("Daemon"); daemon_options.add_options() ("foreground,f", "Do not run as a daemon.") ("pid_file,p", po::value<std::string>(), "A pid file to use.") ; visible_options.add(daemon_options); all_options.add(daemon_options); po::options_description misc_options("Miscellaneous"); misc_options.add_options() ("nocolor", "Disable color output.") ; visible_options.add(misc_options); all_options.add(misc_options); #endif po::variables_map vm; po::store(po::parse_command_line(argc, argv, all_options), vm); make_paths_absolute(vm, fs::current_path()); if (vm.count("help")) { std::cout << visible_options << std::endl; return false; } if (vm.count("version")) { std::cout << FREELAN_NAME << " " << FREELAN_VERSION_STRING << " " << FREELAN_DATE << std::endl; return false; } #ifdef WINDOWS if (vm.count("install")) { if (vm.count("uninstall")) { throw std::runtime_error("Cannot specify both --install and --uninstall options. Use --reinstall instead."); } else { if (windows::install_service()) { logger(fscp::log_level::important) << "Service installed."; } else { logger(fscp::log_level::error) << "The service was already installed."; } return false; } } else if (vm.count("uninstall")) { if (windows::uninstall_service()) { logger(fscp::log_level::important) << "Service uninstalled."; } else { logger(fscp::log_level::error) << "The service has already been deleted."; } return false; } else if (vm.count("reinstall")) { if (windows::uninstall_service()) { logger(fscp::log_level::important) << "Service uninstalled."; } else { logger(fscp::log_level::error) << "The service has already been deleted."; } if (windows::install_service()) { logger(fscp::log_level::important) << "Service installed."; } else { logger(fscp::log_level::error) << "The service was already installed."; } return false; } #else configuration.foreground = (vm.count("foreground") > 0); if (vm.count("nocolor") > 0) { // This is a global variable. Not really nice but does its job in this case. DISABLE_COLOR = true; } if (vm.count("pid_file")) { configuration.pid_file = fs::absolute(vm["pid_file"].as<std::string>()); } else { char* val = getenv("FREELAN_PID_FILE"); if (val) { configuration.pid_file = fs::absolute(std::string(val)); } } #endif fs::path configuration_file; if (vm.count("configuration_file")) { configuration_file = fs::absolute(vm["configuration_file"].as<std::string>()); } else { #ifdef _MSC_VER #ifdef UNICODE std::wstring value(4096, L'\0'); const DWORD value_size = GetEnvironmentVariable(L"FREELAN_CONFIGURATION_FILE", &value[0], static_cast<DWORD>(value.size())); #else std::string value(4096, '\0'); const DWORD value_size = GetEnvironmentVariable("FREELAN_CONFIGURATION_FILE", &value[0], static_cast<DWORD>(value.size())); #endif if (value_size > 0) { value.resize(value_size); configuration_file = fs::absolute(value); } #else const char* val = getenv("FREELAN_CONFIGURATION_FILE"); if (val) { configuration_file = fs::absolute(std::string(val)); } #endif } if (!configuration_file.empty()) { logger(fscp::log_level::information) << "Reading configuration file at: " << configuration_file; fs::basic_ifstream<char> ifs(configuration_file); if (!ifs) { throw po::reading_file(configuration_file.string().c_str()); } po::store(po::parse_config_file(ifs, configuration_options, true), vm); } else { bool configuration_read = false; const std::vector<fs::path> configuration_files = get_configuration_files(); BOOST_FOREACH(const fs::path& conf, configuration_files) { fs::basic_ifstream<char> ifs(conf); if (ifs) { logger(fscp::log_level::information) << "Reading configuration file at: " << conf << std::endl; po::store(po::parse_config_file(ifs, configuration_options, true), vm); configuration_file = fs::absolute(conf); configuration_read = true; break; } } if (!configuration_read) { logger(fscp::log_level::warning) << "Warning ! No configuration file specified and none found in the environment."; logger(fscp::log_level::warning) << "Looked up locations were:"; for (auto&& conf : configuration_files) { logger(fscp::log_level::warning) << "- " << conf; } } }
bool parse_options(int argc, char** argv, cli_configuration& configuration) { namespace po = boost::program_options; po::options_description visible_options; po::options_description all_options; po::options_description generic_options("Generic options"); generic_options.add_options() ("help,h", "Produce help message.") ("debug,d", "Enables debug output.") ("configuration_file,c", po::value<std::string>(), "The configuration file to use") ; visible_options.add(generic_options); all_options.add(generic_options); po::options_description configuration_options("Configuration"); configuration_options.add(get_server_options()); configuration_options.add(get_fscp_options()); configuration_options.add(get_security_options()); configuration_options.add(get_tap_adapter_options()); configuration_options.add(get_switch_options()); visible_options.add(configuration_options); all_options.add(configuration_options); #ifdef WINDOWS po::options_description service_options("Service"); service_options.add_options() ("install", "Install the service.") ("uninstall", "Uninstall the service.") ("reinstall", "Reinstall the service.") ; visible_options.add(service_options); all_options.add(service_options); #else po::options_description daemon_options("Daemon"); daemon_options.add_options() ("foreground,f", "Do not run as a daemon.") ("pid_file,p", po::value<std::string>(), "A pid file to use.") ; visible_options.add(daemon_options); all_options.add(daemon_options); #endif po::variables_map vm; po::store(po::parse_command_line(argc, argv, all_options), vm); if (vm.count("help")) { std::cout << visible_options << std::endl; return false; } #ifdef WINDOWS if (vm.count("install")) { if (vm.count("uninstall")) { throw std::runtime_error("Cannot specify both --install and --uninstall options. Use --reinstall instead."); } else { if (win32::install_service()) { std::cout << "Service installed." << std::endl; } else { std::cerr << "The service was already installed." << std::endl; } return false; } } else if (vm.count("uninstall")) { if (win32::uninstall_service()) { std::cout << "Service uninstalled." << std::endl; } else { std::cerr << "The service has already been deleted." << std::endl; } return false; } else if (vm.count("reinstall")) { if (win32::uninstall_service()) { std::cout << "Service uninstalled." << std::endl; } else { std::cerr << "The service has already been deleted." << std::endl; } if (win32::install_service()) { std::cout << "Service installed." << std::endl; } else { std::cerr << "The service was already installed." << std::endl; } return false; } #else configuration.foreground = (vm.count("foreground") > 0); if (vm.count("pid_file")) { configuration.pid_file = fs::absolute(vm["pid_file"].as<std::string>()); } else { char* val = getenv("FREELAN_PID_FILE"); if (val) { configuration.pid_file = fs::absolute(std::string(val)); } } #endif fs::path configuration_file; if (vm.count("configuration_file")) { configuration_file = fs::absolute(vm["configuration_file"].as<std::string>()); } else { char* val = getenv("FREELAN_CONFIGURATION_FILE"); if (val) { configuration_file = fs::absolute(std::string(val)); } } if (!configuration_file.empty()) { std::cout << "Reading configuration file at: " << configuration_file << std::endl; fs::basic_ifstream<char> ifs(configuration_file); if (!ifs) { throw po::reading_file(configuration_file.string().c_str()); } po::store(po::parse_config_file(ifs, configuration_options, true), vm); } else { bool configuration_read = false; const std::vector<fs::path> configuration_files = get_configuration_files(); BOOST_FOREACH(const fs::path& conf, configuration_files) { fs::basic_ifstream<char> ifs(conf); if (ifs) { std::cout << "Reading configuration file at: " << conf << std::endl; po::store(po::parse_config_file(ifs, configuration_options, true), vm); configuration_file = fs::absolute(conf); break; } } if (!configuration_read) { std::cerr << "Warning ! No configuration file specified and none found in the environment." << std::endl; std::cerr << "Looked up locations were:" << std::endl; BOOST_FOREACH(const fs::path& conf, configuration_files) { std::cerr << "- " << conf << std::endl; }