]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
doveadm: Support running non-mail commands via doveadm server.
authorTimo Sirainen <tss@iki.fi>
Tue, 11 Nov 2014 23:06:02 +0000 (01:06 +0200)
committerTimo Sirainen <tss@iki.fi>
Tue, 11 Nov 2014 23:06:02 +0000 (01:06 +0200)
There are still some commands that print their output via printf though, so
they need to be fixed separately.

src/doveadm/Makefile.am
src/doveadm/client-connection.c
src/doveadm/main.c

index 0e19cd6453af15f595a0a5bae5253df2a39f1b17..355232d74de237d43a0e9dbd54e67284b362cff3 100644 (file)
@@ -58,7 +58,25 @@ doveadm_server_DEPENDENCIES = \
        $(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 @@ common = \
        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 @@ common = \
 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 = \
index 85f2148c1b4fee28a4591795627209276df6af69..a441e69075a244d7e5f0c1fd082d9ddb5d582c8d 100644 (file)
 
 #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 @@ doveadm_mail_cmd_server_run(struct client_connection *conn,
                            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_mail_cmd_server_run(struct client_connection *conn,
        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 @@ doveadm_mail_cmd_server_run(struct client_connection *conn,
                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 @@ static int doveadm_cmd_handle(struct client_connection *conn,
                              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;
 }
 
index e5dc43d748ce861b8123adbc8da58fd5c2407f2c..541beb0b68fc0605c8d6e280a802c918eee63fe0 100644 (file)
@@ -36,6 +36,12 @@ static void client_connected(struct master_service_connection *conn)
                                                  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 @@ static void main_init(void)
                                        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 @@ static void main_deinit(void)
        doveadm_mail_deinit();
        doveadm_unload_modules();
        doveadm_print_deinit();
+       doveadm_cmds_deinit();
 }
 
 int main(int argc, char *argv[])