Mercurial > dovecot > original-hg > dovecot-2.1
changeset 14938:8cc28a5a3f4f
doveadm: Added "batch" command to run multiple mail commands.
This only makes sense when the commands are run with -A or -u <usermask>, so
that the commands are run for the same user before moving onto the next user.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 25 Mar 2013 16:19:54 +0200 |
parents | 73feea4d22aa |
children | 87d0c4056b4d |
files | src/doveadm/Makefile.am src/doveadm/doveadm-mail-batch.c src/doveadm/doveadm-mail.c src/doveadm/doveadm-mail.h |
diffstat | 4 files changed, 204 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/src/doveadm/Makefile.am Fri Feb 22 10:31:38 2013 +0200 +++ b/src/doveadm/Makefile.am Mon Mar 25 16:19:54 2013 +0200 @@ -68,6 +68,7 @@ common = \ doveadm-mail.c \ doveadm-mail-altmove.c \ + doveadm-mail-batch.c \ doveadm-mail-expunge.c \ doveadm-mail-fetch.c \ doveadm-mail-import.c \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/doveadm/doveadm-mail-batch.c Mon Mar 25 16:19:54 2013 +0200 @@ -0,0 +1,162 @@ +/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "array.h" +#include "doveadm-mail.h" + +#include <unistd.h> + +struct batch_cmd_context { + struct doveadm_mail_cmd_context ctx; + ARRAY_DEFINE(commands, struct doveadm_mail_cmd_context *); +}; + +static int cmd_batch_prerun(struct doveadm_mail_cmd_context *_ctx, + struct mail_storage_service_user *service_user, + const char **error_r) +{ + struct batch_cmd_context *ctx = (struct batch_cmd_context *)_ctx; + struct doveadm_mail_cmd_context *const *cmdp; + int ret = 0; + + array_foreach(&ctx->commands, cmdp) { + if ((*cmdp)->v.prerun != NULL && + (*cmdp)->v.prerun(*cmdp, service_user, error_r) < 0) { + ret = -1; + break; + } + } + return ret; +} + +static int cmd_batch_run(struct doveadm_mail_cmd_context *_ctx, + struct mail_user *user) +{ + struct batch_cmd_context *ctx = (struct batch_cmd_context *)_ctx; + struct doveadm_mail_cmd_context *const *cmdp; + int ret = 0; + + array_foreach(&ctx->commands, cmdp) { + if ((*cmdp)->v.run(*cmdp, user) < 0) { + ret = -1; + break; + } + } + return ret; +} + +static void +cmd_batch_add(struct batch_cmd_context *batchctx, + int argc, const char *const *argv) +{ + struct doveadm_mail_cmd_context *subctx; + const struct doveadm_mail_cmd *cmd; + const char *getopt_args; + int c; + + cmd = doveadm_mail_cmd_find_from_argv(argv[0], &argc, &argv); + if (cmd == NULL) { + i_fatal_status(EX_USAGE, "doveadm batch: Unknown subcommand %s", + argv[1]); + } + + subctx = doveadm_mail_cmd_init(cmd, doveadm_settings); + subctx->full_args = argv + 1; + subctx->service_flags |= batchctx->ctx.service_flags; + + optind = 1; + getopt_args = subctx->getopt_args != NULL ? subctx->getopt_args : ""; + while ((c = getopt(argc, (void *)argv, getopt_args)) > 0) { + if (subctx->v.parse_arg == NULL || + !subctx->v.parse_arg(subctx, c)) + doveadm_mail_help(cmd); + } + argv += optind; + if (argv[0] != NULL && cmd->usage_args == NULL) { + i_fatal_status(EX_USAGE, "doveadm %s: Unknown parameter: %s", + cmd->name, argv[0]); + } + subctx->args = argv; + if (subctx->v.preinit != NULL) + subctx->v.preinit(subctx); + array_append(&batchctx->commands, &subctx, 1); +} + +static void +cmd_batch_preinit(struct doveadm_mail_cmd_context *_ctx) +{ + const char *const *args = _ctx->args; + struct batch_cmd_context *ctx = (struct batch_cmd_context *)_ctx; + ARRAY_TYPE(const_string) sep_args; + const char *sep = args[0]; + unsigned int i, start; + int argc; + const char *const *argv; + + if (sep == NULL || args[1] == NULL) + doveadm_mail_help_name("batch"); + args++; + + p_array_init(&ctx->commands, _ctx->pool, 8); + p_array_init(&sep_args, _ctx->pool, 16); + for (i = start = 0;; i++) { + if (args[i] != NULL && strcmp(args[i], sep) != 0) { + array_append(&sep_args, &args[i], 1); + continue; + } + if (i > start) { + (void)array_append_space(&sep_args); + argc = i - start; + argv = array_idx(&sep_args, start); + cmd_batch_add(ctx, argc, argv); + start = i+1; + } + if (args[i] == NULL) + break; + } + (void)array_append_space(&sep_args); +} + +static void +cmd_batch_init(struct doveadm_mail_cmd_context *_ctx, + const char *const args[] ATTR_UNUSED) +{ + struct batch_cmd_context *ctx = (struct batch_cmd_context *)_ctx; + struct doveadm_mail_cmd_context *const *cmdp; + struct batch_cmd_context *subctx; + + array_foreach(&ctx->commands, cmdp) { + subctx = (struct batch_cmd_context *)*cmdp; + subctx->ctx.storage_service = _ctx->storage_service; + if (subctx->ctx.v.init != NULL) + subctx->ctx.v.init(&subctx->ctx, subctx->ctx.args); + } +} + +static void cmd_batch_deinit(struct doveadm_mail_cmd_context *_ctx) +{ + struct batch_cmd_context *ctx = (struct batch_cmd_context *)_ctx; + struct doveadm_mail_cmd_context *const *cmdp; + + array_foreach(&ctx->commands, cmdp) { + if ((*cmdp)->v.deinit != NULL) + (*cmdp)->v.deinit(*cmdp); + } +} + +static struct doveadm_mail_cmd_context *cmd_batch_alloc(void) +{ + struct batch_cmd_context *ctx; + + ctx = doveadm_mail_cmd_alloc(struct batch_cmd_context); + ctx->ctx.v.preinit = cmd_batch_preinit; + ctx->ctx.v.init = cmd_batch_init; + ctx->ctx.v.prerun = cmd_batch_prerun; + ctx->ctx.v.run = cmd_batch_run; + ctx->ctx.v.deinit = cmd_batch_deinit; + return &ctx->ctx; +} + +struct doveadm_mail_cmd cmd_batch = { + cmd_batch_alloc, "batch", "<sep> <cmd1> [<sep> <cmd2> [..]]" +};
--- a/src/doveadm/doveadm-mail.c Fri Feb 22 10:31:38 2013 +0200 +++ b/src/doveadm/doveadm-mail.c Mon Mar 25 16:19:54 2013 +0200 @@ -541,59 +541,78 @@ } static bool -doveadm_mail_try_run_multi_word(const struct doveadm_mail_cmd *cmd, - const char *cmdname, int argc, char *argv[]) +doveadm_mail_cmd_try_find_multi_word(const struct doveadm_mail_cmd *cmd, + const char *cmdname, int *argc, + const char *const **argv) { unsigned int len; - if (argc < 2) + if (*argc < 2) return FALSE; + *argc -= 1; + *argv += 1; - len = strlen(argv[1]); - if (strncmp(cmdname, argv[1], len) != 0) + len = strlen((*argv)[0]); + if (strncmp(cmdname, (*argv)[0], len) != 0) return FALSE; if (cmdname[len] == ' ') { /* more args */ - return doveadm_mail_try_run_multi_word(cmd, cmdname + len + 1, - argc - 1, argv + 1); + return doveadm_mail_cmd_try_find_multi_word(cmd, cmdname + len + 1, + argc, argv); } if (cmdname[len] != '\0') return FALSE; /* match */ - doveadm_mail_cmd(cmd, argc - 1, argv + 1); return TRUE; } -bool doveadm_mail_try_run(const char *cmd_name, int argc, char *argv[]) +const struct doveadm_mail_cmd * +doveadm_mail_cmd_find_from_argv(const char *cmd_name, int *argc, + const char *const **argv) { const struct doveadm_mail_cmd *cmd; unsigned int cmd_name_len; + const char *const *orig_argv; + int orig_argc; - i_assert(argc > 0); + i_assert(*argc > 0); cmd_name_len = strlen(cmd_name); array_foreach(&doveadm_mail_cmds, cmd) { - if (strcmp(cmd->name, cmd_name) == 0) { - doveadm_mail_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; - if (doveadm_mail_try_run_multi_word(cmd, subcmd, - argc, argv)) - return TRUE; + orig_argc = *argc; + orig_argv = *argv; + if (doveadm_mail_cmd_try_find_multi_word(cmd, subcmd, + argc, argv)) + return cmd; + *argc = orig_argc; + *argv = orig_argv; } } return FALSE; } +bool doveadm_mail_try_run(const char *cmd_name, int argc, char *argv[]) +{ + const struct doveadm_mail_cmd *cmd; + + cmd = doveadm_mail_cmd_find_from_argv(cmd_name, &argc, (void *)&argv); + if (cmd == NULL) + return FALSE; + doveadm_mail_cmd(cmd, argc, argv); + return TRUE; +} + void doveadm_mail_register_cmd(const struct doveadm_mail_cmd *cmd) { /* for now we'll just assume that cmd will be permanently in memory */ @@ -686,6 +705,7 @@ &cmd_mailbox_subscribe, &cmd_mailbox_unsubscribe, &cmd_mailbox_status, + &cmd_batch, &cmd_dsync_backup, &cmd_dsync_mirror, &cmd_dsync_server
--- a/src/doveadm/doveadm-mail.h Fri Feb 22 10:31:38 2013 +0200 +++ b/src/doveadm/doveadm-mail.h Mon Mar 25 16:19:54 2013 +0200 @@ -95,6 +95,9 @@ void doveadm_mail_init(void); void doveadm_mail_deinit(void); +const struct doveadm_mail_cmd * +doveadm_mail_cmd_find_from_argv(const char *cmd_name, int *argc, + const char *const **argv); struct doveadm_mail_cmd_context * doveadm_mail_cmd_init(const struct doveadm_mail_cmd *cmd, const struct doveadm_settings *set); @@ -145,5 +148,6 @@ struct doveadm_mail_cmd cmd_mailbox_subscribe; struct doveadm_mail_cmd cmd_mailbox_unsubscribe; struct doveadm_mail_cmd cmd_mailbox_status; +struct doveadm_mail_cmd cmd_batch; #endif