dovecot-2.0: doveadm: Added client/server architecture support f...
dovecot at dovecot.org
dovecot at dovecot.org
Fri Jul 23 22:37:52 EEST 2010
details: http://hg.dovecot.org/dovecot-2.0/rev/b60e225386bf
changeset: 11897:b60e225386bf
user: Timo Sirainen <tss at iki.fi>
date: Fri Jul 23 20:37:35 2010 +0100
description:
doveadm: Added client/server architecture support for running mail commands.
This is done when doveadm_worker_count is non-zero.
diffstat:
.hgignore | 1 +
doc/example-config/dovecot.conf | 6 +
src/doveadm/Makefile.am | 52 ++++-
src/doveadm/client-connection.c | 239 +++++++++++++++++++++++++++++
src/doveadm/client-connection.h | 9 +
src/doveadm/doveadm-mail-server.c | 269 +++++++++++++++++++++++++++++++++
src/doveadm/doveadm-mail.c | 13 +
src/doveadm/doveadm-mail.h | 6 +
src/doveadm/doveadm-print-server.c | 82 ++++++++++
src/doveadm/doveadm-print.c | 8 +
src/doveadm/doveadm-print.h | 1 +
src/doveadm/doveadm-server.h | 16 ++
src/doveadm/doveadm-settings.c | 69 ++++++++
src/doveadm/doveadm-settings.h | 2 +
src/doveadm/doveadm-util.c | 2 +-
src/doveadm/doveadm-util.h | 2 +-
src/doveadm/main.c | 101 ++++++++++++
src/doveadm/server-connection.c | 290 ++++++++++++++++++++++++++++++++++++
src/doveadm/server-connection.h | 27 +++
src/lib-master/master-service-private.h | 1 +
src/lib-master/master-service.c | 6 +
src/lib-master/master-service.h | 2 +
src/plugins/expire/doveadm-expire.c | 1 +
23 files changed, 1189 insertions(+), 16 deletions(-)
diffs (truncated from 1489 to 300 lines):
diff -r 158be8d93ddc -r b60e225386bf .hgignore
--- a/.hgignore Fri Jul 23 20:31:21 2010 +0100
+++ b/.hgignore Fri Jul 23 20:37:35 2010 +0100
@@ -65,6 +65,7 @@
src/director/director-test
src/dns/dns-client
src/doveadm/doveadm
+src/doveadm/doveadm-server
src/dsync/dsync
src/imap-login/imap-login
src/imap/imap
diff -r 158be8d93ddc -r b60e225386bf doc/example-config/dovecot.conf
--- a/doc/example-config/dovecot.conf Fri Jul 23 20:31:21 2010 +0100
+++ b/doc/example-config/dovecot.conf Fri Jul 23 20:37:35 2010 +0100
@@ -56,6 +56,12 @@
# a problem if the upgrade is e.g. because of a security fix).
#shutdown_clients = yes
+# If non-zero, run mail commands via this many connections to doveadm server,
+# instead of running them directly in the same process.
+#doveadm_worker_count = 0
+# UNIX socket or host:port used for connecting to doveadm server
+#doveadm_socket_path = doveadm-server
+
##
## Dictionary server settings
##
diff -r 158be8d93ddc -r b60e225386bf src/doveadm/Makefile.am
--- a/src/doveadm/Makefile.am Fri Jul 23 20:31:21 2010 +0100
+++ b/src/doveadm/Makefile.am Fri Jul 23 20:37:35 2010 +0100
@@ -1,6 +1,7 @@
doveadm_moduledir = $(moduledir)/doveadm
bin_PROGRAMS = doveadm
+pkglibexec_PROGRAMS = doveadm-server
AM_CPPFLAGS = \
-I$(top_srcdir)/src/lib \
@@ -33,18 +34,42 @@
libs = \
$(LIBDOVECOT_STORAGE) \
- $(cmd_pw_libs) \
$(unused_objects)
doveadm_LDADD = \
$(libs) $(AUTH_LIBS) \
+ $(cmd_pw_libs) \
$(LIBDOVECOT) \
$(MODULE_LIBS)
doveadm_DEPENDENCIES = \
$(libs) \
+ $(cmd_pw_libs) \
$(LIBDOVECOT_DEPS)
+doveadm_server_LDADD = \
+ $(libs) \
+ $(LIBDOVECOT) \
+ $(MODULE_LIBS)
+doveadm_server_DEPENDENCIES = \
+ $(libs) \
+ $(LIBDOVECOT_DEPS)
+
+common = \
+ doveadm-mail.c \
+ doveadm-mail-altmove.c \
+ doveadm-mail-expunge.c \
+ doveadm-mail-fetch.c \
+ doveadm-mail-iter.c \
+ doveadm-mail-mailbox.c \
+ doveadm-mail-mailbox-status.c \
+ doveadm-mail-list-iter.c \
+ doveadm-mail-search.c \
+ doveadm-print.c \
+ doveadm-settings.c \
+ doveadm-util.c
+
doveadm_SOURCES = \
+ $(common) \
doveadm.c \
doveadm-auth.c \
doveadm-director.c \
@@ -56,28 +81,26 @@
doveadm-kick.c \
doveadm-log.c \
doveadm-master.c \
- doveadm-mail.c \
- doveadm-mail-altmove.c \
- doveadm-mail-expunge.c \
- doveadm-mail-fetch.c \
- doveadm-mail-iter.c \
- doveadm-mail-mailbox.c \
- doveadm-mail-mailbox-status.c \
- doveadm-mail-list-iter.c \
- doveadm-mail-search.c \
+ doveadm-mail-server.c \
doveadm-mutf7.c \
doveadm-penalty.c \
- doveadm-print.c \
doveadm-print-flow.c \
doveadm-print-pager.c \
doveadm-print-tab.c \
doveadm-print-table.c \
doveadm-pw.c \
- doveadm-settings.c \
- doveadm-util.c \
- doveadm-who.c
+ doveadm-who.c \
+ server-connection.c
+
+doveadm_server_SOURCES = \
+ $(common) \
+ client-connection.c \
+ doveadm-print-server.c \
+ main.c
noinst_HEADERS = \
+ client-connection.h \
+ server-connection.h \
doveadm.h \
doveadm-dump.h \
doveadm-mail.h \
@@ -85,6 +108,7 @@
doveadm-mail-list-iter.h \
doveadm-print.h \
doveadm-print-private.h \
+ doveadm-server.h \
doveadm-settings.h \
doveadm-util.h \
doveadm-who.h
diff -r 158be8d93ddc -r b60e225386bf src/doveadm/client-connection.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/doveadm/client-connection.c Fri Jul 23 20:37:35 2010 +0100
@@ -0,0 +1,239 @@
+/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "ioloop.h"
+#include "istream.h"
+#include "ostream.h"
+#include "strescape.h"
+#include "master-service.h"
+#include "mail-storage-service.h"
+#include "doveadm-util.h"
+#include "doveadm-server.h"
+#include "doveadm-mail.h"
+#include "doveadm-print.h"
+#include "client-connection.h"
+
+#include <unistd.h>
+
+#define MAX_INBUF_SIZE 1024
+
+struct client_connection {
+ int fd;
+ struct io *io;
+ struct istream *input;
+ struct ostream *output;
+
+ unsigned int handshaked:1;
+ unsigned int authenticated:1;
+};
+
+static bool doveadm_mail_cmd_server(const char *cmd_name, const char *username,
+ int argc, char *argv[])
+{
+ enum mail_storage_service_flags service_flags =
+ MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT |
+ MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
+ struct doveadm_mail_cmd_context *ctx;
+ const struct doveadm_mail_cmd *cmd;
+ const char *getopt_args;
+ bool add_username_header;
+ int c;
+
+ cmd = doveadm_mail_cmd_find(cmd_name);
+ if (cmd == NULL) {
+ i_error("doveadm: Client sent unknown command: %s", cmd_name);
+ return FALSE;
+ }
+
+ if (doveadm_debug)
+ service_flags |= MAIL_STORAGE_SERVICE_FLAG_DEBUG;
+
+ ctx = doveadm_mail_cmd_init(cmd);
+ getopt_args = t_strconcat("Au:", ctx->getopt_args, NULL);
+ while ((c = getopt(argc, argv, getopt_args)) > 0) {
+ switch (c) {
+ case 'A':
+ add_username_header = TRUE;
+ break;
+ case 'u':
+ if (strchr(optarg, '*') != NULL ||
+ strchr(optarg, '?') != NULL)
+ add_username_header = TRUE;
+ break;
+ default:
+ if ((ctx->v.parse_arg == NULL ||
+ !ctx->v.parse_arg(ctx, c))) {
+ i_error("doveadm %s: "
+ "Client sent unknown parameter: %c",
+ cmd->name, c);
+ ctx->v.deinit(ctx);
+ return FALSE;
+ }
+ }
+ }
+
+ argv += optind;
+ if (argv[0] != NULL && cmd->usage_args == NULL) {
+ i_error("doveadm %s: Client sent unknown parameter: %s",
+ cmd->name, argv[0]);
+ ctx->v.deinit(ctx);
+ return FALSE;
+ }
+
+ if (doveadm_print_is_initialized() && add_username_header) {
+ doveadm_print_header("username", "Username",
+ DOVEADM_PRINT_HEADER_FLAG_STICKY |
+ DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
+ doveadm_print_sticky("username", username);
+ }
+
+ ctx->v.init(ctx, (const void *)argv);
+ doveadm_mail_single_user(ctx, username, service_flags);
+ ctx->v.deinit(ctx);
+ doveadm_print_flush();
+ return !ctx->failed;
+}
+
+static bool client_handle_command(struct client_connection *conn, char **args)
+{
+ const char *flags, *username, *cmd_name;
+ unsigned int argc;
+ bool ret;
+
+ for (argc = 0; args[argc] != NULL; argc++)
+ args[argc] = str_tabunescape(args[argc]);
+
+ if (argc < 3) {
+ i_error("doveadm client: No command given");
+ return FALSE;
+ }
+ flags = args[0];
+ username = args[1];
+ cmd_name = args[2];
+ args += 3;
+ argc -= 3;
+
+ doveadm_debug = FALSE;
+ doveadm_verbose = FALSE;
+
+ for (; *flags != '\0'; flags++) {
+ switch (*flags) {
+ case 'D':
+ doveadm_debug = TRUE;
+ doveadm_verbose = TRUE;
+ break;
+ case 'v':
+ doveadm_verbose = TRUE;
+ break;
+ default:
+ i_error("doveadm client: Unknown flag: %c", *flags);
+ return FALSE;
+ }
+ }
+
+ o_stream_cork(conn->output);
+ ret = doveadm_mail_cmd_server(cmd_name, username, argc, args);
+ if (ret)
+ o_stream_send(conn->output, "\n+\n", 3);
+ else
+ o_stream_send(conn->output, "\n-\n", 3);
+ o_stream_uncork(conn->output);
+
+ /* flush the output and disconnect */
+ net_set_nonblock(conn->fd, FALSE);
+ (void)o_stream_flush(conn->output);
+ return FALSE;
+}
+
+static bool
+client_connection_authenticate(struct client_connection *conn ATTR_UNUSED)
+{
+ i_fatal("Authentication not supported yet");
+ return FALSE;
+}
+
+static void client_connection_input(struct client_connection *conn)
+{
+ const char *line;
+ bool ret = TRUE;
+
+ if (!conn->handshaked) {
+ if ((line = i_stream_read_next_line(conn->input)) == NULL) {
+ if (conn->input->eof || conn->input->stream_errno != 0)
+ client_connection_destroy(&conn);
+ return;
+ }
+
More information about the dovecot-cvs
mailing list