dovecot-2.2: doveadm: Support running non-mail commands via dove...

dovecot at dovecot.org dovecot at dovecot.org
Tue Nov 11 23:08:55 UTC 2014


details:   http://hg.dovecot.org/dovecot-2.2/rev/a4fbe94952ea
changeset: 18060:a4fbe94952ea
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Nov 12 01:06:02 2014 +0200
description:
doveadm: Support running non-mail commands via doveadm server.
There are still some commands that print their output via printf though, so
they need to be fixed separately.

diffstat:

 src/doveadm/Makefile.am         |   44 ++++++++++-------
 src/doveadm/client-connection.c |  100 ++++++++++++++++++++++++++++++---------
 src/doveadm/main.c              |    8 +++
 3 files changed, 109 insertions(+), 43 deletions(-)

diffs (260 lines):

diff -r c54b6bbf215a -r a4fbe94952ea src/doveadm/Makefile.am
--- a/src/doveadm/Makefile.am	Wed Nov 12 01:04:27 2014 +0200
+++ b/src/doveadm/Makefile.am	Wed Nov 12 01:06:02 2014 +0200
@@ -58,7 +58,25 @@
 	$(LIBDOVECOT_STORAGE_DEPS) \
 	$(LIBDOVECOT_DEPS)
 
-common = \
+doveadm_common_cmds = \
+	doveadm-auth.c \
+	doveadm-dict.c \
+	doveadm-director.c \
+	doveadm-fs.c \
+	doveadm-instance.c \
+	doveadm-kick.c \
+	doveadm-log.c \
+	doveadm-master.c \
+	doveadm-mount.c \
+	doveadm-mutf7.c \
+	doveadm-penalty.c \
+	doveadm-proxy.c \
+	doveadm-replicator.c \
+	doveadm-sis.c \
+	doveadm-stats.c \
+	doveadm-who.c
+
+doveadm_common_mail_cmds = \
 	doveadm-dsync.c \
 	doveadm-mail.c \
 	doveadm-mail-altmove.c \
@@ -76,7 +94,12 @@
 	doveadm-mail-copymove.c \
 	doveadm-mailbox-list-iter.c \
 	doveadm-mail-search.c \
-	doveadm-mail-server.c \
+	doveadm-mail-server.c
+
+common = \
+	$(doveadm_common_cmds) \
+	$(doveadm_common_mail_cmds) \
+	doveadm-cmd.c \
 	doveadm-print.c \
 	doveadm-settings.c \
 	doveadm-util.c \
@@ -85,34 +108,17 @@
 doveadm_SOURCES = \
 	$(common) \
 	doveadm.c \
-	doveadm-auth.c \
-	doveadm-cmd.c \
-	doveadm-dict.c \
-	doveadm-director.c \
 	doveadm-dump.c \
 	doveadm-dump-dbox.c \
 	doveadm-dump-index.c \
 	doveadm-dump-log.c \
 	doveadm-dump-mailboxlog.c \
 	doveadm-dump-thread.c \
-	doveadm-fs.c \
-	doveadm-instance.c \
-	doveadm-kick.c \
-	doveadm-log.c \
-	doveadm-master.c \
-	doveadm-mount.c \
-	doveadm-mutf7.c \
-	doveadm-penalty.c \
 	doveadm-print-flow.c \
 	doveadm-print-pager.c \
 	doveadm-print-tab.c \
 	doveadm-print-table.c \
-	doveadm-proxy.c \
 	doveadm-pw.c \
-	doveadm-replicator.c \
-	doveadm-sis.c \
-	doveadm-stats.c \
-	doveadm-who.c \
 	doveadm-zlib.c
 
 doveadm_server_SOURCES = \
diff -r c54b6bbf215a -r a4fbe94952ea src/doveadm/client-connection.c
--- a/src/doveadm/client-connection.c	Wed Nov 12 01:04:27 2014 +0200
+++ b/src/doveadm/client-connection.c	Wed Nov 12 01:06:02 2014 +0200
@@ -24,8 +24,52 @@
 
 #define MAX_INBUF_SIZE (1024*1024)
 
+static struct {
+	int code;
+	const char *str;
+} exit_code_strings[] = {
+	{ EX_TEMPFAIL, "TEMPFAIL" },
+	{ EX_USAGE, "USAGE" },
+	{ EX_NOUSER, "NOUSER" },
+	{ EX_NOPERM, "NOPERM" },
+	{ EX_PROTOCOL, "PROTOCOL" },
+	{ EX_DATAERR, "DATAERR" },
+	{ DOVEADM_EX_NOTFOUND, "NOTFOUND" }
+};
+
 static void client_connection_input(struct client_connection *conn);
 
+static void
+doveadm_cmd_server_run(struct client_connection *conn,
+		       const struct doveadm_cmd *cmd, int argc, char *argv[])
+{
+	const char *str = NULL;
+	unsigned int i;
+
+	doveadm_exit_code = 0;
+	cmd->cmd(argc, argv);
+
+	if (doveadm_exit_code == 0) {
+		o_stream_nsend(conn->output, "\n+\n", 3);
+		return;
+	}
+
+	for (i = 0; i < N_ELEMENTS(exit_code_strings); i++) {
+		if (exit_code_strings[i].code == doveadm_exit_code) {
+			str = exit_code_strings[i].str;
+			break;
+		}
+	}
+	if (str != NULL) {
+		o_stream_nsend_str(conn->output,
+				   t_strdup_printf("\n-%s\n", str));
+	} else {
+		o_stream_nsend_str(conn->output, "\n-\n");
+		i_error("BUG: Command '%s' returned unknown error code %d",
+			cmd->name, doveadm_exit_code);
+	}
+}
+
 static int
 doveadm_mail_cmd_server_parse(const struct doveadm_mail_cmd *cmd,
 			      const struct doveadm_settings *set,
@@ -102,16 +146,10 @@
 			    const struct mail_storage_service_input *input)
 {
 	const char *error;
-	struct ioloop *ioloop, *prev_ioloop = current_ioloop;
 	int ret;
 
 	ctx->conn = conn;
 
-	/* some commands will want to call io_loop_run(), but we're already
-	   running one and we can't call the original one recursively, so
-	   create a new ioloop. */
-	ioloop = io_loop_create();
-	lib_signals_reset_ioloop();
 	if (ctx->v.preinit != NULL)
 		ctx->v.preinit(ctx);
 
@@ -121,12 +159,6 @@
 	doveadm_print_flush();
 	mail_storage_service_deinit(&ctx->storage_service);
 
-	io_loop_set_current(prev_ioloop);
-	lib_signals_reset_ioloop();
-	o_stream_switch_ioloop(conn->output);
-	io_loop_set_current(ioloop);
-	io_loop_destroy(&ioloop);
-
 	if (ret < 0) {
 		i_error("%s: %s", ctx->cmd->name, error);
 		o_stream_nsend(conn->output, "\n-\n", 3);
@@ -140,10 +172,6 @@
 		o_stream_nsend(conn->output, "\n+\n", 3);
 	}
 	pool_unref(&ctx->pool);
-
-	/* clear all headers */
-	doveadm_print_deinit();
-	doveadm_print_init(DOVEADM_PRINT_TYPE_SERVER);
 }
 
 static bool client_is_allowed_command(const struct doveadm_settings *set,
@@ -172,19 +200,43 @@
 			      const struct mail_storage_service_input *input,
 			      int argc, char *argv[])
 {
-	const struct doveadm_mail_cmd *cmd;
+	struct ioloop *ioloop, *prev_ioloop = current_ioloop;
+	const struct doveadm_cmd *cmd;
+	const struct doveadm_mail_cmd *mail_cmd;
 	struct doveadm_mail_cmd_context *ctx;
 
-	cmd = doveadm_mail_cmd_find(cmd_name);
+	cmd = doveadm_cmd_find(cmd_name, &argc, &argv);
 	if (cmd == NULL) {
-		i_error("doveadm: Client sent unknown command: %s", cmd_name);
-		return -1;
+		mail_cmd = doveadm_mail_cmd_find(cmd_name);
+		if (mail_cmd == NULL) {
+			i_error("doveadm: Client sent unknown command: %s", cmd_name);
+			return -1;
+		}
+		if (doveadm_mail_cmd_server_parse(mail_cmd, conn->set, input,
+						  argc, argv, &ctx) < 0)
+			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);
+	/* some commands will want to call io_loop_run(), but we're already
+	   running one and we can't call the original one recursively, so
+	   create a new ioloop. */
+	ioloop = io_loop_create();
+	lib_signals_reset_ioloop();
+
+	if (cmd != NULL)
+		doveadm_cmd_server_run(conn, cmd, argc, argv);
+	else
+		doveadm_mail_cmd_server_run(conn, ctx, input);
+
+	io_loop_set_current(prev_ioloop);
+	lib_signals_reset_ioloop();
+	o_stream_switch_ioloop(conn->output);
+	io_loop_set_current(ioloop);
+	io_loop_destroy(&ioloop);
+
+	/* clear all headers */
+	doveadm_print_deinit();
+	doveadm_print_init(DOVEADM_PRINT_TYPE_SERVER);
 	return 0;
 }
 
diff -r c54b6bbf215a -r a4fbe94952ea src/doveadm/main.c
--- a/src/doveadm/main.c	Wed Nov 12 01:04:27 2014 +0200
+++ b/src/doveadm/main.c	Wed Nov 12 01:06:02 2014 +0200
@@ -36,6 +36,12 @@
 						  conn->ssl);
 }
 
+void help(const struct doveadm_cmd *cmd)
+{
+	i_fatal("Client sent invalid command. Usage: %s %s",
+		cmd->name, cmd->short_usage);
+}
+
 static void main_preinit(void)
 {
 	restrict_access_by_env(NULL, FALSE);
@@ -50,6 +56,7 @@
 					doveadm_settings,
 					pool_datastack_create());
 
+	doveadm_cmds_init();
 	doveadm_mail_init();
 	doveadm_load_modules();
 	doveadm_print_init(DOVEADM_PRINT_TYPE_SERVER);
@@ -62,6 +69,7 @@
 	doveadm_mail_deinit();
 	doveadm_unload_modules();
 	doveadm_print_deinit();
+	doveadm_cmds_deinit();
 }
 
 int main(int argc, char *argv[])


More information about the dovecot-cvs mailing list