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