]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-program-client: Initialize dot streams right after the connection is established.
authorStephan Bosch <stephan.bosch@dovecot.fi>
Sun, 25 Feb 2018 10:43:04 +0000 (11:43 +0100)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Tue, 25 Jun 2019 09:22:30 +0000 (12:22 +0300)
This avoids creating the dot streams in the input/output handlers, which makes
the code cleaner and easier to port to using iostream-pump.

src/lib-program-client/program-client-private.h
src/lib-program-client/program-client-remote.c
src/lib-program-client/program-client.c

index cf4f4d14c92a17e5164b0f100833e4db4dbb304a..7abad7ed4b8e153f5ab644ec408988c2ad7b937e 100644 (file)
@@ -41,8 +41,8 @@ struct program_client {
        struct timeout *to;
        struct timeval start_time;
 
-       struct istream *input, *program_input, *dot_input;
-       struct ostream *output, *program_output, *dot_output;
+       struct istream *input, *program_input, *raw_program_input;
+       struct ostream *output, *program_output, *raw_program_output;
 
        ARRAY(struct program_client_extra_fd) extra_fds;
 
@@ -62,8 +62,6 @@ struct program_client {
        bool debug:1;
        bool disconnected:1;
        bool output_seekable:1;
-       bool input_dot_created:1;
-       bool output_dot_created:1;
        bool destroying:1;
 };
 
index 63bf8616e1b6d37aa7c2d8938bb751b6f1b8acf7..e0dd99e43b369f13ccd36471dbcfe21833122b6f 100644 (file)
@@ -234,10 +234,9 @@ program_client_remote_connected(struct program_client_remote *prclient)
        program_client_init_streams(pclient);
 
        if (!prclient->noreply) {
-               struct istream *is = pclient->program_input;
-               pclient->program_input =
-                       program_client_istream_create(pclient,
-                                                     pclient->program_input);
+               struct istream *is = pclient->raw_program_input;
+               pclient->raw_program_input =
+                       program_client_istream_create(pclient, is);
                i_stream_unref(&is);
        }
 
@@ -263,11 +262,11 @@ program_client_remote_connected(struct program_client_remote *prclient)
        }
        str_append_c(str, '\n');
 
-       if (o_stream_send(pclient->program_output,
+       if (o_stream_send(pclient->raw_program_output,
                          str_data(str), str_len(str)) < 0) {
                i_error("write(%s) failed: %s",
-                       o_stream_get_name(pclient->program_output),
-                       o_stream_get_error(pclient->program_output));
+                       o_stream_get_name(pclient->raw_program_output),
+                       o_stream_get_error(pclient->raw_program_output));
                program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
                return;
        }
@@ -554,7 +553,7 @@ program_client_remote_disconnect(struct program_client *pclient, bool force)
 
        timeout_remove(&prclient->to_retry);
 
-       if (pclient->program_input == NULL) {
+       if (pclient->raw_program_input == NULL) {
                /* nothing */
        } else if (pclient->error == PROGRAM_CLIENT_ERROR_NONE &&
                   !prclient->noreply && !force) {
@@ -563,15 +562,15 @@ program_client_remote_disconnect(struct program_client *pclient, bool force)
 
                /* Skip any remaining program output and parse the exit code */
                while (i_stream_read_more
-                       (pclient->program_input, &data, &size) > 0) {
-                       i_stream_skip(pclient->program_input, size);
+                       (pclient->raw_program_input, &data, &size) > 0) {
+                       i_stream_skip(pclient->raw_program_input, size);
                }
 
                /* Check for error and EOF. Since we're disconnected, always
                   mark an internal error when not all input is read. This is
                   generally unlikely to occur. */
-               if (pclient->program_input->stream_errno != 0 ||
-                   i_stream_have_bytes_left(pclient->program_input)) {
+               if (pclient->raw_program_input->stream_errno != 0 ||
+                   i_stream_have_bytes_left(pclient->raw_program_input)) {
                        pclient->exit_code =
                                PROGRAM_CLIENT_EXIT_INTERNAL_FAILURE;
                }
index 6bed1d58ba7943c746c829c52ce9c0534fbe6e5e..d977dfc7b5fe9da58cd93695a301c8488ed6943c 100644 (file)
@@ -92,13 +92,10 @@ program_client_disconnect_extra_fds(struct program_client *pclient)
 
 void program_client_disconnected(struct program_client *pclient)
 {
-       if (pclient->program_input != NULL) {
-               if (pclient->set.use_dotstream)
-                       i_stream_unref(&pclient->program_input);
-               else
-                       i_stream_destroy(&pclient->program_input);
-       }
+       i_stream_destroy(&pclient->program_input);
        o_stream_destroy(&pclient->program_output);
+       i_stream_destroy(&pclient->raw_program_input);
+       o_stream_destroy(&pclient->raw_program_output);
 
        io_remove(&pclient->io);
 
@@ -198,16 +195,6 @@ program_client_program_output(struct program_client *pclient)
                return ret;
        }
 
-       /* initialize dot stream if required */
-       if (!pclient->output_dot_created &&
-           pclient->set.use_dotstream &&
-           output != NULL) {
-               pclient->dot_output = o_stream_create_dot(output, FALSE);
-               pclient->output_dot_created = TRUE;
-       }
-       if (pclient->dot_output != NULL)
-               output = pclient->dot_output;
-
        if (input != NULL && output != NULL) {
                /* transfer provided input stream to output towards program */
                res = o_stream_send_istream(output, input);
@@ -247,7 +234,8 @@ program_client_program_output(struct program_client *pclient)
                }
                if (ret == 0)
                        return 0;
-               o_stream_unref(&pclient->dot_output);
+               o_stream_unref(&pclient->program_output);
+               o_stream_unref(&pclient->raw_program_output);
        }
 
        if (input == NULL) {
@@ -274,22 +262,19 @@ void program_client_program_input(struct program_client *pclient)
        int ret = 0;
 
        if (input != NULL) {
-               /* initialize dot stream if required */
-               if (!pclient->input_dot_created &&
-                   pclient->set.use_dotstream) {
-                       pclient->dot_input = i_stream_create_dot(input, FALSE);
-                       pclient->input_dot_created = TRUE;
-               }
-               if (pclient->dot_input != NULL)
-                       input = pclient->dot_input;
-
                /* transfer input from program to provided output stream */
                if (output != NULL) {
                        res = o_stream_send_istream(output, input);
                        switch (res) {
                        case OSTREAM_SEND_ISTREAM_RESULT_FINISHED:
-                               i_stream_unref(&pclient->dot_input);
-                               input = pclient->program_input;
+                               /* return to raw program input */
+                               if (pclient->program_input ==
+                                       pclient->raw_program_input)
+                                       break;
+                               i_stream_unref(&pclient->program_input);
+                               input = pclient->program_input =
+                                       pclient->raw_program_input;
+                               i_stream_ref(pclient->program_input);
                                break;
                        case OSTREAM_SEND_ISTREAM_RESULT_WAIT_INPUT:
                        case OSTREAM_SEND_ISTREAM_RESULT_WAIT_OUTPUT:
@@ -311,7 +296,7 @@ void program_client_program_input(struct program_client *pclient)
                        }
                }
 
-               /* read (the remainder of) the outer stream */
+               /* read (the remainder of) the raw program input */
                while ((ret=i_stream_read_more(input, &data, &size)) > 0)
                        i_stream_skip(input, size);
                if (ret == 0)
@@ -368,6 +353,29 @@ int program_client_connected(struct program_client *pclient)
 {
        int ret = 1;
 
+       /* finish creating program input */
+       if (pclient->raw_program_input != NULL) {
+               struct istream *input = pclient->raw_program_input;
+
+               /* initialize dot input stream if required */
+               if (pclient->set.use_dotstream)
+                       input = i_stream_create_dot(input, FALSE);
+               else
+                       i_stream_ref(input);
+               pclient->program_input = input;
+       }
+       /* finish creating program output */
+       if (pclient->raw_program_output != NULL) {
+               struct ostream *output = pclient->raw_program_output;
+
+               /* initialize dot output stream if required */
+               if (pclient->set.use_dotstream)
+                       output = o_stream_create_dot(output, FALSE);
+               else
+                       o_stream_ref(output);
+               pclient->program_output = output;
+       }
+
        pclient->start_time = ioloop_timeval;
        timeout_remove(&pclient->to);
        if (pclient->set.input_idle_timeout_msecs != 0) {
@@ -486,18 +494,22 @@ void program_client_init_streams(struct program_client *pclient)
 {
        /* Create streams for normal program I/O */
        if (pclient->fd_out >= 0) {
-               pclient->program_output =
-                       o_stream_create_fd(pclient->fd_out,
-                                          MAX_OUTPUT_BUFFER_SIZE);
-               o_stream_set_name(pclient->program_output, "program stdin");
-               o_stream_set_no_error_handling(pclient->program_output, TRUE);
+               struct ostream *program_output;
+
+               program_output = o_stream_create_fd(pclient->fd_out,
+                                                   MAX_OUTPUT_BUFFER_SIZE);
+               o_stream_set_name(program_output, "program stdin");
+               o_stream_set_no_error_handling(program_output, TRUE);
+               pclient->raw_program_output = program_output;
        }
        if (pclient->fd_in >= 0) {
-               pclient->program_input =
-                       i_stream_create_fd(pclient->fd_in, (size_t)-1);
-               i_stream_set_name(pclient->program_input, "program stdout");
+               struct istream *program_input;
+
+               program_input = i_stream_create_fd(pclient->fd_in, (size_t)-1);
+               i_stream_set_name(program_input, "program stdout");
                pclient->io = io_add(pclient->fd_in, IO_READ,
                                     program_client_program_input, pclient);
+               pclient->raw_program_input = program_input;
        }
 
        /* Create streams for additional output through side-channel fds */
@@ -534,10 +546,12 @@ void program_client_destroy(struct program_client **_pclient)
        i_assert(pclient->callback == NULL);
 
        i_stream_unref(&pclient->input);
-       i_stream_unref(&pclient->dot_input);
+       o_stream_unref(&pclient->output);
+
        i_stream_unref(&pclient->program_input);
        o_stream_unref(&pclient->program_output);
-       o_stream_unref(&pclient->output);
+       i_stream_unref(&pclient->raw_program_input);
+       o_stream_unref(&pclient->raw_program_output);
 
        io_remove(&pclient->io);