Repository: bitcoin/bitcoin
File: src/bitcoin.cpp (C++)

Code before:
        } else if (arg == "-M" || arg == "--monolithic") {
            cmd.use_multiprocess = false;
        } else if (arg == "-v" || arg == "--version") {
            cmd.show_version = true;
        } else if (arg == "-h" || arg == "--help") {
            cmd.show_help = true;
        } else if (arg.starts_with("-")) {
            throw std::runtime_error(strprintf("Unknown option: %s", arg));
        } else if (!arg.empty()) {
            cmd.command = arg;
        }
    }
    return cmd;
}

// Execute the specified bitcoind, bitcoin-qt or other command line in `args`
// using src, bin and libexec directory paths relative to this executable, where
// the path to this executable is specified `argv0`.
//
// This function doesn't currently print anything but can be debugged from
// the command line using strace like:
//
//     strace -e trace=execve -s 10000 build/src/bitcoin ...
void ExecCommand(const std::vector<std::string>& args, std::string_view argv0)
{
    // Construct argument string for execvp
    std::vector<const char*> cstr_args{};
    cstr_args.reserve(args.size() + 1);
    for (const auto& arg : args) {
        cstr_args.emplace_back(arg.c_str());
    }
    cstr_args.emplace_back(nullptr);

    // Try to call execvp with given exe path.
    auto try_exec = [&](fs::path exe_path, bool allow_notfound = true) {
        std::string exe_path_str{fs::PathToString(exe_path)};
        cstr_args[0] = exe_path_str.c_str();
        if (execvp(cstr_args[0], (char*const*)cstr_args.data()) == -1) {
            if (allow_notfound && errno == ENOENT) return false;
            throw std::system_error(errno, std::system_category(), strprintf("execvp failed to execute '%s'", cstr_args[0]));
        }
        return true; // Will not actually be reached if execvp succeeds
    };

    // Try to figure out where current executable is located. This is a
    // simplified search that won't work perfectly on every platform and doesn't
    // need to, as it is only trying to prioritize locally built or installed
    // executables over system executables. We may want to add options to
    // override this behavior in the future, though.
    const fs::path exe_path{fs::PathFromString(std::string{argv0})};
    fs::path exe_dir(argv0);

Review comment (suggestion):
f17453ff13ebd0be842396c17bcc99b0c903abb8: this seems near impossible on macOS. With `htop` I see that `bitcoin daemon` causes `bitcoind` to run, and there's no lingering `bitcoin` process. The terminal window process also shows this.

<img width="837" alt="Scherm­afbeelding 2024-12-14 om 13 50 21" src="https://github.com/user-attachments/assets/1a978403-fcc0-40c1-8a10-42c6e0af4572" />

<img width="565" alt="Scherm­afbeelding 2024-12-14 om 13 51 09" src="https://github.com/user-attachments/assets/d9342656-c6ae-4921-be4a-891acec5caa9" />


Code after:
    CommandLine cmd;
    cmd.args.reserve(argc);
    for (int i = 1; i < argc; ++i) {
        std::string_view arg = argv[i];
        if (!cmd.command.empty()) {
            cmd.args.emplace_back(argv[i]);
        } else if (arg == "-m" || arg == "--multiprocess") {
            cmd.use_multiprocess = true;
        } else if (arg == "-M" || arg == "--monolithic") {
            cmd.use_multiprocess = false;
        } else if (arg == "-v" || arg == "--version") {
            cmd.show_version = true;
        } else if (arg == "-h" || arg == "--help" || arg == "help") {
            cmd.show_help = true;
        } else if (cmd.show_help && (arg == "-a" || arg == "--all")) {
            cmd.show_help_all = true;
        } else if (arg.starts_with("-")) {
            throw std::runtime_error(strprintf("Unknown option: %s", arg));
        } else if (!arg.empty()) {
            cmd.command = arg;
        }
    }
    return cmd;
}

//! Execute the specified bitcoind, bitcoin-qt or other command line in `args`
//! using src, bin and libexec directory paths relative to this executable, where
//! the path to this executable is specified in `wrapper_argv0`.
//!
//! @param args Command line arguments to execute, where first argument should
//!             be a relative path to a bitcoind, bitcoin-qt or other executable
//!             that will be located on the PATH or relative to wrapper_argv0.
//!
//! @param wrapper_argv0 String containing first command line argument passed to
//!                      main() to run the current executable. This is used to
//!                      help determine the path to the current executable and
//!                      how to look for new executables.
//
//! @note This function doesn't currently print anything but can be debugged
//! from the command line using strace or dtrace like:
//!
//!     strace -e trace=execve -s 10000 build/bin/bitcoin ...
//!     dtrace -n 'proc:::exec-success  /pid == $target/ { trace(curpsinfo->pr_psargs); }' -c ...
static void ExecCommand(const std::vector<const char*>& args, std::string_view wrapper_argv0)
{
    // Construct argument string for execvp
    std::vector<const char*> exec_args{args};
    exec_args.emplace_back(nullptr);

    // Try to call ExecVp with given exe path.
    auto try_exec = [&](fs::path exe_path, bool allow_notfound = true) {