From 64e5114947c12562acb068fc68b9db24ff213749 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Sat, 16 Apr 2022 21:50:23 +0200 Subject: [PATCH] allow to read environment variables as config parameters Environment variables must be prefixed with winix_ to be loaded by winix. The winix_ prefix is then removed and the key value converted to lowercase. Sample: evn WINIX_MY_OPTION=TEST123test winix -c config_file This will add my_option to the config with value TEST123test. Environment variables are read last so they will overwrite the values from the configuration files. --- winixd/core/config.cpp | 8 +++-- winixd/core/config.h | 2 ++ winixd/main/main.cpp | 81 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 82 insertions(+), 9 deletions(-) diff --git a/winixd/core/config.cpp b/winixd/core/config.cpp index 523624c..8ae17c7 100644 --- a/winixd/core/config.cpp +++ b/winixd/core/config.cpp @@ -95,8 +95,6 @@ bool Config::ReadConfig(const std::wstring & config_file) if( status == pt::SpaceParser::ok ) { - AssignValues(); - SetAdditionalVariables(); return true; } else @@ -107,6 +105,12 @@ bool Config::ReadConfig(const std::wstring & config_file) } +void Config::AssignValuesFromSpace() +{ + AssignValues(); + SetAdditionalVariables(); +} + void Config::AssignValues() diff --git a/winixd/core/config.h b/winixd/core/config.h index c492186..bdbe69a 100644 --- a/winixd/core/config.h +++ b/winixd/core/config.h @@ -854,6 +854,8 @@ public: Config(); bool ReadConfig(const std::wstring & config_file); + void AssignValuesFromSpace(); + /* * diff --git a/winixd/main/main.cpp b/winixd/main/main.cpp index a4f86db..8aee640 100644 --- a/winixd/main/main.cpp +++ b/winixd/main/main.cpp @@ -47,6 +47,7 @@ + namespace Winix { @@ -67,11 +68,22 @@ void print_syntax() std::cout << "Usage: winix [options]" << std::endl; std::cout << " -c : a path to the config file" << std::endl; std::cout << " --config : a path to the config file" << std::endl; + std::cout << " --use-env : allow to use environment variables" << std::endl; + std::cout << " --dump-config : dump all read config options to stdout and exit" << std::endl; std::cout << " -h : print usage information" << std::endl; std::cout << " --help : print usage information" << std::endl; std::cout << " -? : print usage information" << std::endl; + std::cout << std::endl; std::cout << "At least one -c or --config parameter is required, use -c or --config option" << std::endl; std::cout << "multiple times to load more than one config." << std::endl; + std::cout << std::endl; + std::cout << "Environment variables must be prefixed with winix_ to be loaded by winix." << std::endl; + std::cout << "The winix_ prefix is then removed and the key value converted to lowercase." << std::endl; + std::cout << "Sample:" << std::endl; + std::cout << "evn WINIX_MY_OPTION=TEST123test winix -c config_file" << std::endl; + std::cout << "This will add my_option to the config with value TEST123test." << std::endl; + std::cout << "Environment variables are read last so they will overwrite the values" << std::endl; + std::cout << "from the configuration files." << std::endl; } @@ -179,7 +191,42 @@ bool ReadConfigs(const pt::Space::TableType & table, size_t & config_read) } -bool ReadConfigs(const pt::Space & options) +void ReadEnvOption(const char * option) +{ + const char winix_prefix[] = "winix_"; + size_t prefix_len = sizeof(winix_prefix) - 1; // null terminating table + std::wstring opt, val; + + if( pt::is_substr_nc(winix_prefix, option) ) + { + pt::utf8_to_wide(option + prefix_len, opt); + + std::wstring::size_type sep = opt.find('='); + + if( sep != std::wstring::npos ) + { + val = opt.substr(sep + 1); + opt.erase(sep); + } + + TemplatesFunctions::locale.ToSmall(opt); + app.config.space.add(opt, val); + } +} + + +void ReadConfigFromEnv(const char ** env) +{ + for(size_t i = 0 ; env[i] ; ++i) + { + ReadEnvOption(env[i]); + } +} + + + + +bool ReadConfigs(const pt::Space & options, const char ** env) { size_t config_read = 0; bool status = true; @@ -205,6 +252,13 @@ bool ReadConfigs(const pt::Space & options) return false; } + if( options.has_key(L"use-env") ) + { + ReadConfigFromEnv(env); + } + + app.config.AssignValuesFromSpace(); + return status; } @@ -212,7 +266,7 @@ bool ReadConfigs(const pt::Space & options) -int main(int argc, const char ** argv) +int main(int argc, const char ** argv, const char ** env) { using Winix::app; @@ -241,22 +295,35 @@ using Winix::app; } Winix::Log & log = app.GetMainLog(); + pt::WTextStream * log_buffer = log.get_log_buffer(); Winix::LogInfo(log, Winix::log3, "UTC booting Winix", true, ""); // date will be printed as UTC because the time zones are not loaded yet - if( !Winix::ReadConfigs(options) ) + if( !Winix::ReadConfigs(options, env) ) { // we need to print the buffer by hand because the logger // is not fully initialized yet - pt::WTextStream * buffer = log.get_log_buffer(); - - if( buffer && !buffer->empty() ) + if( log_buffer && !log_buffer->empty() ) { - pt::wide_stream_to_utf8(*buffer, std::cout); + pt::wide_stream_to_utf8(*log_buffer, std::cout); } return 2; } + if( options.has_key(L"dump-config") ) + { + if( log_buffer ) + { + log << "all read config options (some of the values could have been modified by winix" + << " but the modified values are not printed here):" << Winix::logend; + app.config.space.serialize_to_space_stream(*log_buffer, true); + log << Winix::logend; + pt::wide_stream_to_utf8(*log_buffer, std::cout); + } + + return 0; + } + app.InitLoggers(); if( app.stdout_is_closed || app.config.demonize )