From e16cdc182bf122c37e252b49809db688e874b2a3 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Wed, 12 Nov 2014 00:20:40 +0200 Subject: [PATCH] doveadm: Code cleanups to prepare server code for non-mail commands. --- src/doveadm/client-connection.c | 48 +++++++++++++++--------- src/doveadm/doveadm.c | 65 +++++++++++++++++++++------------ 2 files changed, 71 insertions(+), 42 deletions(-) diff --git a/src/doveadm/client-connection.c b/src/doveadm/client-connection.c index f1ae467d4c..85f2148c1b 100644 --- a/src/doveadm/client-connection.c +++ b/src/doveadm/client-connection.c @@ -26,24 +26,18 @@ static void client_connection_input(struct client_connection *conn); -static struct doveadm_mail_cmd_context * -doveadm_mail_cmd_server_parse(const char *cmd_name, +static int +doveadm_mail_cmd_server_parse(const struct doveadm_mail_cmd *cmd, const struct doveadm_settings *set, const struct mail_storage_service_input *input, - int argc, char *argv[]) + int argc, char *argv[], + struct doveadm_mail_cmd_context **ctx_r) { struct doveadm_mail_cmd_context *ctx; - const struct doveadm_mail_cmd *cmd; const char *getopt_args; bool add_username_header = FALSE; int c; - cmd = doveadm_mail_cmd_find(cmd_name); - if (cmd == NULL) { - i_error("doveadm: Client sent unknown command: %s", cmd_name); - return NULL; - } - ctx = doveadm_mail_cmd_init(cmd, set); ctx->full_args = (const void *)(argv + 1); ctx->proxying = TRUE; @@ -77,7 +71,7 @@ doveadm_mail_cmd_server_parse(const char *cmd_name, cmd->name, c); ctx->v.deinit(ctx); pool_unref(&ctx->pool); - return NULL; + return -1; } } } @@ -88,7 +82,7 @@ doveadm_mail_cmd_server_parse(const char *cmd_name, cmd->name, argv[0]); ctx->v.deinit(ctx); pool_unref(&ctx->pool); - return NULL; + return -1; } ctx->args = (const void *)argv; @@ -98,7 +92,8 @@ doveadm_mail_cmd_server_parse(const char *cmd_name, DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE); doveadm_print_sticky("username", input->username); } - return ctx; + *ctx_r = ctx; + return 0; } static void @@ -172,10 +167,30 @@ static bool client_is_allowed_command(const struct doveadm_settings *set, return ret; } +static int doveadm_cmd_handle(struct client_connection *conn, + const char *cmd_name, + const struct mail_storage_service_input *input, + int argc, char *argv[]) +{ + const struct doveadm_mail_cmd *cmd; + struct doveadm_mail_cmd_context *ctx; + + cmd = doveadm_mail_cmd_find(cmd_name); + if (cmd == NULL) { + i_error("doveadm: Client sent unknown command: %s", cmd_name); + return -1; + } + + if (doveadm_mail_cmd_server_parse(cmd, conn->set, input, + argc, argv, &ctx) < 0) + return -1; + doveadm_mail_cmd_server_run(conn, ctx, input); + return 0; +} + static bool client_handle_command(struct client_connection *conn, char **args) { struct mail_storage_service_input input; - struct doveadm_mail_cmd_context *ctx; const char *flags, *cmd_name; unsigned int argc; @@ -225,11 +240,8 @@ static bool client_handle_command(struct client_connection *conn, char **args) } o_stream_cork(conn->output); - ctx = doveadm_mail_cmd_server_parse(cmd_name, conn->set, &input, argc, args); - if (ctx == NULL) + if (doveadm_cmd_handle(conn, cmd_name, &input, argc, args) < 0) o_stream_nsend(conn->output, "\n-\n", 3); - else - doveadm_mail_cmd_server_run(conn, ctx, &input); o_stream_uncork(conn->output); /* flush the output and disconnect */ diff --git a/src/doveadm/doveadm.c b/src/doveadm/doveadm.c index eb6416ea6f..5863ce2017 100644 --- a/src/doveadm/doveadm.c +++ b/src/doveadm/doveadm.c @@ -199,58 +199,75 @@ static void cmd_exec(int argc ATTR_UNUSED, char *argv[]) i_fatal("execv(%s) failed: %m", argv[0]); } -static bool -doveadm_try_run_multi_word(const struct doveadm_cmd *cmd, - const char *cmdname, int argc, char *argv[]) +static const struct doveadm_cmd * +doveadm_cmd_find_multi_word(const struct doveadm_cmd *cmd, + const char *cmdname, int *_argc, char **_argv[]) { + int argc = *_argc; + char **argv = *_argv; + const struct doveadm_cmd *subcmd; unsigned int len; if (argc < 2) - return FALSE; + return NULL; len = strlen(argv[1]); if (strncmp(cmdname, argv[1], len) != 0) - return FALSE; + return NULL; + argc--; argv++; if (cmdname[len] == ' ') { /* more args */ - return doveadm_try_run_multi_word(cmd, cmdname + len + 1, - argc - 1, argv + 1); + subcmd = doveadm_cmd_find_multi_word(cmd, cmdname + len + 1, + &argc, &argv); + if (subcmd == NULL) + return NULL; + } else { + if (cmdname[len] != '\0') + return NULL; } - if (cmdname[len] != '\0') - return FALSE; - /* match */ - cmd->cmd(argc - 1, argv + 1); - return TRUE; + *_argc = argc; + *_argv = argv; + return cmd; } -static bool doveadm_try_run(const char *cmd_name, int argc, char *argv[]) +static const struct doveadm_cmd * +doveadm_cmd_find(const char *cmd_name, int *argc, char **argv[]) { - const struct doveadm_cmd *cmd; + const struct doveadm_cmd *cmd, *subcmd; unsigned int cmd_name_len; - i_assert(argc > 0); + i_assert(*argc > 0); cmd_name_len = strlen(cmd_name); array_foreach(&doveadm_cmds, cmd) { - if (strcmp(cmd->name, cmd_name) == 0) { - cmd->cmd(argc, argv); - return TRUE; - } + if (strcmp(cmd->name, cmd_name) == 0) + return cmd; /* see if it matches a multi-word command */ if (strncmp(cmd->name, cmd_name, cmd_name_len) == 0 && cmd->name[cmd_name_len] == ' ') { - const char *subcmd = cmd->name + cmd_name_len + 1; + const char *subcmd_name = cmd->name + cmd_name_len + 1; - if (doveadm_try_run_multi_word(cmd, subcmd, - argc, argv)) - return TRUE; + subcmd = doveadm_cmd_find_multi_word(cmd, subcmd_name, + argc, argv); + if (subcmd != NULL) + return subcmd; } } + return NULL; +} + +static bool doveadm_try_run(const char *cmd_name, int argc, char *argv[]) +{ + const struct doveadm_cmd *cmd; - return FALSE; + cmd = doveadm_cmd_find(cmd_name, &argc, &argv); + if (cmd == NULL) + return FALSE; + cmd->cmd(argc, argv); + return TRUE; } static bool doveadm_has_subcommands(const char *cmd_name) -- 2.47.3