dovecot-2.1: doveadm: Added "batch" command to run multiple mail...
dovecot at dovecot.org
dovecot at dovecot.org
Mon Mar 25 16:20:00 EET 2013
details: http://hg.dovecot.org/dovecot-2.1/rev/8cc28a5a3f4f
changeset: 14938:8cc28a5a3f4f
user: Timo Sirainen <tss at iki.fi>
date: Mon Mar 25 16:19:54 2013 +0200
description:
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.
diffstat:
src/doveadm/Makefile.am | 1 +
src/doveadm/doveadm-mail-batch.c | 162 +++++++++++++++++++++++++++++++++++++++
src/doveadm/doveadm-mail.c | 54 ++++++++----
src/doveadm/doveadm-mail.h | 4 +
4 files changed, 204 insertions(+), 17 deletions(-)
diffs (truncated from 304 to 300 lines):
diff -r 73feea4d22aa -r 8cc28a5a3f4f src/doveadm/Makefile.am
--- 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 \
diff -r 73feea4d22aa -r 8cc28a5a3f4f src/doveadm/doveadm-mail-batch.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> [..]]"
+};
diff -r 73feea4d22aa -r 8cc28a5a3f4f src/doveadm/doveadm-mail.c
--- 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
diff -r 73feea4d22aa -r 8cc28a5a3f4f src/doveadm/doveadm-mail.h
--- 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;
More information about the dovecot-cvs
mailing list