5#include <bitcoin-build-config.h>
22static constexpr auto HELP_USAGE = R
"(Usage: %s [OPTIONS] COMMAND...
25 -m, --multiprocess Run multiprocess binaries bitcoin-node, bitcoin-gui.
26 -M, --monolithic Run monolithic binaries bitcoind, bitcoin-qt. (Default behavior)
27 -v, --version Show version information
28 -h, --help Show full help message
31 gui [ARGS] Start GUI, equivalent to running 'bitcoin-qt [ARGS]' or 'bitcoin-gui [ARGS]'.
32 node [ARGS] Start node, equivalent to running 'bitcoind [ARGS]' or 'bitcoin-node [ARGS]'.
33 rpc [ARGS] Call RPC method, equivalent to running 'bitcoin-cli -named [ARGS]'.
34 wallet [ARGS] Call wallet command, equivalent to running 'bitcoin-wallet [ARGS]'.
35 tx [ARGS] Manipulate hex-encoded transactions, equivalent to running 'bitcoin-tx [ARGS]'.
36 help Show full help message.
40Additional less commonly used commands:
41 bench [ARGS] Run bench command, equivalent to running 'bench_bitcoin [ARGS]'.
42 chainstate [ARGS] Run bitcoin kernel chainstate util, equivalent to running 'bitcoin-chainstate [ARGS]'.
43 test [ARGS] Run unit tests, equivalent to running 'test_bitcoin [ARGS]'.
44 test-gui [ARGS] Run GUI unit tests, equivalent to running 'test_bitcoin-qt [ARGS]'.
48Run '%s help' to see additional commands (e.g. for testing and debugging).
56 std::vector<const char*>
args;
61static void ExecCommand(
const std::vector<const char*>&
args, std::string_view argv0);
63int main(
int argc,
char* argv[])
69 if (
cmd.show_version) {
75 std::vector<const char*>
args;
76 if (
cmd.show_help ||
cmd.command.empty()) {
85 }
else if (
cmd.command ==
"gui") {
87 }
else if (
cmd.command ==
"node") {
89 }
else if (
cmd.command ==
"rpc") {
90 args.emplace_back(
"bitcoin-cli");
97 args.emplace_back(
"-named");
98 }
else if (
cmd.command ==
"wallet") {
99 args.emplace_back(
"bitcoin-wallet");
100 }
else if (
cmd.command ==
"tx") {
101 args.emplace_back(
"bitcoin-tx");
102 }
else if (
cmd.command ==
"bench") {
103 args.emplace_back(
"bench_bitcoin");
104 }
else if (
cmd.command ==
"chainstate") {
105 args.emplace_back(
"bitcoin-chainstate");
106 }
else if (
cmd.command ==
"test") {
107 args.emplace_back(
"test_bitcoin");
108 }
else if (
cmd.command ==
"test-gui") {
109 args.emplace_back(
"test_bitcoin-qt");
110 }
else if (
cmd.command ==
"util") {
111 args.emplace_back(
"bitcoin-util");
113 throw std::runtime_error(
strprintf(
"Unrecognized command: '%s'",
cmd.command));
119 }
catch (
const std::exception& e) {
120 tfm::format(std::cerr,
"Error: %s\nTry '%s --help' for more information.\n", e.what(), argv[0]);
129 cmd.args.reserve(argc);
130 for (
int i = 1; i < argc; ++i) {
131 std::string_view arg = argv[i];
132 if (!
cmd.command.empty()) {
133 cmd.args.emplace_back(argv[i]);
134 }
else if (arg ==
"-m" || arg ==
"--multiprocess") {
135 cmd.use_multiprocess =
true;
136 }
else if (arg ==
"-M" || arg ==
"--monolithic") {
137 cmd.use_multiprocess =
false;
138 }
else if (arg ==
"-v" || arg ==
"--version") {
139 cmd.show_version =
true;
140 }
else if (arg ==
"-h" || arg ==
"--help" || arg ==
"help") {
141 cmd.show_help =
true;
142 }
else if (arg.starts_with(
"-")) {
143 throw std::runtime_error(
strprintf(
"Unknown option: %s", arg));
144 }
else if (!arg.empty()) {
155 if (
cmd.use_multiprocess)
return *
cmd.use_multiprocess;
159 std::string error_message;
161 argv.insert(argv.begin(),
nullptr);
163 tfm::format(std::cerr,
"Warning: failed to parse subcommand command line options: %s\n", error_message);
166 tfm::format(std::cerr,
"Warning: failed to parse subcommand config: %s\n", error_message);
193static void ExecCommand(
const std::vector<const char*>&
args, std::string_view wrapper_argv0)
196 std::vector<const char*> exec_args{
args};
197 exec_args.emplace_back(
nullptr);
200 auto try_exec = [&](fs::path exe_path,
bool allow_notfound =
true) {
202 exec_args[0] = exe_path_str.c_str();
203 if (
util::ExecVp(exec_args[0], (
char*
const*)exec_args.data()) == -1) {
204 if (allow_notfound && errno == ENOENT)
return false;
205 throw std::system_error(errno, std::system_category(),
strprintf(
"execvp failed to execute '%s'", exec_args[0]));
207 throw std::runtime_error(
"execvp returned unexpectedly");
215 auto wrapper_dir{fs::weakly_canonical(wrapper_path, ec)};
216 if (wrapper_dir.empty()) wrapper_dir = wrapper_path;
217 wrapper_dir = wrapper_dir.parent_path();
227 const bool fallback_os_search{!
fs::PathFromString(std::string{wrapper_argv0}).has_parent_path()};
231 (wrapper_dir.filename() ==
"bin" && try_exec(wrapper_dir.parent_path() /
"libexec" / arg0.filename())) ||
234 (!wrapper_dir.empty() && try_exec(wrapper_dir /
"daemon" / arg0.filename())) ||
237 (!wrapper_dir.empty() && try_exec(wrapper_dir / arg0.filename(), fallback_os_search)) ||
239 (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.