#ifndef BITCOIN_COMMON_ARGS_H
#define BITCOIN_COMMON_ARGS_H
#include <common/settings.h>
#include <compat/compat.h>
#include <sync.h>
#include <util/chaintype.h>
#include <util/fs.h>
#include <cstdint>
#include <iosfwd>
#include <list>
#include <map>
#include <optional>
#include <set>
#include <string>
#include <variant>
#include <vector>
class ArgsManager;
extern const char * const BITCOIN_CONF_FILENAME;
extern const char * const BITCOIN_SETTINGS_FILENAME;
bool CheckDataDirOption(const ArgsManager& args);
fs::path AbsPathForConfigVal(const ArgsManager& args, const fs::path& path, bool net_specific = true);
inline bool IsSwitchChar(char c)
{
#ifdef WIN32
return c == '-' || c == '/';
#else
return c == '-';
#endif
}
enum class OptionsCategory {
OPTIONS,
CONNECTION,
WALLET,
WALLET_DEBUG_TEST,
ZMQ,
DEBUG_TEST,
CHAINPARAMS,
NODE_RELAY,
BLOCK_CREATION,
RPC,
GUI,
COMMANDS,
REGISTER_COMMANDS,
CLI_COMMANDS,
IPC,
HIDDEN };
struct KeyInfo {
std::string name;
std::string section;
bool negated{false};
};
KeyInfo InterpretKey(std::string key);
std::optional<common::SettingsValue> InterpretValue(const KeyInfo& key, const std::string* value,
unsigned int flags, std::string& error);
struct SectionInfo {
std::string m_name;
std::string m_file;
int m_line;
};
std::string SettingToString(const common::SettingsValue&, const std::string&);
std::optional<std::string> SettingToString(const common::SettingsValue&);
int64_t SettingToInt(const common::SettingsValue&, int64_t);
std::optional<int64_t> SettingToInt(const common::SettingsValue&);
bool SettingToBool(const common::SettingsValue&, bool);
std::optional<bool> SettingToBool(const common::SettingsValue&);
class ArgsManager
{
public:
enum Flags : uint32_t {
ALLOW_ANY = 0x01, DISALLOW_NEGATION = 0x20, DISALLOW_ELISION = 0x40,
DEBUG_ONLY = 0x100,
NETWORK_ONLY = 0x200,
SENSITIVE = 0x400,
COMMAND = 0x800,
};
protected:
struct Arg
{
std::string m_help_param;
std::string m_help_text;
unsigned int m_flags;
};
mutable RecursiveMutex cs_args;
common::Settings m_settings GUARDED_BY(cs_args);
std::vector<std::string> m_command GUARDED_BY(cs_args);
std::string m_network GUARDED_BY(cs_args);
std::set<std::string> m_network_only_args GUARDED_BY(cs_args);
std::map<OptionsCategory, std::map<std::string, Arg>> m_available_args GUARDED_BY(cs_args);
bool m_accept_any_command GUARDED_BY(cs_args){true};
std::list<SectionInfo> m_config_sections GUARDED_BY(cs_args);
std::optional<fs::path> m_config_path GUARDED_BY(cs_args);
mutable fs::path m_cached_blocks_path GUARDED_BY(cs_args);
mutable fs::path m_cached_datadir_path GUARDED_BY(cs_args);
mutable fs::path m_cached_network_datadir_path GUARDED_BY(cs_args);
[[nodiscard]] bool ReadConfigStream(std::istream& stream, const std::string& filepath, std::string& error, bool ignore_invalid_keys = false);
bool UseDefaultSection(const std::string& arg) const EXCLUSIVE_LOCKS_REQUIRED(cs_args);
public:
common::SettingsValue GetSetting(const std::string& arg) const;
std::vector<common::SettingsValue> GetSettingsList(const std::string& arg) const;
ArgsManager();
~ArgsManager();
void SelectConfigNetwork(const std::string& network);
[[nodiscard]] bool ParseParameters(int argc, const char* const argv[], std::string& error);
fs::path GetConfigFilePath() const;
void SetConfigFilePath(fs::path);
[[nodiscard]] bool ReadConfigFiles(std::string& error, bool ignore_invalid_keys = false);
std::set<std::string> GetUnsuitableSectionOnlyArgs() const;
std::list<SectionInfo> GetUnrecognizedSections() const;
struct Command {
std::string command;
std::vector<std::string> args;
};
std::optional<const Command> GetCommand() const;
fs::path GetBlocksDirPath() const;
fs::path GetDataDirBase() const { return GetDataDir(false); }
fs::path GetDataDirNet() const { return GetDataDir(true); }
void ClearPathCache();
std::vector<std::string> GetArgs(const std::string& strArg) const;
bool IsArgSet(const std::string& strArg) const;
bool IsArgNegated(const std::string& strArg) const;
std::string GetArg(const std::string& strArg, const std::string& strDefault) const;
std::optional<std::string> GetArg(const std::string& strArg) const;
fs::path GetPathArg(std::string arg, const fs::path& default_value = {}) const;
int64_t GetIntArg(const std::string& strArg, int64_t nDefault) const;
std::optional<int64_t> GetIntArg(const std::string& strArg) const;
bool GetBoolArg(const std::string& strArg, bool fDefault) const;
std::optional<bool> GetBoolArg(const std::string& strArg) const;
bool SoftSetArg(const std::string& strArg, const std::string& strValue);
bool SoftSetBoolArg(const std::string& strArg, bool fValue);
void ForceSetArg(const std::string& strArg, const std::string& strValue);
ChainType GetChainType() const;
std::string GetChainTypeString() const;
void AddArg(const std::string& name, const std::string& help, unsigned int flags, const OptionsCategory& cat);
void AddCommand(const std::string& cmd, const std::string& help);
void AddHiddenArgs(const std::vector<std::string>& args);
void ClearArgs() {
LOCK(cs_args);
m_available_args.clear();
m_network_only_args.clear();
}
void CheckMultipleCLIArgs() const;
std::string GetHelpMessage() const;
std::optional<unsigned int> GetArgFlags(const std::string& name) const;
bool GetSettingsPath(fs::path* filepath = nullptr, bool temp = false, bool backup = false) const;
bool ReadSettingsFile(std::vector<std::string>* errors = nullptr);
bool WriteSettingsFile(std::vector<std::string>* errors = nullptr, bool backup = false) const;
common::SettingsValue GetPersistentSetting(const std::string& name) const;
template <typename Fn>
void LockSettings(Fn&& fn)
{
LOCK(cs_args);
fn(m_settings);
}
void LogArgs() const;
private:
fs::path GetDataDir(bool net_specific) const;
std::variant<ChainType, std::string> GetChainArg() const;
void logArgsPrefix(
const std::string& prefix,
const std::string& section,
const std::map<std::string, std::vector<common::SettingsValue>>& args) const;
};
extern ArgsManager gArgs;
bool HelpRequested(const ArgsManager& args);
void SetupHelpOptions(ArgsManager& args);
extern const std::vector<std::string> TEST_OPTIONS_DOC;
bool HasTestOption(const ArgsManager& args, const std::string& test_option);
std::string HelpMessageGroup(const std::string& message);
std::string HelpMessageOpt(const std::string& option, const std::string& message);
namespace common {
#ifdef WIN32
class WinCmdLineArgs
{
public:
WinCmdLineArgs();
~WinCmdLineArgs();
std::pair<int, char**> get();
private:
int argc;
char** argv;
std::vector<std::string> args;
};
#endif
}
#endif