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