util: Report parse errors in configuration file

Report errors while parsing the configuration file, instead of silently
ignoring them.

    $ src/bitcoind -regtest
    Error reading configuration file: parse error on line 22: nodebuglogfile, if you intended to specify a negated option, use nodebuglogfile=1 instead
    $ src/bitcoind -regtest
    Error reading configuration file: parse error on line 22: sdafsdfafs
    $ src/bitcoind -regtest
    Error reading configuration file: parse error on line 24: -nodebuglogfile=1, options in the configuration file must be specified without leading -

Github-Pull: #14105
Rebased-From: a66c0f78a9
Tree-SHA512: 2b6be1ab643623e6ef9b53354820147a6c5d2baae3795ffe428fc60d8563ec00a68a379aee4029380f80f892abe23763afb1c75c32b60a13bffe7b82496bf2bb
This commit is contained in:
Wladimir J. van der Laan 2018-08-30 13:04:19 +02:00
parent 6ba1f15432
commit 83aafd5b32
No known key found for this signature in database
GPG key ID: 1E4AED62986CD25D

View file

@ -820,11 +820,11 @@ static std::string TrimString(const std::string& str, const std::string& pattern
return str.substr(front, end - front + 1);
}
static std::vector<std::pair<std::string, std::string>> GetConfigOptions(std::istream& stream)
static bool GetConfigOptions(std::istream& stream, std::string& error, std::vector<std::pair<std::string, std::string>> &options)
{
std::vector<std::pair<std::string, std::string>> options;
std::string str, prefix;
std::string::size_type pos;
int linenr = 1;
while (std::getline(stream, str)) {
if ((pos = str.find('#')) != std::string::npos) {
str = str.substr(0, pos);
@ -834,21 +834,34 @@ static std::vector<std::pair<std::string, std::string>> GetConfigOptions(std::is
if (!str.empty()) {
if (*str.begin() == '[' && *str.rbegin() == ']') {
prefix = str.substr(1, str.size() - 2) + '.';
} else if (*str.begin() == '-') {
error = strprintf("parse error on line %i: %s, options in configuration file must be specified without leading -", linenr, str);
return false;
} else if ((pos = str.find('=')) != std::string::npos) {
std::string name = prefix + TrimString(str.substr(0, pos), pattern);
std::string value = TrimString(str.substr(pos + 1), pattern);
options.emplace_back(name, value);
} else {
error = strprintf("parse error on line %i: %s", linenr, str);
if (str.size() >= 2 && str.substr(0, 2) == "no") {
error += strprintf(", if you intended to specify a negated option, use %s=1 instead", str);
}
return false;
}
}
++linenr;
}
return options;
return true;
}
bool ArgsManager::ReadConfigStream(std::istream& stream, std::string& error, bool ignore_invalid_keys)
{
LOCK(cs_args);
for (const std::pair<std::string, std::string>& option : GetConfigOptions(stream)) {
std::vector<std::pair<std::string, std::string>> options;
if (!GetConfigOptions(stream, error, options)) {
return false;
}
for (const std::pair<std::string, std::string>& option : options) {
std::string strKey = std::string("-") + option.first;
std::string strValue = option.second;