Changeset View
Changeset View
Standalone View
Standalone View
src/util.cpp
Show First 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | |||||
#ifdef HAVE_SYS_PRCTL_H | #ifdef HAVE_SYS_PRCTL_H | ||||
#include <sys/prctl.h> | #include <sys/prctl.h> | ||||
#endif | #endif | ||||
#ifdef HAVE_MALLOPT_ARENA_MAX | #ifdef HAVE_MALLOPT_ARENA_MAX | ||||
#include <malloc.h> | #include <malloc.h> | ||||
#endif | #endif | ||||
#include <boost/algorithm/string/case_conv.hpp> // for to_lower() | |||||
#include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith() | |||||
#include <boost/program_options/detail/config_file.hpp> | #include <boost/program_options/detail/config_file.hpp> | ||||
#include <boost/thread.hpp> | #include <boost/thread.hpp> | ||||
#include <openssl/conf.h> | #include <openssl/conf.h> | ||||
#include <openssl/rand.h> | #include <openssl/rand.h> | ||||
// Application startup time (used for uptime calculation) | // Application startup time (used for uptime calculation) | ||||
const int64_t nStartupTime = GetTime(); | const int64_t nStartupTime = GetTime(); | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | ~CInit() { | ||||
CRYPTO_set_locking_callback(nullptr); | CRYPTO_set_locking_callback(nullptr); | ||||
for (int i = 0; i < CRYPTO_num_locks(); i++) { | for (int i = 0; i < CRYPTO_num_locks(); i++) { | ||||
delete ppmutexOpenSSL[i]; | delete ppmutexOpenSSL[i]; | ||||
} | } | ||||
OPENSSL_free(ppmutexOpenSSL); | OPENSSL_free(ppmutexOpenSSL); | ||||
} | } | ||||
} instance_of_cinit; | } instance_of_cinit; | ||||
/** Interpret string as boolean, for argument parsing */ | /** | ||||
* Interpret a string argument as a boolean. | |||||
* | |||||
* The definition of atoi() requires that non-numeric string values like "foo", | |||||
* return 0. This means that if a user unintentionally supplies a non-integer | |||||
* argument here, the return value is always false. This means that -foo=false | |||||
* does what the user probably expects, but -foo=true is well defined but does | |||||
* not do what they probably expected. | |||||
* | |||||
* The return value of atoi() is undefined when given input not representable as | |||||
* an int. On most systems this means string value between "-2147483648" and | |||||
* "2147483647" are well defined (this method will return true). Setting | |||||
* -txindex=2147483648 on most systems, however, is probably undefined. | |||||
* | |||||
* For a more extensive discussion of this topic (and a wide range of opinions | |||||
* on the Right Way to change this code), see PR12713. | |||||
*/ | |||||
static bool InterpretBool(const std::string &strValue) { | static bool InterpretBool(const std::string &strValue) { | ||||
if (strValue.empty()) { | if (strValue.empty()) { | ||||
return true; | return true; | ||||
} | } | ||||
return (atoi(strValue) != 0); | return (atoi(strValue) != 0); | ||||
} | } | ||||
/** Turn -noX into -X=0 */ | /** | ||||
static void InterpretNegativeSetting(std::string &strKey, | * Interpret -nofoo as if the user supplied -foo=0. | ||||
std::string &strValue) { | * | ||||
if (strKey.length() > 3 && strKey[0] == '-' && strKey[1] == 'n' && | * This method also tracks when the -no form was supplied, and treats "-foo" as | ||||
strKey[2] == 'o') { | * a negated option when this happens. This can be later checked using the | ||||
strKey = "-" + strKey.substr(3); | * IsArgNegated() method. One use case for this is to have a way to disable | ||||
strValue = InterpretBool(strValue) ? "0" : "1"; | * options that are not normally boolean (e.g. using -nodebuglogfile to request | ||||
* that debug log output is not sent to any file at all). | |||||
*/ | |||||
void ArgsManager::InterpretNegatedOption(std::string &key, std::string &val) { | |||||
if (key.substr(0, 3) == "-no") { | |||||
bool bool_val = InterpretBool(val); | |||||
if (!bool_val) { | |||||
// Double negatives like -nofoo=0 are supported (but discouraged) | |||||
LogPrintf( | |||||
"Warning: parsed potentially confusing double-negative %s=%s\n", | |||||
key, val); | |||||
} | |||||
key.erase(1, 2); | |||||
m_negated_args.insert(key); | |||||
val = bool_val ? "0" : "1"; | |||||
} else { | |||||
// In an invocation like "bitcoind -nofoo -foo" we want to unmark -foo | |||||
// as negated when we see the second option. | |||||
m_negated_args.erase(key); | |||||
} | } | ||||
} | } | ||||
void ArgsManager::ParseParameters(int argc, const char *const argv[]) { | void ArgsManager::ParseParameters(int argc, const char *const argv[]) { | ||||
LOCK(cs_args); | LOCK(cs_args); | ||||
mapArgs.clear(); | mapArgs.clear(); | ||||
mapMultiArgs.clear(); | mapMultiArgs.clear(); | ||||
m_negated_args.clear(); | |||||
for (int i = 1; i < argc; i++) { | for (int i = 1; i < argc; i++) { | ||||
std::string str(argv[i]); | std::string key(argv[i]); | ||||
std::string strValue; | std::string val; | ||||
size_t is_index = str.find('='); | size_t is_index = key.find('='); | ||||
if (is_index != std::string::npos) { | if (is_index != std::string::npos) { | ||||
strValue = str.substr(is_index + 1); | val = key.substr(is_index + 1); | ||||
str = str.substr(0, is_index); | key.erase(is_index); | ||||
} | } | ||||
#ifdef WIN32 | #ifdef WIN32 | ||||
boost::to_lower(str); | std::transform(key.begin(), key.end(), key.begin(), ::tolower); | ||||
if (boost::algorithm::starts_with(str, "/")) { | if (key[0] == '/') { | ||||
str = "-" + str.substr(1); | key[0] = '-'; | ||||
} | } | ||||
#endif | #endif | ||||
if (str[0] != '-') { | if (key[0] != '-') { | ||||
break; | break; | ||||
} | } | ||||
// Interpret --foo as -foo. | // Transform --foo to -foo | ||||
// If both --foo and -foo are set, the last takes effect. | if (key.length() > 1 && key[1] == '-') { | ||||
if (str.length() > 1 && str[1] == '-') { | key.erase(0, 1); | ||||
str = str.substr(1); | |||||
} | } | ||||
InterpretNegativeSetting(str, strValue); | |||||
mapArgs[str] = strValue; | // Transform -nofoo to -foo=0 | ||||
mapMultiArgs[str].push_back(strValue); | InterpretNegatedOption(key, val); | ||||
mapArgs[key] = val; | |||||
mapMultiArgs[key].push_back(val); | |||||
} | } | ||||
} | } | ||||
std::vector<std::string> ArgsManager::GetArgs(const std::string &strArg) const { | std::vector<std::string> ArgsManager::GetArgs(const std::string &strArg) const { | ||||
LOCK(cs_args); | LOCK(cs_args); | ||||
auto it = mapMultiArgs.find(strArg); | auto it = mapMultiArgs.find(strArg); | ||||
if (it != mapMultiArgs.end()) { | if (it != mapMultiArgs.end()) { | ||||
return it->second; | return it->second; | ||||
} | } | ||||
return {}; | return {}; | ||||
} | } | ||||
bool ArgsManager::IsArgSet(const std::string &strArg) const { | bool ArgsManager::IsArgSet(const std::string &strArg) const { | ||||
LOCK(cs_args); | LOCK(cs_args); | ||||
return mapArgs.count(strArg); | return mapArgs.count(strArg); | ||||
} | } | ||||
bool ArgsManager::IsArgNegated(const std::string &strArg) const { | |||||
LOCK(cs_args); | |||||
return m_negated_args.find(strArg) != m_negated_args.end(); | |||||
} | |||||
std::string ArgsManager::GetArg(const std::string &strArg, | std::string ArgsManager::GetArg(const std::string &strArg, | ||||
const std::string &strDefault) const { | const std::string &strDefault) const { | ||||
LOCK(cs_args); | LOCK(cs_args); | ||||
auto it = mapArgs.find(strArg); | auto it = mapArgs.find(strArg); | ||||
if (it != mapArgs.end()) { | if (it != mapArgs.end()) { | ||||
return it->second; | return it->second; | ||||
} | } | ||||
return strDefault; | return strDefault; | ||||
▲ Show 20 Lines • Show All 193 Lines • ▼ Show 20 Lines | if (!streamConfig.good()) { | ||||
for (boost::program_options::detail::config_file_iterator | for (boost::program_options::detail::config_file_iterator | ||||
it(streamConfig, setOptions), | it(streamConfig, setOptions), | ||||
end; | end; | ||||
it != end; ++it) { | it != end; ++it) { | ||||
// Don't overwrite existing settings so command line settings | // Don't overwrite existing settings so command line settings | ||||
// override bitcoin.conf | // override bitcoin.conf | ||||
std::string strKey = std::string("-") + it->string_key; | std::string strKey = std::string("-") + it->string_key; | ||||
std::string strValue = it->value[0]; | std::string strValue = it->value[0]; | ||||
InterpretNegativeSetting(strKey, strValue); | InterpretNegatedOption(strKey, strValue); | ||||
if (mapArgs.count(strKey) == 0) { | if (mapArgs.count(strKey) == 0) { | ||||
mapArgs[strKey] = strValue; | mapArgs[strKey] = strValue; | ||||
} | } | ||||
mapMultiArgs[strKey].push_back(strValue); | mapMultiArgs[strKey].push_back(strValue); | ||||
} | } | ||||
} | } | ||||
// If datadir is changed in .conf file: | // If datadir is changed in .conf file: | ||||
ClearDatadirCache(); | ClearDatadirCache(); | ||||
▲ Show 20 Lines • Show All 251 Lines • Show Last 20 Lines |