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

Code before:
        } else if (cmd.command == "util") { // undocumented, used by tests
            args.emplace_back("bitcoin-util");
        } else if (!cmd.command.empty()){
            throw std::runtime_error(strprintf("Unrecognized command: '%s'", cmd.command));
        }
        if (!args.empty()) {
            args.insert(args.end(), cmd.args.begin(), cmd.args.end());
            ExecCommand(args, argv[0]);
        }
    } catch (const std::exception& e) {
        tfm::format(std::cerr, "Error: %s\nTry '%s --help' for more information.\n", e.what(), argv[0]);
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

CommandLine ParseCommandLine(int argc, char* argv[])
{
    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(arg);
        } 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") {
            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)
{

Review comment (suggestion):
If I understand correctly passing `-m -M` will give precedence to `-M`. Should we really support this? Might it better if providing multiple flags at once be an error? E.g. currently running
```
./bitcoin -h -m daemon
```
will print the help string and run the daemon, which might be confusing, since it is not doing the same for `-v`.

Code after:
            args.emplace_back("bitcoin-chainstate");
        } else if (cmd.command == "test") {
            args.emplace_back("test_bitcoin");
        } else if (cmd.command == "test-gui") {
            args.emplace_back("test_bitcoin-qt");
        } else if (cmd.command == "util") {
            args.emplace_back("bitcoin-util");
        } else {
            throw std::runtime_error(strprintf("Unrecognized command: '%s'", cmd.command));
        }
        if (!args.empty()) {
            args.insert(args.end(), cmd.args.begin(), cmd.args.end());
            ExecCommand(args, argv[0]);
        }
    } catch (const std::exception& e) {
        tfm::format(std::cerr, "Error: %s\nTry '%s --help' for more information.\n", e.what(), argv[0]);
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

CommandLine ParseCommandLine(int argc, char* argv[])
{
    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`.