From: Karl Fleischmann Date: Thu, 22 Jun 2023 10:18:07 +0000 (+0200) Subject: doveadm: Process subcommand "--help" options X-Git-Tag: 2.4.0~2643 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6735fd68b041e3e6a1e4bab6d296fd14b703a18e;p=thirdparty%2Fdovecot%2Fcore.git doveadm: Process subcommand "--help" options Arguments are handled individually in different situations when invoking doveadm with or without subcommands (specifically doveadm_cmdline_find_with_args() may fail if "help" is passed). To handle all necessary situtations the command context needs to be expanded with a variable to differentiate whether a help argument (i.e. "--help") or a help option (i.e. "help") is given. This is used subsequently to print the help/usage text to stdout with a successful return code if requested. --- diff --git a/src/doveadm/doveadm-cmd-parse.h b/src/doveadm/doveadm-cmd-parse.h index ce9d15302e..54b2578add 100644 --- a/src/doveadm/doveadm-cmd-parse.h +++ b/src/doveadm/doveadm-cmd-parse.h @@ -90,12 +90,19 @@ struct doveadm_cmd_ver2 { const struct doveadm_cmd_param *parameters; }; +enum doveadm_cmd_ver2_help_requested { + DOVEADM_CMD_VER2_NO_HELP, + DOVEADM_CMD_VER2_HELP_ARGUMENT, + DOVEADM_CMD_VER2_HELP_COMMAND, +}; + struct doveadm_cmd_context { const struct doveadm_cmd_ver2 *cmd; /* for help */ pool_t pool; int argc; const struct doveadm_cmd_param *argv; + enum doveadm_cmd_ver2_help_requested help_requested; const char *username; struct ip_addr local_ip, remote_ip; diff --git a/src/doveadm/doveadm-cmd.c b/src/doveadm/doveadm-cmd.c index 1f64fd3446..147d172001 100644 --- a/src/doveadm/doveadm-cmd.c +++ b/src/doveadm/doveadm-cmd.c @@ -124,17 +124,39 @@ void doveadm_cmds_deinit(void) array_free(&doveadm_cmds_ver2); } +static void +doveadm_cmdline_check_for_help_request(int argc, const char *const argv[], + struct doveadm_cmd_context *cctx) { + for (int i = 0; i < argc; i++) { + if (strcmp(argv[i], "--") == 0) + break; + + if (strcmp(argv[i], "--help") == 0) { + cctx->help_requested = DOVEADM_CMD_VER2_HELP_ARGUMENT; + break; + } + + if (strcmp(argv[i], "help") == 0) { + cctx->help_requested = DOVEADM_CMD_VER2_HELP_COMMAND; + break; + } + } +} + bool doveadm_cmdline_try_run(const char *cmd_name, int argc, const char *const argv[], struct doveadm_cmd_context *cctx) { const struct doveadm_cmd_ver2 *cmd; + doveadm_cmdline_check_for_help_request(argc, argv, cctx); cmd = doveadm_cmdline_find_with_args(cmd_name, &argc, &argv); if (cmd == NULL) return FALSE; cctx->cmd = cmd; + if (cctx->help_requested == DOVEADM_CMD_VER2_HELP_ARGUMENT) + return FALSE; if (doveadm_cmdline_run(argc, argv, cctx) < 0) doveadm_exit_code = EX_USAGE; return TRUE; diff --git a/src/doveadm/doveadm.c b/src/doveadm/doveadm.c index 30e8c25f36..45d7b54234 100644 --- a/src/doveadm/doveadm.c +++ b/src/doveadm/doveadm.c @@ -383,8 +383,16 @@ int main(int argc, char *argv[]) cctx->username = getenv("USER"); if (!doveadm_cmdline_try_run(cmd_name, argc, (const char**)argv, cctx)) { + help_requested = cctx->help_requested != DOVEADM_CMD_VER2_NO_HELP; + FILE *out = help_requested ? stdout : stderr; + int exit_code = help_requested ? EX_OK : EX_USAGE; + if (cctx->help_requested == DOVEADM_CMD_VER2_HELP_ARGUMENT && + cctx->cmd != NULL) { + print_usage_and_exit(stdout, cctx->cmd, EX_OK); + } if (doveadm_has_subcommands(cmd_name)) - usage_prefix(stderr, cmd_name, EX_USAGE); + usage_prefix(out, cmd_name, exit_code); + if (doveadm_has_unloaded_plugin(cmd_name)) { i_fatal("Unknown command '%s', but plugin %s exists. " "Try to set mail_plugins=%s",