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 this 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 [-a] Show this help message. Include -a or --all to show additional commands.
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]'.
51 std::vector<const char*>
args;
55static void ExecCommand(
const std::vector<const char*>&
args, std::string_view argv0);
57int main(
int argc,
char* argv[])
61 if (
cmd.show_version) {
66 std::vector<const char*>
args;
67 if (
cmd.show_help ||
cmd.command.empty()) {
71 }
else if (
cmd.command ==
"gui") {
72 args.emplace_back(
cmd.use_multiprocess ?
"bitcoin-gui" :
"bitcoin-qt");
73 }
else if (
cmd.command ==
"node") {
74 args.emplace_back(
cmd.use_multiprocess ?
"bitcoin-node" :
"bitcoind");
75 }
else if (
cmd.command ==
"rpc") {
76 args.emplace_back(
"bitcoin-cli");
83 args.emplace_back(
"-named");
84 }
else if (
cmd.command ==
"wallet") {
85 args.emplace_back(
"bitcoin-wallet");
86 }
else if (
cmd.command ==
"tx") {
87 args.emplace_back(
"bitcoin-tx");
88 }
else if (
cmd.command ==
"bench") {
89 args.emplace_back(
"bench_bitcoin");
90 }
else if (
cmd.command ==
"chainstate") {
91 args.emplace_back(
"bitcoin-chainstate");
92 }
else if (
cmd.command ==
"test") {
93 args.emplace_back(
"test_bitcoin");
94 }
else if (
cmd.command ==
"test-gui") {
95 args.emplace_back(
"test_bitcoin-qt");
96 }
else if (
cmd.command ==
"util") {
97 args.emplace_back(
"bitcoin-util");
99 throw std::runtime_error(
strprintf(
"Unrecognized command: '%s'",
cmd.command));
105 }
catch (
const std::exception& e) {
106 tfm::format(std::cerr,
"Error: %s\nTry '%s --help' for more information.\n", e.what(), argv[0]);
115 cmd.args.reserve(argc);
116 for (
int i = 1; i < argc; ++i) {
117 std::string_view arg = argv[i];
118 if (!
cmd.command.empty()) {
119 cmd.args.emplace_back(argv[i]);
120 }
else if (arg ==
"-m" || arg ==
"--multiprocess") {
121 cmd.use_multiprocess =
true;
122 }
else if (arg ==
"-M" || arg ==
"--monolithic") {
123 cmd.use_multiprocess =
false;
124 }
else if (arg ==
"-v" || arg ==
"--version") {
125 cmd.show_version =
true;
126 }
else if (arg ==
"-h" || arg ==
"--help" || arg ==
"help") {
127 cmd.show_help =
true;
128 }
else if (
cmd.show_help && (arg ==
"-a" || arg ==
"--all")) {
129 cmd.show_help_all =
true;
130 }
else if (arg.starts_with(
"-")) {
131 throw std::runtime_error(
strprintf(
"Unknown option: %s", arg));
132 }
else if (!arg.empty()) {
157static void ExecCommand(
const std::vector<const char*>&
args, std::string_view wrapper_argv0)
160 std::vector<const char*> exec_args{
args};
161 exec_args.emplace_back(
nullptr);
164 auto try_exec = [&](fs::path exe_path,
bool allow_notfound =
true) {
166 exec_args[0] = exe_path_str.c_str();
167 if (
util::ExecVp(exec_args[0], (
char*
const*)exec_args.data()) == -1) {
168 if (allow_notfound && errno == ENOENT)
return false;
169 throw std::system_error(errno, std::system_category(),
strprintf(
"execvp failed to execute '%s'", exec_args[0]));
171 throw std::runtime_error(
"execvp returned unexpectedly");
179 fs::path wrapper_dir{fs::weakly_canonical(wrapper_path, ec)};
180 if (wrapper_dir.empty()) wrapper_dir = wrapper_path;
181 wrapper_dir = wrapper_dir.parent_path();
191 const bool fallback_os_search{!
fs::PathFromString(std::string{wrapper_argv0}).has_parent_path()};
195 (wrapper_dir.filename() ==
"bin" && try_exec(fs::path{wrapper_dir.parent_path()} /
"libexec" / arg0.filename())) ||
198 (!wrapper_dir.empty() && try_exec(wrapper_dir /
"daemon" / arg0.filename())) ||
201 (!wrapper_dir.empty() && try_exec(wrapper_dir / arg0.filename(), fallback_os_search)) ||
203 (fallback_os_search && try_exec(arg0.filename(),
false));
int main(int argc, char *argv[])
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
static constexpr auto HELP_EXTRA
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.