changeset 15593:e0d4d8f9d097

replicator: Send only one sync command to doveadm-server per connection. This fixes setuid()/setgid() problems when multiple UIDs are used.
author Timo Sirainen <tss@iki.fi>
date Tue, 08 Jan 2013 07:42:38 +0200
parents 0949ddc3a892
children 5bb80a6491eb
files src/replication/replicator/doveadm-connection.c
diffstat 1 files changed, 16 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/replication/replicator/doveadm-connection.c	Tue Jan 08 06:41:56 2013 +0200
+++ b/src/replication/replicator/doveadm-connection.c	Tue Jan 08 07:42:38 2013 +0200
@@ -29,6 +29,7 @@
 	time_t last_connect_failure;
 	unsigned int handshaked:1;
 	unsigned int end_of_print:1;
+	unsigned int cmd_sent:1;
 };
 
 struct doveadm_connection *doveadm_connection_init(const char *path)
@@ -55,7 +56,7 @@
 	callback(reply, context);
 }
 
-static void doveadm_disconnect(struct doveadm_connection *conn)
+static void doveadm_close(struct doveadm_connection *conn)
 {
 	if (conn->fd == -1)
 		return;
@@ -66,7 +67,13 @@
 	if (close(conn->fd) < 0)
 		i_error("close(doveadm) failed: %m");
 	conn->fd = -1;
+	conn->end_of_print = FALSE;
+	conn->cmd_sent = FALSE;
+}
 
+static void doveadm_disconnect(struct doveadm_connection *conn)
+{
+	doveadm_close(conn);
 	if (conn->callback != NULL)
 		doveadm_callback(conn, DOVEADM_REPLY_FAIL);
 }
@@ -102,6 +109,9 @@
 			conn->end_of_print = TRUE;
 		return 0;
 	}
+	line = t_strdup(line);
+	doveadm_close(conn);
+
 	if (line[0] == '+')
 		doveadm_callback(conn, DOVEADM_REPLY_OK);
 	else if (line[0] == '-') {
@@ -113,9 +123,9 @@
 		i_error("%s: Invalid input: %s", conn->path, line);
 		return -1;
 	}
-	conn->end_of_print = FALSE;
 	/* FIXME: disconnect after each request for now.
-	   doveadm server's getopt() handling seems to break otherwise */
+	   doveadm server's getopt() handling seems to break otherwise.
+	   also with multiple UIDs doveadm-server fails because setid() fails */
 	return -1;
 }
 
@@ -158,7 +168,7 @@
 
 static void doveadm_fail_timeout(struct doveadm_connection *conn)
 {
-	doveadm_callback(conn, DOVEADM_REPLY_FAIL);
+	doveadm_disconnect(conn);
 }
 
 void doveadm_connection_sync(struct doveadm_connection *conn,
@@ -170,6 +180,7 @@
 	i_assert(callback != NULL);
 	i_assert(!doveadm_connection_is_busy(conn));
 
+	conn->cmd_sent = TRUE;
 	conn->callback = callback;
 	conn->context = context;
 
@@ -192,5 +203,5 @@
 
 bool doveadm_connection_is_busy(struct doveadm_connection *conn)
 {
-	return conn->callback != NULL;
+	return conn->cmd_sent;
 }