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