5#include <bitcoin-build-config.h>
20static constexpr auto HELP_USAGE = R
"(Usage: %s [OPTIONS] COMMAND...
23 -m, --multiprocess Run multiprocess binaries bitcoin-node, bitcoin-gui.
24 -M, --monolithic Run monolithic binaries bitcoind, bitcoin-qt. (Default behavior)
25 -v, --version Show version information
26 -h, --help Show full help message
29 gui [ARGS] Start GUI, equivalent to running 'bitcoin-qt [ARGS]' or 'bitcoin-gui [ARGS]'.
30 node [ARGS] Start node, equivalent to running 'bitcoind [ARGS]' or 'bitcoin-node [ARGS]'.
31 rpc [ARGS] Call RPC method, equivalent to running 'bitcoin-cli -named [ARGS]'.
32 wallet [ARGS] Call wallet command, equivalent to running 'bitcoin-wallet [ARGS]'.
33 tx [ARGS] Manipulate hex-encoded transactions, equivalent to running 'bitcoin-tx [ARGS]'.
34 help Show full help message.
38Additional less commonly used commands:
39 bench [ARGS] Run bench command, equivalent to running 'bench_bitcoin [ARGS]'.
40 chainstate [ARGS] Run bitcoin kernel chainstate util, equivalent to running 'bitcoin-chainstate [ARGS]'.
41 test [ARGS] Run unit tests, equivalent to running 'test_bitcoin [ARGS]'.
42 test-gui [ARGS] Run GUI unit tests, equivalent to running 'test_bitcoin-qt [ARGS]'.
46Run '%s help' to see additional commands (e.g. for testing and debugging).
54 std::vector<const char*>
args;
58static void ExecCommand(
const std::vector<const char*>&
args, std::string_view argv0);
60int main(
int argc,
char* argv[])
64 if (
cmd.show_version) {
70 std::vector<const char*>
args;
71 if (
cmd.show_help ||
cmd.command.empty()) {
80 }
else if (
cmd.command ==
"gui") {
81 args.emplace_back(
cmd.use_multiprocess ?
"bitcoin-gui" :
"bitcoin-qt");
82 }
else if (
cmd.command ==
"node") {
83 args.emplace_back(
cmd.use_multiprocess ?
"bitcoin-node" :
"bitcoind");
84 }
else if (
cmd.command ==
"rpc") {
85 args.emplace_back(
"bitcoin-cli");
92 args.emplace_back(
"-named");
93 }
else if (
cmd.command ==
"wallet") {
94 args.emplace_back(
"bitcoin-wallet");
95 }
else if (
cmd.command ==
"tx") {
96 args.emplace_back(
"bitcoin-tx");
97 }
else if (
cmd.command ==
"bench") {
98 args.emplace_back(
"bench_bitcoin");
99 }
else if (
cmd.command ==
"chainstate") {
100 args.emplace_back(
"bitcoin-chainstate");
101 }
else if (
cmd.command ==
"test") {
102 args.emplace_back(
"test_bitcoin");
103 }
else if (
cmd.command ==
"test-gui") {
104 args.emplace_back(
"test_bitcoin-qt");
105 }
else if (
cmd.command ==
"util") {
106 args.emplace_back(
"bitcoin-util");
108 throw std::runtime_error(
strprintf(
"Unrecognized command: '%s'",
cmd.command));
114 }
catch (
const std::exception& e) {
115 tfm::format(std::cerr,
"Error: %s\nTry '%s --help' for more information.\n", e.what(), argv[0]);
124 cmd.args.reserve(argc);
125 for (
int i = 1; i < argc; ++i) {
126 std::string_view arg = argv[i];
127 if (!
cmd.command.empty()) {
128 cmd.args.emplace_back(argv[i]);
129 }
else if (arg ==
"-m" || arg ==
"--multiprocess") {
130 cmd.use_multiprocess =
true;
131 }
else if (arg ==
"-M" || arg ==
"--monolithic") {
132 cmd.use_multiprocess =
false;
133 }
else if (arg ==
"-v" || arg ==
"--version") {
134 cmd.show_version =
true;
135 }
else if (arg ==
"-h" || arg ==
"--help" || arg ==
"help") {
136 cmd.show_help =
true;
137 }
else if (arg.starts_with(
"-")) {
138 throw std::runtime_error(
strprintf(
"Unknown option: %s", arg));
139 }
else if (!arg.empty()) {
164static void ExecCommand(
const std::vector<const char*>&
args, std::string_view wrapper_argv0)
167 std::vector<const char*> exec_args{
args};
168 exec_args.emplace_back(
nullptr);
171 auto try_exec = [&](fs::path exe_path,
bool allow_notfound =
true) {
173 exec_args[0] = exe_path_str.c_str();
174 if (
util::ExecVp(exec_args[0], (
char*
const*)exec_args.data()) == -1) {
175 if (allow_notfound && errno == ENOENT)
return false;
176 throw std::system_error(errno, std::system_category(),
strprintf(
"execvp failed to execute '%s'", exec_args[0]));
178 throw std::runtime_error(
"execvp returned unexpectedly");
186 fs::path wrapper_dir{fs::weakly_canonical(wrapper_path, ec)};
187 if (wrapper_dir.empty()) wrapper_dir = wrapper_path;
188 wrapper_dir = wrapper_dir.parent_path();
198 const bool fallback_os_search{!
fs::PathFromString(std::string{wrapper_argv0}).has_parent_path()};
202 (wrapper_dir.filename() ==
"bin" && try_exec(fs::path{wrapper_dir.parent_path()} /
"libexec" / arg0.filename())) ||
205 (!wrapper_dir.empty() && try_exec(wrapper_dir /
"daemon" / arg0.filename())) ||
208 (!wrapper_dir.empty() && try_exec(wrapper_dir / arg0.filename(), fallback_os_search)) ||
210 (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.
static constexpr auto HELP_USAGE
CommandLine ParseCommandLine(int argc, char *argv[])
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::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.