dovecot-2.1: dsync: Added dsync_remote_cmd setting, which is use...

dovecot at dovecot.org dovecot at dovecot.org
Fri Mar 2 14:18:42 EET 2012


details:   http://hg.dovecot.org/dovecot-2.1/rev/69ed88beb12f
changeset: 14215:69ed88beb12f
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Mar 02 14:18:29 2012 +0200
description:
dsync: Added dsync_remote_cmd setting, which is used to execute remote dsync.
This is used for the old style "host" and "mailuser at host" parameters, as
well as for a new "remote:[user@]host" parameter.

diffstat:

 src/doveadm/doveadm-settings.c    |    2 +
 src/doveadm/doveadm-settings.h    |    1 +
 src/doveadm/dsync/doveadm-dsync.c |  165 +++++++++++++++++++++++++++----------
 3 files changed, 122 insertions(+), 46 deletions(-)

diffs (284 lines):

diff -r 523a6f3e0713 -r 69ed88beb12f src/doveadm/doveadm-settings.c
--- a/src/doveadm/doveadm-settings.c	Fri Mar 02 14:06:18 2012 +0200
+++ b/src/doveadm/doveadm-settings.c	Fri Mar 02 14:18:29 2012 +0200
@@ -61,6 +61,7 @@
 	DEF(SET_STR, doveadm_password),
 	DEF(SET_STR, doveadm_allowed_commands),
 	DEF(SET_STR, dsync_alt_char),
+	DEF(SET_STR, dsync_remote_cmd),
 
 	{ SET_STRLIST, "plugin", offsetof(struct doveadm_settings, plugin_envs), NULL },
 
@@ -77,6 +78,7 @@
 	.doveadm_password = "",
 	.doveadm_allowed_commands = "",
 	.dsync_alt_char = "_",
+	.dsync_remote_cmd = "ssh -l%{login} %{host} doveadm dsync-server -u%u -l%{lock_timeout}",
 
 	.plugin_envs = ARRAY_INIT
 };
diff -r 523a6f3e0713 -r 69ed88beb12f src/doveadm/doveadm-settings.h
--- a/src/doveadm/doveadm-settings.h	Fri Mar 02 14:06:18 2012 +0200
+++ b/src/doveadm/doveadm-settings.h	Fri Mar 02 14:18:29 2012 +0200
@@ -11,6 +11,7 @@
 	const char *doveadm_password;
 	const char *doveadm_allowed_commands;
 	const char *dsync_alt_char;
+	const char *dsync_remote_cmd;
 
 	ARRAY_DEFINE(plugin_envs, const char *);
 };
diff -r 523a6f3e0713 -r 69ed88beb12f src/doveadm/dsync/doveadm-dsync.c
--- a/src/doveadm/dsync/doveadm-dsync.c	Fri Mar 02 14:06:18 2012 +0200
+++ b/src/doveadm/dsync/doveadm-dsync.c	Fri Mar 02 14:18:29 2012 +0200
@@ -4,6 +4,8 @@
 #include "lib-signals.h"
 #include "array.h"
 #include "execv-const.h"
+#include "str.h"
+#include "var-expand.h"
 #include "settings-parser.h"
 #include "master-service.h"
 #include "mail-storage-service.h"
@@ -28,7 +30,6 @@
 	enum dsync_brain_flags brain_flags;
 	const char *mailbox;
 
-	const char *const *remote_cmd_args;
 	const char *local_location;
 
 	int fd_in, fd_out, fd_err;
@@ -38,9 +39,9 @@
 
 	unsigned int lock:1;
 	unsigned int reverse_workers:1;
+	unsigned int remote:1;
 };
 
-static const char *ssh_cmd = "ssh";
 static bool legacy_dsync = FALSE;
 
 static void remote_error_input(struct dsync_cmd_context *ctx)
@@ -128,12 +129,61 @@
 	*cmd_args_r = array_idx(&cmd_args, 0);
 }
 
+static const char *const *
+get_ssh_cmd_args(struct dsync_cmd_context *ctx,
+		 const char *host, const char *login, const char *mail_user)
+{
+	static struct var_expand_table static_tab[] = {
+		{ 'u', NULL, "user" },
+		{ '\0', NULL, "login" },
+		{ '\0', NULL, "host" },
+		{ '\0', NULL, "lock_timeout" },
+		{ '\0', NULL, NULL }
+	};
+	struct var_expand_table *tab;
+	ARRAY_TYPE(const_string) cmd_args;
+	string_t *str, *str2;
+	const char *value, *const *args;
+
+	tab = t_malloc(sizeof(static_tab));
+	memcpy(tab, static_tab, sizeof(static_tab));
+
+	tab[0].value = mail_user;
+	tab[1].value = login;
+	tab[2].value = host;
+	tab[3].value = dec2str(ctx->lock_timeout);
+
+	t_array_init(&cmd_args, 8);
+	str = t_str_new(128);
+	str2 = t_str_new(128);
+	args = t_strsplit(doveadm_settings->dsync_remote_cmd, " ");
+	for (; *args != NULL; args++) {
+		if (strchr(*args, '%') == NULL)
+			value = *args;
+		else {
+			/* some automation: if parameter's all %variables
+			   expand to empty, but the %variable isn't the only
+			   text in the parameter, skip it. */
+			str_truncate(str, 0);
+			str_truncate(str2, 0);
+			var_expand(str, *args, tab);
+			var_expand(str2, *args, static_tab);
+			if (strcmp(str_c(str), str_c(str2)) == 0 &&
+			    str_len(str) > 0)
+				continue;
+			value = t_strdup(str_c(str));
+		}
+		array_append(&cmd_args, &value, 1);
+	}
+	(void)array_append_space(&cmd_args);
+	return array_idx(&cmd_args, 0);
+}
+
 static bool mirror_get_remote_cmd(struct dsync_cmd_context *ctx,
-				  const char *const *argv, const char *user,
+				  const char *user,
 				  const char *const **cmd_args_r)
 {
-	ARRAY_TYPE(const_string) cmd_args;
-	const char *p, *host;
+	const char *p, *host, *const *argv = ctx->ctx.args;
 
 	if (argv[1] != NULL) {
 		/* more than one parameter, so it contains a full command
@@ -170,21 +220,7 @@
 
 	/* we'll assume virtual users, so in user at host it really means not to
 	   give ssh a username, but to give dsync -u user parameter. */
-	t_array_init(&cmd_args, 8);
-	array_append(&cmd_args, &ssh_cmd, 1);
-	array_append(&cmd_args, &host, 1);
-	p = "doveadm"; array_append(&cmd_args, &p, 1);
-	p = "dsync-server"; array_append(&cmd_args, &p, 1);
-	if (ctx->lock) {
-		p = "-l"; array_append(&cmd_args, &p, 1);
-		p = dec2str(ctx->lock_timeout); array_append(&cmd_args, &p, 1);
-	}
-	if (*user != '\0') {
-		p = "-u"; array_append(&cmd_args, &p, 1);
-		array_append(&cmd_args, &user, 1);
-	}
-	(void)array_append_space(&cmd_args);
-	*cmd_args_r = array_idx(&cmd_args, 0);
+	*cmd_args_r = get_ssh_cmd_args(ctx, host, "", user);
 	return TRUE;
 }
 
@@ -241,6 +277,22 @@
 	return dsync_worker_init_proxy_client(ctx->fd_in, ctx->fd_out);
 }
 
+static const char *const *
+parse_ssh_location(struct dsync_cmd_context *ctx,
+		   const char *location, const char *username)
+{
+	const char *host, *login;
+
+	host = strchr(location, '@');
+	if (host != NULL)
+		login = t_strdup_until(location, host++);
+	else {
+		host = location;
+		login = "";
+	}
+	return get_ssh_cmd_args(ctx, host, login, username);
+}
+
 static int dsync_lock(struct mail_user *user, unsigned int lock_timeout,
 		      const char **path_r, struct file_lock **lock_r)
 {
@@ -282,7 +334,7 @@
 	/* create and run the brain */
 	brain = dsync_brain_init(worker1, worker2, ctx->mailbox,
 				 ctx->brain_flags);
-	if (ctx->remote_cmd_args == NULL)
+	if (!ctx->remote)
 		dsync_brain_sync_all(brain);
 	else {
 		dsync_brain_sync(brain);
@@ -315,7 +367,7 @@
 
 	/* create workers */
 	worker1 = dsync_worker_init_local(user, *_ctx->set->dsync_alt_char);
-	if (ctx->remote_cmd_args == NULL)
+	if (!ctx->remote)
 		worker2 = cmd_dsync_run_local(ctx, user);
 	else
 		worker2 = cmd_dsync_run_remote(ctx, user);
@@ -350,15 +402,54 @@
 	return ret;
 }
 
+static int cmd_dsync_prerun(struct doveadm_mail_cmd_context *_ctx,
+			    struct mail_storage_service_user *service_user,
+			    const char **error_r ATTR_UNUSED)
+{
+	struct dsync_cmd_context *ctx = (struct dsync_cmd_context *)_ctx;
+	const char *const *remote_cmd_args = NULL;
+	const struct mail_user_settings *user_set;
+	const char *username = "";
+
+	user_set = mail_storage_service_user_get_set(service_user)[0];
+
+	ctx->fd_in = STDIN_FILENO;
+	ctx->fd_out = STDOUT_FILENO;
+	ctx->fd_err = -1;
+	ctx->remote = FALSE;
+
+	/* if we're executing remotely, give -u parameter if we also
+	   did a userdb lookup. */
+	if ((_ctx->service_flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0)
+		username = _ctx->cur_username;
+
+	if (!mirror_get_remote_cmd(ctx, username, &remote_cmd_args)) {
+		/* it's a mail_location */
+		if (_ctx->args[1] != NULL)
+			doveadm_mail_help_name(_ctx->cmd->name);
+		ctx->local_location = _ctx->args[0];
+	}
+
+	if (remote_cmd_args == NULL && ctx->local_location != NULL &&
+	    strncmp(ctx->local_location, "remote:", 7) == 0) {
+		/* this is a remote (ssh) command */
+		remote_cmd_args = parse_ssh_location(ctx, ctx->local_location+7,
+						     _ctx->cur_username);
+	}
+
+	if (remote_cmd_args != NULL) {
+		/* do this before mail_storage_service_next() in case it
+		   drops process privileges */
+		run_cmd(ctx, remote_cmd_args);
+		ctx->remote = TRUE;
+	}
+	return 0;
+}
+
 static void cmd_dsync_init(struct doveadm_mail_cmd_context *_ctx,
 			   const char *const args[])
 {
 	struct dsync_cmd_context *ctx = (struct dsync_cmd_context *)_ctx;
-	const char *username = "";
-
-	ctx->fd_in = STDIN_FILENO;
-	ctx->fd_out = STDOUT_FILENO;
-	ctx->fd_err = -1;
 
 	if (args[0] == NULL)
 		doveadm_mail_help_name(_ctx->cmd->name);
@@ -367,25 +458,6 @@
 
 	if (doveadm_debug || doveadm_verbose)
 		ctx->brain_flags |= DSYNC_BRAIN_FLAG_VERBOSE;
-
-	/* if we're executing remotely, give -u parameter if we also
-	   did a userdb lookup. this works only when we're handling a
-	   single user */
-	if ((_ctx->service_flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0 &&
-	    _ctx->cur_username != NULL)
-		username = _ctx->cur_username;
-	if (!mirror_get_remote_cmd(ctx, args, username, &ctx->remote_cmd_args)) {
-		/* it's a mail_location */
-		if (args[1] != NULL)
-			doveadm_mail_help_name(_ctx->cmd->name);
-		ctx->local_location = args[0];
-	}
-
-	if (ctx->remote_cmd_args != NULL) {
-		/* do this before mail_storage_service_next() in case it
-		   drops process privileges */
-		run_cmd(ctx, ctx->remote_cmd_args);
-	}
 }
 
 static void cmd_dsync_preinit(struct doveadm_mail_cmd_context *ctx)
@@ -433,6 +505,7 @@
 	ctx->ctx.v.parse_arg = cmd_mailbox_dsync_parse_arg;
 	ctx->ctx.v.preinit = cmd_dsync_preinit;
 	ctx->ctx.v.init = cmd_dsync_init;
+	ctx->ctx.v.prerun = cmd_dsync_prerun;
 	ctx->ctx.v.run = cmd_dsync_run;
 	return &ctx->ctx;
 }


More information about the dovecot-cvs mailing list