diff --git a/src/app/config/config.c b/src/app/config/config.c index 74cd70ad38..734bd0f928 100644 --- a/src/app/config/config.c +++ b/src/app/config/config.c @@ -2457,6 +2457,8 @@ static const struct { const char *name; /** Does this option accept an argument? */ takes_argument_t takes_argument; + /** If not CMD_RUN_TOR, what should Tor do when it starts? */ + tor_cmdline_mode_t command; } CMDLINE_ONLY_OPTIONS[] = { { .name="-f", .takes_argument=ARGUMENT_NECESSARY }, @@ -2464,31 +2466,44 @@ static const struct { { .name="--defaults-torrc", .takes_argument=ARGUMENT_NECESSARY }, { .name="--hash-password", - .takes_argument=ARGUMENT_NECESSARY }, + .takes_argument=ARGUMENT_NECESSARY, + .command=CMD_HASH_PASSWORD }, { .name="--dump-config", - .takes_argument=ARGUMENT_OPTIONAL }, - { .name="--list-fingerprint" }, - { .name="--keygen" }, + .takes_argument=ARGUMENT_OPTIONAL, + .command=CMD_DUMP_CONFIG }, + { .name="--list-fingerprint", + .command=CMD_LIST_FINGERPRINT }, + { .name="--keygen", + .command=CMD_KEYGEN }, { .name="--key-expiration", - .takes_argument=ARGUMENT_OPTIONAL }, + .takes_argument=ARGUMENT_OPTIONAL, + .command=CMD_KEY_EXPIRATION }, { .name="--newpass" }, { .name="--no-passphrase" }, { .name="--passphrase-fd", .takes_argument=ARGUMENT_NECESSARY }, - { .name="--verify-config" }, + { .name="--verify-config", + .command=CMD_VERIFY_CONFIG }, { .name="--ignore-missing-torrc" }, { .name="--quiet" }, { .name="--hush" }, - { .name="--version" }, - { .name="--list-modules" }, - { .name="--library-versions" }, - { .name="-h" }, - { .name="--help" }, - { .name="--list-torrc-options" }, - { .name="--list-deprecated-options" }, + { .name="--version", + .command=CMD_OTHER }, + { .name="--list-modules", + .command=CMD_OTHER }, + { .name="--library-versions", + .command=CMD_OTHER }, + { .name="-h", + .command=CMD_OTHER }, + { .name="--help", + .command=CMD_OTHER }, + { .name="--list-torrc-options", + .command=CMD_OTHER }, + { .name="--list-deprecated-options", + .command=CMD_OTHER }, { .name="--nt-service" }, { .name="-nt-service" }, - { NULL, 0 }, + { .name=NULL }, }; /** Helper: Read a list of configuration options from the command line. If @@ -2502,6 +2517,7 @@ parsed_cmdline_t * config_parse_commandline(int argc, char **argv, int ignore_errors) { parsed_cmdline_t *result = tor_malloc_zero(sizeof(parsed_cmdline_t)); + result->command = CMD_RUN_TOR; config_line_t *param = NULL; config_line_t **new_cmdline = &result->cmdline_opts; @@ -2515,11 +2531,16 @@ config_parse_commandline(int argc, char **argv, int ignore_errors) takes_argument_t want_arg = ARGUMENT_NECESSARY; int is_cmdline = 0; int j; + bool is_a_command = false; for (j = 0; CMDLINE_ONLY_OPTIONS[j].name != NULL; ++j) { if (!strcmp(argv[i], CMDLINE_ONLY_OPTIONS[j].name)) { is_cmdline = 1; want_arg = CMDLINE_ONLY_OPTIONS[j].takes_argument; + if (CMDLINE_ONLY_OPTIONS[j].command != CMD_RUN_TOR) { + is_a_command = true; + result->command = CMDLINE_ONLY_OPTIONS[j].command; + } break; } } @@ -2569,6 +2590,10 @@ config_parse_commandline(int argc, char **argv, int ignore_errors) log_debug(LD_CONFIG, "command line: parsed keyword '%s', value '%s'", param->key, param->value); + if (is_a_command) { + result->command_arg = param->value; + } + if (is_cmdline) { *new_cmdline = param; new_cmdline = &((*new_cmdline)->next); @@ -3020,7 +3045,9 @@ is_local_addr, (const tor_addr_t *addr)) or_options_t * options_new(void) { - return config_new(get_options_mgr()); + or_options_t *options = config_new(get_options_mgr()); + options->command = CMD_RUN_TOR; + return options; } /** Set options to hold reasonable defaults for most options. @@ -5277,25 +5304,10 @@ options_init_from_torrc(int argc, char **argv) return 1; } - command = CMD_RUN_TOR; - for (p_index = cmdline_only_options; p_index; p_index = p_index->next) { - if (!strcmp(p_index->key,"--keygen")) { - command = CMD_KEYGEN; - } else if (!strcmp(p_index->key, "--key-expiration")) { - command = CMD_KEY_EXPIRATION; - command_arg = p_index->value; - } else if (!strcmp(p_index->key,"--list-fingerprint")) { - command = CMD_LIST_FINGERPRINT; - } else if (!strcmp(p_index->key, "--hash-password")) { - command = CMD_HASH_PASSWORD; - command_arg = p_index->value; - } else if (!strcmp(p_index->key, "--dump-config")) { - command = CMD_DUMP_CONFIG; - command_arg = p_index->value; - } else if (!strcmp(p_index->key, "--verify-config")) { - command = CMD_VERIFY_CONFIG; - } - } + int command = global_cmdline->command; + const char *command_arg = global_cmdline->command_arg; + /* "Other" has already been handled by this point. */ + tor_assert(command != CMD_OTHER); if (command == CMD_HASH_PASSWORD) { cf_defaults = tor_strdup(""); diff --git a/src/app/config/config.h b/src/app/config/config.h index fe4e272d87..582b97d74b 100644 --- a/src/app/config/config.h +++ b/src/app/config/config.h @@ -204,6 +204,10 @@ typedef struct { /** List of other options, to be handled by the general Tor configuration system. */ struct config_line_t *other_opts; + /** Subcommand that Tor has been told to run */ + tor_cmdline_mode_t command; + /** Argument for the command mode, if any. */ + const char *command_arg; } parsed_cmdline_t; parsed_cmdline_t *config_parse_commandline(int argc, char **argv, diff --git a/src/app/config/tor_cmdline_mode.h b/src/app/config/tor_cmdline_mode.h index 9bc9a68d56..36626bed54 100644 --- a/src/app/config/tor_cmdline_mode.h +++ b/src/app/config/tor_cmdline_mode.h @@ -16,7 +16,7 @@ * Enumeration to describe which command Tor is running. These commands * are controlled by command-line options. **/ -typedef enum tor_cmdline_mode_t { +typedef enum { CMD_RUN_TOR=0, /**< The default: run Tor as a daemon. */ CMD_LIST_FINGERPRINT, /**< Running --list-fingerprint. */ CMD_HASH_PASSWORD, /**< Running --hash-password. */ @@ -24,6 +24,8 @@ typedef enum tor_cmdline_mode_t { CMD_DUMP_CONFIG, /**< Running --dump-config. */ CMD_KEYGEN, /**< Running --keygen */ CMD_KEY_EXPIRATION, /**< Running --key-expiration */ + CMD_OTHER, /**< Special value: indicates a command that is handled + * immediately during configuration processing. */ CMD_RUN_UNITTESTS, /**< Special value: indicates that we have entered * the Tor code from the unit tests, not from the * regular Tor binary at all. */ diff --git a/src/app/main/main.c b/src/app/main/main.c index 0edda66fd0..ad8253cc7e 100644 --- a/src/app/main/main.c +++ b/src/app/main/main.c @@ -1357,6 +1357,7 @@ tor_run_main(const tor_main_configuration_t *tor_cfg) result = do_dump_config(); break; case CMD_RUN_UNITTESTS: /* only set by test.c */ + case CMD_OTHER: /* Handled in config.c */ default: log_warn(LD_BUG,"Illegal command number %d: internal error.", get_options()->command); diff --git a/src/app/main/ntmain.c b/src/app/main/ntmain.c index a2de5bb87e..16dc72acc5 100644 --- a/src/app/main/ntmain.c +++ b/src/app/main/ntmain.c @@ -340,6 +340,7 @@ nt_service_main(void) "or --key-expiration) in NT service."); break; case CMD_RUN_UNITTESTS: + case CMD_OTHER: default: log_err(LD_CONFIG, "Illegal command number %d: internal error.", get_options()->command);