Skip to content

Commit

Permalink
-includeconf=<path> support in config handler, for including external…
Browse files Browse the repository at this point in the history
… configuration files. Fixes bitcoin#10071
  • Loading branch information
kallewoof authored and jnewbery committed Mar 20, 2018
1 parent 4ba3d4f commit 64e5d80
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 17 deletions.
2 changes: 1 addition & 1 deletion src/bitcoin-cli.cpp
Expand Up @@ -106,7 +106,7 @@ static int AppInitRPC(int argc, char* argv[])
return EXIT_FAILURE;
}
try {
gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME));
gArgs.ReadConfigFiles();
} catch (const std::exception& e) {
fprintf(stderr,"Error reading configuration file: %s\n", e.what());
return EXIT_FAILURE;
Expand Down
2 changes: 1 addition & 1 deletion src/bitcoind.cpp
Expand Up @@ -95,7 +95,7 @@ bool AppInit(int argc, char* argv[])
}
try
{
gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME));
gArgs.ReadConfigFiles();
} catch (const std::exception& e) {
fprintf(stderr,"Error reading configuration file: %s\n", e.what());
return false;
Expand Down
2 changes: 1 addition & 1 deletion src/qt/bitcoin.cpp
Expand Up @@ -626,7 +626,7 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
try {
gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME));
gArgs.ReadConfigFiles();
} catch (const std::exception& e) {
QMessageBox::critical(0, QObject::tr(PACKAGE_NAME),
QObject::tr("Error: Cannot parse configuration file: %1. Only use key=value syntax.").arg(e.what()));
Expand Down
47 changes: 34 additions & 13 deletions src/util.cpp
Expand Up @@ -649,26 +649,47 @@ fs::path GetConfigFile(const std::string& confPath)
return AbsPathForConfigVal(fs::path(confPath), false);
}

void ArgsManager::ReadConfigFile(const std::string& confPath)
void ArgsManager::ReadConfigFile(fs::ifstream& streamConfig)
{
std::set<std::string> setOptions;
setOptions.insert("*");

for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it) {
// Don't overwrite existing settings so command line settings override bitcoin.conf
std::string strKey = std::string("-") + it->string_key;
std::string strValue = it->value[0];
InterpretNegativeSetting(strKey, strValue);
if (mapArgs.count(strKey) == 0) {
mapArgs[strKey] = strValue;
}
mapMultiArgs[strKey].push_back(strValue);
}
}

void ArgsManager::ReadConfigFiles()
{
const std::string confPath = GetArg("-conf", BITCOIN_CONF_FILENAME);
fs::ifstream streamConfig(GetConfigFile(confPath));
if (!streamConfig.good())
return; // No bitcoin.conf file is OK

// we do not allow -includeconf from command line, so we clear it here
mapArgs.erase("-includeconf");

std::string includeconf;
{
LOCK(cs_args);
std::set<std::string> setOptions;
setOptions.insert("*");

for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
{
// Don't overwrite existing settings so command line settings override bitcoin.conf
std::string strKey = std::string("-") + it->string_key;
std::string strValue = it->value[0];
InterpretNegativeSetting(strKey, strValue);
if (mapArgs.count(strKey) == 0)
mapArgs[strKey] = strValue;
mapMultiArgs[strKey].push_back(strValue);
ReadConfigFile(streamConfig);
if (mapArgs.count("-includeconf")) includeconf = mapArgs["-includeconf"];
}
if (includeconf != "") {
LogPrintf("Attempting to include configuration file %s\n", includeconf.c_str());
fs::ifstream includeConfig(GetConfigFile(includeconf));
if (includeConfig.good()) {
LOCK(cs_args);
ReadConfigFile(includeConfig);
} else {
LogPrintf("Failed to include configuration file %s\n", includeconf.c_str());
}
}
// If datadir is changed in .conf file:
Expand Down
4 changes: 3 additions & 1 deletion src/util.h
Expand Up @@ -218,13 +218,15 @@ inline bool IsSwitchChar(char c)

class ArgsManager
{
private:
void ReadConfigFile(fs::ifstream& streamConfig);
protected:
mutable CCriticalSection cs_args;
std::map<std::string, std::string> mapArgs;
std::map<std::string, std::vector<std::string>> mapMultiArgs;
public:
void ParseParameters(int argc, const char*const argv[]);
void ReadConfigFile(const std::string& confPath);
void ReadConfigFiles();

/**
* Return a vector of strings of the given argument
Expand Down

0 comments on commit 64e5d80

Please sign in to comment.