5#include <bitcoin-build-config.h>
21static constexpr auto HELP_USAGE = R
"(Usage: %s [OPTIONS] COMMAND...
24 -m, --multiprocess Run multiprocess binaries bitcoin-node, bitcoin-gui.
25 -M, --monolithic Run monolithic binaries bitcoind, bitcoin-qt. (Default behavior)
26 -v, --version Show version information
27 -h, --help Show full help message
30 gui [ARGS] Start GUI, equivalent to running 'bitcoin-qt [ARGS]' or 'bitcoin-gui [ARGS]'.
31 node [ARGS] Start node, equivalent to running 'bitcoind [ARGS]' or 'bitcoin-node [ARGS]'.
32 rpc [ARGS] Call RPC method, equivalent to running 'bitcoin-cli -named [ARGS]'.
33 wallet [ARGS] Call wallet command, equivalent to running 'bitcoin-wallet [ARGS]'.
34 tx [ARGS] Manipulate hex-encoded transactions, equivalent to running 'bitcoin-tx [ARGS]'.
35 help Show full help message.
39Additional less commonly used commands:
40 bench [ARGS] Run bench command, equivalent to running 'bench_bitcoin [ARGS]'.
41 chainstate [ARGS] Run bitcoin kernel chainstate util, equivalent to running 'bitcoin-chainstate [ARGS]'.
42 test [ARGS] Run unit tests, equivalent to running 'test_bitcoin [ARGS]'.
43 test-gui [ARGS] Run GUI unit tests, equivalent to running 'test_bitcoin-qt [ARGS]'.
47Run '%s help' to see additional commands (e.g. for testing and debugging).
55 std::vector<const char*>
args;
60static void ExecCommand(
const std::vector<const char*>&
args, std::string_view argv0);
62int main(
int argc,
char* argv[])
66 if (
cmd.show_version) {
72 std::vector<const char*>
args;
73 if (
cmd.show_help ||
cmd.command.empty()) {
82 }
else if (
cmd.command ==
"gui") {
84 }
else if (
cmd.command ==
"node") {
86 }
else if (
cmd.command ==
"rpc") {
87 args.emplace_back(
"bitcoin-cli");
94 args.emplace_back(
"-named");
95 }
else if (
cmd.command ==
"wallet") {
96 args.emplace_back(
"bitcoin-wallet");
97 }
else if (
cmd.command ==
"tx") {
98 args.emplace_back(
"bitcoin-tx");
99 }
else if (
cmd.command ==
"bench") {
100 args.emplace_back(
"bench_bitcoin");
101 }
else if (
cmd.command ==
"chainstate") {
102 args.emplace_back(
"bitcoin-chainstate");
103 }
else if (
cmd.command ==
"test") {
104 args.emplace_back(
"test_bitcoin");
105 }
else if (
cmd.command ==
"test-gui") {
106 args.emplace_back(
"test_bitcoin-qt");
107 }
else if (
cmd.command ==
"util") {
108 args.emplace_back(
"bitcoin-util");
110 throw std::runtime_error(
strprintf(
"Unrecognized command: '%s'",
cmd.command));
116 }
catch (
const std::exception& e) {
117 tfm::format(std::cerr,
"Error: %s\nTry '%s --help' for more information.\n", e.what(), argv[0]);
126 cmd.args.reserve(argc);
127 for (
int i = 1; i < argc; ++i) {
128 std::string_view arg = argv[i];
129 if (!
cmd.command.empty()) {
130 cmd.args.emplace_back(argv[i]);
131 }
else if (arg ==
"-m" || arg ==
"--multiprocess") {
132 cmd.use_multiprocess =
true;
133 }
else if (arg ==
"-M" || arg ==
"--monolithic") {
134 cmd.use_multiprocess =
false;
135 }
else if (arg ==
"-v" || arg ==
"--version") {
136 cmd.show_version =
true;
137 }
else if (arg ==
"-h" || arg ==
"--help" || arg ==
"help") {
138 cmd.show_help =
true;
139 }
else if (arg.starts_with(
"-")) {
140 throw std::runtime_error(
strprintf(
"Unknown option: %s", arg));
141 }
else if (!arg.empty()) {
152 if (
cmd.use_multiprocess)
return *
cmd.use_multiprocess;
156 std::string error_message;
158 argv.insert(argv.begin(),
nullptr);
160 tfm::format(std::cerr,
"Warning: failed to parse subcommand command line options: %s\n", error_message);
163 tfm::format(std::cerr,
"Warning: failed to parse subcommand config: %s\n", error_message);
190static void ExecCommand(
const std::vector<const char*>&
args, std::string_view wrapper_argv0)
193 std::vector<const char*> exec_args{
args};
194 exec_args.emplace_back(
nullptr);
197 auto try_exec = [&](fs::path exe_path,
bool allow_notfound =
true) {
199 exec_args[0] = exe_path_str.c_str();
200 if (
util::ExecVp(exec_args[0], (
char*
const*)exec_args.data()) == -1) {
201 if (allow_notfound && errno == ENOENT)
return false;
202 throw std::system_error(errno, std::system_category(),
strprintf(
"execvp failed to execute '%s'", exec_args[0]));
204 throw std::runtime_error(
"execvp returned unexpectedly");
212 fs::path wrapper_dir{fs::weakly_canonical(wrapper_path, ec)};
213 if (wrapper_dir.empty()) wrapper_dir = wrapper_path;
214 wrapper_dir = wrapper_dir.parent_path();
224 const bool fallback_os_search{!
fs::PathFromString(std::string{wrapper_argv0}).has_parent_path()};
228 (wrapper_dir.filename() ==
"bin" && try_exec(fs::path{wrapper_dir.parent_path()} /
"libexec" / arg0.filename())) ||
231 (!wrapper_dir.empty() && try_exec(wrapper_dir /
"daemon" / arg0.filename())) ||
234 (!wrapper_dir.empty() && try_exec(wrapper_dir / arg0.filename(), fallback_os_search)) ||
236 (fallback_os_search && try_exec(arg0.filename(),
false));
int main(int argc, char *argv[])
static constexpr auto HELP_FULL
static constexpr auto HELP_SHORT
static void ExecCommand(const std::vector< const char * > &args, std::string_view argv0)
Execute the specified bitcoind, bitcoin-qt or other command line in args using src,...
const TranslateFn G_TRANSLATION_FUN
Translate string to current locale using Qt.
bool UseMultiprocess(const CommandLine &cmd)
static constexpr auto HELP_USAGE
CommandLine ParseCommandLine(int argc, char *argv[])
@ ALLOW_ANY
disable validation
std::string GetChainTypeString() const
Returns the appropriate chain type string from the program arguments.
bool ParseParameters(int argc, const char *const argv[], std::string &error)
void SetDefaultFlags(std::optional< unsigned int >)
Set default flags to return for an unknown arg.
void SelectConfigNetwork(const std::string &network)
Select the network in use.
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
bool ReadConfigFiles(std::string &error, bool ignore_invalid_keys=false)
std::string FormatFullVersion()
std::string LicenseInfo()
Returns licensing information (for -version)
static std::string PathToString(const path &path)
Convert path object to a byte string.
static path PathFromString(const std::string &string)
Convert byte string to path object.
int ExecVp(const char *file, char *const argv[])
Cross-platform wrapper for POSIX execvp function.
fs::path GetExePath(std::string_view argv0)
Return path to current executable assuming it was invoked with argv0.
std::vector< const char * > args
std::optional< bool > use_multiprocess
std::function< std::string(const char *)> TranslateFn
Translate a message to the native language of the user.
std::string FormatParagraph(std::string_view in, size_t width, size_t indent)
Format a paragraph of text to a fixed width, adding spaces for indentation to any added line.