dovecot-2.2-pigeonhole: sieve_extprograms plugin: Changed progra...

pigeonhole at rename-it.nl pigeonhole at rename-it.nl
Wed Dec 25 22:51:30 EET 2013


details:   http://hg.rename-it.nl/dovecot-2.2-pigeonhole/rev/9448c8ae2f15
changeset: 1829:9448c8ae2f15
user:      Stephan Bosch <stephan at rename-it.nl>
date:      Wed Dec 25 21:45:47 2013 +0100
description:
sieve_extprograms plugin: Changed program client such that the filter command only needs to create a temporary file when the program output is very large.
This commit also includes a small change that makes it possible to run a program several times.

diffstat:

 src/lib-sieve/util/program-client-local.c                |    8 +-
 src/lib-sieve/util/program-client-private.h              |    4 +-
 src/lib-sieve/util/program-client-remote.c               |    3 +-
 src/lib-sieve/util/program-client.c                      |   98 +++++++++++-
 src/lib-sieve/util/program-client.h                      |    5 +
 src/plugins/sieve-extprograms/cmd-filter.c               |  112 ++++----------
 src/plugins/sieve-extprograms/sieve-extprograms-common.c |   18 ++
 src/plugins/sieve-extprograms/sieve-extprograms-common.h |    5 +
 8 files changed, 157 insertions(+), 96 deletions(-)

diffs (truncated from 469 to 300 lines):

diff -r 2a8bb622f17e -r 9448c8ae2f15 src/lib-sieve/util/program-client-local.c
--- a/src/lib-sieve/util/program-client-local.c	Wed Dec 25 21:42:05 2013 +0100
+++ b/src/lib-sieve/util/program-client-local.c	Wed Dec 25 21:45:47 2013 +0100
@@ -82,7 +82,8 @@
 		(struct program_client_local *) pclient;
 	int fd[2] = { -1, -1 };
 
-	if ( pclient->input != NULL || pclient->output != NULL ) {
+	if ( pclient->input != NULL || pclient->output != NULL ||
+		pclient->output_seekable ) {
 		if ( socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0 ) {
 			i_error("socketpair() failed: %m");
 			return -1;
@@ -114,7 +115,7 @@
 
 		exec_child(pclient->path, pclient->args, envs,
 			( pclient->input != NULL ? fd[0] : -1 ),
-			( pclient->output != NULL ? fd[0] : -1 ));
+			( pclient->output != NULL || pclient->output_seekable ? fd[0] : -1 ));
 		i_unreached();
 	}
 
@@ -125,7 +126,8 @@
 
 	if ( fd[1] >= 0 ) {
 		net_set_nonblock(fd[1], TRUE);
-		pclient->fd_in = ( pclient->output != NULL ? fd[1] : -1 );
+		pclient->fd_in =
+			( pclient->output != NULL || pclient->output_seekable ? fd[1] : -1 );
 		pclient->fd_out = ( pclient->input != NULL ? fd[1] : -1 );
 	}
 	program_client_init_streams(pclient);
diff -r 2a8bb622f17e -r 9448c8ae2f15 src/lib-sieve/util/program-client-private.h
--- a/src/lib-sieve/util/program-client-private.h	Wed Dec 25 21:42:05 2013 +0100
+++ b/src/lib-sieve/util/program-client-private.h	Wed Dec 25 21:45:47 2013 +0100
@@ -28,8 +28,9 @@
 	struct timeout *to;
 	time_t start_time;
 
-	struct istream *input, *program_input;
+	struct istream *input, *program_input, *seekable_output;
 	struct ostream *output, *program_output;
+	char *temp_prefix;
 
 	enum program_client_error error;
 	int exit_code;
@@ -42,6 +43,7 @@
 	
 	unsigned int debug:1;
 	unsigned int disconnected:1;
+	unsigned int output_seekable:1;
 };
 
 void program_client_init
diff -r 2a8bb622f17e -r 9448c8ae2f15 src/lib-sieve/util/program-client-remote.c
--- a/src/lib-sieve/util/program-client-remote.c	Wed Dec 25 21:42:05 2013 +0100
+++ b/src/lib-sieve/util/program-client-remote.c	Wed Dec 25 21:45:47 2013 +0100
@@ -234,7 +234,8 @@
 
 	net_set_nonblock(fd, TRUE);
 	
-	pclient->fd_in = ( slclient->noreply && pclient->output == NULL ? -1 : fd );
+	pclient->fd_in = ( slclient->noreply && pclient->output == NULL &&
+		!pclient->output_seekable ? -1 : fd );
 	pclient->fd_out = fd;
 	pclient->io = io_add(fd, IO_WRITE, program_client_remote_connected, pclient);
 	return 1;
diff -r 2a8bb622f17e -r 9448c8ae2f15 src/lib-sieve/util/program-client.c
--- a/src/lib-sieve/util/program-client.c	Wed Dec 25 21:42:05 2013 +0100
+++ b/src/lib-sieve/util/program-client.c	Wed Dec 25 21:45:47 2013 +0100
@@ -4,14 +4,18 @@
 #include "lib.h"
 #include "ioloop.h"
 #include "array.h"
+#include "str.h"
+#include "safe-mkstemp.h"
 #include "istream-private.h"
+#include "istream-seekable.h"
 #include "ostream.h"
 
 #include "program-client-private.h"
 
 #include <unistd.h>
 
-#define MAX_OUTBUF_SIZE 16384
+#define MAX_OUTPUT_BUFFER_SIZE 16384
+#define MAX_OUTPUT_MEMORY_BUFFER (1024*128)
 
 static void program_client_timeout(struct program_client *pclient)
 {
@@ -35,7 +39,6 @@
 		program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
 		return -1;
 	}
-
 	return 1;
 }
 
@@ -69,8 +72,12 @@
 	if ( (ret=pclient->disconnect(pclient, force)) < 0 )
 		error = TRUE;
 
-	if ( pclient->program_input != NULL )
-		i_stream_destroy(&pclient->program_input);
+	if ( pclient->program_input != NULL ) {
+		if (pclient->output_seekable)
+			i_stream_unref(&pclient->program_input);
+		else
+			i_stream_destroy(&pclient->program_input);
+	} 
 	if ( pclient->program_output != NULL )
 		o_stream_destroy(&pclient->program_output);
 
@@ -239,7 +246,7 @@
 void program_client_set_input
 (struct program_client *pclient, struct istream *input)
 {
-	if ( pclient->input )
+	if ( pclient->input != NULL )
 		i_stream_unref(&pclient->input);
 	if ( input != NULL )
 		i_stream_ref(input);
@@ -249,11 +256,33 @@
 void program_client_set_output
 (struct program_client *pclient, struct ostream *output)
 {
-	if ( pclient->output )
+	if ( pclient->output != NULL )
 		o_stream_unref(&pclient->output);
 	if ( output != NULL )
 		o_stream_ref(output);
 	pclient->output = output;
+	pclient->output_seekable = FALSE;
+	i_free(pclient->temp_prefix);
+}
+
+void program_client_set_output_seekable
+(struct program_client *pclient, const char *temp_prefix)
+{
+	if ( pclient->output != NULL )
+		o_stream_unref(&pclient->output);
+	pclient->temp_prefix = i_strdup(temp_prefix);
+	pclient->output_seekable = TRUE;
+}
+
+struct istream *program_client_get_output_seekable
+(struct program_client *pclient)
+{
+	struct istream *input = pclient->seekable_output;
+	
+	pclient->seekable_output = NULL;
+
+	i_stream_seek(input, 0);
+	return input;
 }
 
 void program_client_set_env
@@ -268,15 +297,56 @@
 	array_append(&pclient->envs, &env, 1);
 }
 
+static int program_client_seekable_fd_callback
+(const char **path_r, void *context)
+{
+	struct program_client *pclient = (struct program_client *)context;
+	string_t *path;
+	int fd;
+
+	path = t_str_new(128);
+	str_append(path, pclient->temp_prefix);
+	fd = safe_mkstemp(path, 0600, (uid_t)-1, (gid_t)-1);
+	if (fd == -1) {
+		i_error("safe_mkstemp(%s) failed: %m", str_c(path));
+		return -1;
+	}
+
+	/* we just want the fd, unlink it */
+	if (unlink(str_c(path)) < 0) {
+		/* shouldn't happen.. */
+		i_error("unlink(%s) failed: %m", str_c(path));
+		i_close_fd(&fd);
+		return -1;
+	}
+
+	*path_r = str_c(path);
+	return fd;
+}
+
 void program_client_init_streams(struct program_client *pclient)
 {
 	if ( pclient->fd_out >= 0 ) {
 		pclient->program_output =
-			o_stream_create_fd(pclient->fd_out, MAX_OUTBUF_SIZE, FALSE);
+			o_stream_create_fd(pclient->fd_out, MAX_OUTPUT_BUFFER_SIZE, FALSE);
 	}
 	if ( pclient->fd_in >= 0 ) {
-		pclient->program_input =
-			i_stream_create_fd(pclient->fd_in, (size_t)-1, FALSE);
+		struct istream *input;
+		
+		input = i_stream_create_fd(pclient->fd_in, (size_t)-1, FALSE);
+
+		if (pclient->output_seekable) {
+			struct istream *input2 = input, *input_list[2];
+	
+			input_list[0] = input2; input_list[1] = NULL;
+			input = i_stream_create_seekable(input_list, MAX_OUTPUT_MEMORY_BUFFER,
+						 program_client_seekable_fd_callback, pclient);
+			i_stream_unref(&input2);
+			pclient->seekable_output = input;
+			i_stream_ref(pclient->seekable_output);
+		}
+
+		pclient->program_input = input;
 		pclient->io = io_add
 			(pclient->fd_in, IO_READ, program_client_program_input, pclient);
 	}
@@ -292,11 +362,13 @@
 		i_stream_unref(&pclient->input);
 	if ( pclient->output != NULL )
 		o_stream_unref(&pclient->output);
+	if ( pclient->input != NULL )
+		i_stream_unref(&pclient->seekable_output);
 	if ( pclient->io != NULL )
 		io_remove(&pclient->io);
 	if ( pclient->ioloop != NULL )
 		io_loop_destroy(&pclient->ioloop);
-
+	i_free(pclient->temp_prefix);
 	pool_unref(&pclient->pool);
 	*_pclient = NULL;
 }
@@ -305,6 +377,12 @@
 {
 	int ret;
 
+	/* reset */
+	pclient->disconnected = FALSE;
+	pclient->exit_code = 0;
+	pclient->error = PROGRAM_CLIENT_ERROR_NONE;
+
+
 	pclient->ioloop = io_loop_create();
 
 	if ( program_client_connect(pclient) >= 0 ) {
diff -r 2a8bb622f17e -r 9448c8ae2f15 src/lib-sieve/util/program-client.h
--- a/src/lib-sieve/util/program-client.h	Wed Dec 25 21:42:05 2013 +0100
+++ b/src/lib-sieve/util/program-client.h	Wed Dec 25 21:45:47 2013 +0100
@@ -26,6 +26,11 @@
 void program_client_set_output
 	(struct program_client *pclient, struct ostream *output);
 
+void program_client_set_output_seekable
+	(struct program_client *pclient, const char *temp_prefix);
+struct istream *program_client_get_output_seekable
+	(struct program_client *pclient);
+
 void program_client_set_env
 	(struct program_client *pclient, const char *name, const char *value);
 
diff -r 2a8bb622f17e -r 9448c8ae2f15 src/plugins/sieve-extprograms/cmd-filter.c
--- a/src/plugins/sieve-extprograms/cmd-filter.c	Wed Dec 25 21:42:05 2013 +0100
+++ b/src/plugins/sieve-extprograms/cmd-filter.c	Wed Dec 25 21:45:47 2013 +0100
@@ -121,38 +121,6 @@
  * Code execution
  */
 
-static int cmd_filter_get_tempfile
-(const struct sieve_runtime_env *renv)
-{
-	struct sieve_instance *svinst = renv->svinst;
-	struct mail_user *mail_user = renv->scriptenv->user;
-	string_t *path;
-	int fd;
-
-	path = t_str_new(128);
-	mail_user_set_get_temp_prefix(path, mail_user->set);
-	fd = safe_mkstemp(path, 0600, (uid_t)-1, (gid_t)-1);
-	if (fd == -1) {
-		sieve_sys_error(svinst, "filter action: "
-			"safe_mkstemp(%s) failed: %m", str_c(path));
-		return -1;
-	}
-
-	/* We just want the fd, unlink it */
-	if (unlink(str_c(path)) < 0) {
-		/* Shouldn't happen.. */
-		sieve_sys_error(svinst, "filter action: "
-			"unlink(%s) failed: %m", str_c(path));
-		if ( close(fd) < 0 ) {
-			sieve_sys_error(svinst, "filter action: "
-				"close(%s) failed after error: %m", str_c(path));
-		}
-		return -1;
-	}
-
-	return fd;
-}
-
 static int cmd_filter_operation_execute


More information about the dovecot-cvs mailing list