/* Local functions definitions */ void parse_service_options(int argc, LPTSTR* argv, service_configuration& configuration) { namespace po = boost::program_options; po::options_description service_options("Service options"); service_options.add_options() ("configuration_file,c", po::value<std::string>()->default_value((get_configuration_directory() / "freelan.cfg").string()), "The configuration file to use.") ("debug,d", "Enables debug output.") ("threads,t", po::value<unsigned int>(&configuration.thread_count)->default_value(0), "The number of threads to use.") ("log_file,l", po::value<std::string>(), "The log file to use.") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, service_options), vm); po::notify(vm); const fs::path installation_directory = get_installation_directory(); if (vm.count("configuration_file")) { configuration.configuration_file = fs::absolute(vm["configuration_file"].as<std::string>(), installation_directory); } configuration.debug = (vm.count("debug") > 0); if (vm.count("log_file")) { configuration.log_file = fs::absolute(vm["log_file"].as<std::string>(), installation_directory); } else { configuration.log_file = installation_directory / "log" / "freelan.log"; } }
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; }
void parse_config(char *name, char *parameter) { #ifdef CONFDIR char *default_config_file=CONFDIR "/stunnel.conf"; #else char *default_config_file="stunnel.conf"; #endif FILE *fp; char line[STRLEN], *arg, *opt, *errstr, *filename; int line_number, i; LOCAL_OPTIONS *section, *new_section; memset(&options, 0, sizeof(GLOBAL_OPTIONS)); /* reset global options */ memset(&local_options, 0, sizeof(LOCAL_OPTIONS)); /* reset local options */ local_options.next=NULL; section=&local_options; global_options(CMD_INIT, NULL, NULL); service_options(CMD_INIT, section, NULL, NULL); if(!name) name=default_config_file; if(!strcasecmp(name, "-help")) { global_options(CMD_HELP, NULL, NULL); service_options(CMD_HELP, section, NULL, NULL); exit(1); } if(!strcasecmp(name, "-version")) { log_raw("%s", stunnel_info()); log_raw(" "); global_options(CMD_DEFAULT, NULL, NULL); service_options(CMD_DEFAULT, section, NULL, NULL); exit(1); } if(!strcasecmp(name, "-sockets")) { print_socket_options(); exit(1); } #ifndef USE_WIN32 if(!strcasecmp(name, "-fd")) { if(!parameter) { log_raw("No file descriptor specified"); syntax(default_config_file); } for(arg=parameter, i=0; *arg; arg++) { if(*arg<'0' || *arg>'9') { log_raw("Invalid file descriptor %s", parameter); syntax(default_config_file); } i=10*i+*arg-'0'; } fp=fdopen(i, "r"); if(!fp) { log_raw("Invalid file descriptor %s", parameter); syntax(default_config_file); } filename="descriptor"; } else #endif { fp=fopen(name, "r"); if(!fp) { #ifdef USE_WIN32 /* Win32 doesn't seem to set errno in fopen() */ log_raw("Failed to open configuration file %s", name); #else ioerror(name); #endif syntax(default_config_file); } filename=name; } line_number=0; while(fgets(line, STRLEN, fp)) { line_number++; opt=line; while(isspace(*opt)) opt++; /* remove initial whitespaces */ for(i=strlen(opt)-1; i>=0 && isspace(opt[i]); i--) opt[i]='\0'; /* remove trailing whitespaces */ if(opt[0]=='\0' || opt[0]=='#') /* empty line or comment */ continue; if(opt[0]=='[' && opt[strlen(opt)-1]==']') { /* new section */ errstr=section_validate(section); if(errstr) { log_raw("file %s line %d: %s", filename, line_number, errstr); exit(1); } opt++; opt[strlen(opt)-1]='\0'; new_section=calloc(1, sizeof(LOCAL_OPTIONS)); if(!new_section) { log_raw("Fatal memory allocation error"); exit(2); } memcpy(new_section, &local_options, sizeof(LOCAL_OPTIONS)); new_section->servname=stralloc(opt); new_section->next=NULL; section->next=new_section; section=new_section; continue; } arg=strchr(line, '='); if(!arg) { log_raw("file %s line %d: No '=' found", filename, line_number); exit(1); } *arg++='\0'; /* split into option name and argument value */ for(i=strlen(opt)-1; i>=0 && isspace(opt[i]); i--) opt[i]='\0'; /* remove trailing whitespaces */ while(isspace(*arg)) arg++; /* remove initial whitespaces */ errstr=service_options(CMD_EXEC, section, opt, arg); if(section==&local_options && errstr==option_not_found) errstr=global_options(CMD_EXEC, opt, arg); if(errstr) { log_raw("file %s line %d: %s", filename, line_number, errstr); exit(1); } } errstr=section_validate(section); if(errstr) { log_raw("file %s line %d: %s", filename, line_number, errstr); exit(1); } fclose(fp); if(!local_options.next && section->option.accept) { log_raw("accept option is not allowed in inetd mode"); log_raw("remove accept option or define a [section]"); exit(1); } if(!options.option.client) options.option.cert=1; /* Server always needs a certificate */ if(!options.option.foreground) options.option.syslog=1; }