summaryrefslogtreecommitdiff
path: root/libmailutils
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2021-08-23 22:24:58 +0300
committerSergey Poznyakoff <gray@gnu.org>2021-08-23 22:45:21 +0300
commit33344f24b34711da73ece6939e79bc6037a8e23c (patch)
tree110bf9f808390fe375bb0ce2fbb27a904dedd192 /libmailutils
parent97dc3a446cd782e8cc7bce9b2e11806f7f49e1a4 (diff)
downloadmailutils-33344f24b34711da73ece6939e79bc6037a8e23c.tar.gz
mailutils-33344f24b34711da73ece6939e79bc6037a8e23c.tar.bz2
Fix handling of MU_IOCTL_SUBSTREAM in iostream
* libmailutils/stream/iostream.c (_iostream_ctl): Fix handling of MU_IOCTL_SUBSTREAM (get/set) requests. * imap4d/io.c (io_setio): Unreference the source stream. (imap4d_init_tls_server): Fix reference decrement for tlsstream. * pop3d/extra.c (pop3d_setio): Unreference the source stream. (pop3d_init_tls_server): Fix reference decrement for tlsstream.
Diffstat (limited to 'libmailutils')
-rw-r--r--libmailutils/stream/iostream.c112
1 files changed, 112 insertions, 0 deletions
diff --git a/libmailutils/stream/iostream.c b/libmailutils/stream/iostream.c
index 0f7b767b5..793c2e9ea 100644
--- a/libmailutils/stream/iostream.c
+++ b/libmailutils/stream/iostream.c
@@ -114,6 +114,100 @@ _iostream_done (struct _mu_stream *str)
}
static int
+_iostream_get_substream (struct _mu_iostream *sp, mu_stream_t *pstr)
+{
+ mu_stream_t tmp[2], instream;
+ int status;
+
+ status = mu_stream_ioctl (sp->transport[MU_TRANSPORT_INPUT],
+ MU_IOCTL_SUBSTREAM, MU_IOCTL_OP_GET, tmp);
+ if (status == ENOSYS)
+ {
+ instream = sp->transport[MU_TRANSPORT_INPUT];
+ mu_stream_ref (instream);
+ status = 0;
+ }
+ else if (status == 0)
+ {
+ mu_stream_unref (tmp[MU_TRANSPORT_OUTPUT]);
+ instream = tmp[MU_TRANSPORT_INPUT];
+ }
+
+ if (status == 0)
+ {
+ status = mu_stream_ioctl (sp->transport[MU_TRANSPORT_OUTPUT],
+ MU_IOCTL_SUBSTREAM, MU_IOCTL_OP_GET, tmp);
+ if (status == 0)
+ {
+ mu_stream_unref (tmp[MU_TRANSPORT_INPUT]);
+ pstr[MU_TRANSPORT_INPUT] = instream;
+ pstr[MU_TRANSPORT_OUTPUT] = tmp[MU_TRANSPORT_OUTPUT];
+ }
+ else if (status == ENOSYS)
+ {
+ pstr[MU_TRANSPORT_INPUT] = instream;
+ pstr[MU_TRANSPORT_OUTPUT] = sp->transport[MU_TRANSPORT_OUTPUT];
+ mu_stream_ref (pstr[MU_TRANSPORT_OUTPUT]);
+ status = 0;
+ }
+ else
+ mu_stream_unref (instream);
+ }
+ return status;
+}
+
+static int
+_iostream_set_substream (struct _mu_iostream *sp, mu_stream_t *newstr)
+{
+ mu_stream_t saved[2], tmp[2];
+ int status;
+
+ status = _iostream_get_substream (sp, tmp);
+ if (status)
+ return status;
+ saved[MU_TRANSPORT_INPUT] = tmp[MU_TRANSPORT_INPUT];
+ saved[MU_TRANSPORT_OUTPUT] = tmp[MU_TRANSPORT_OUTPUT];
+
+ tmp[MU_TRANSPORT_INPUT] = newstr[MU_TRANSPORT_INPUT];
+ tmp[MU_TRANSPORT_OUTPUT] = NULL;
+ status = mu_stream_ioctl (sp->transport[MU_TRANSPORT_INPUT],
+ MU_IOCTL_SUBSTREAM, MU_IOCTL_OP_SET, tmp);
+ if (status == ENOSYS)
+ {
+ mu_stream_unref (sp->transport[MU_TRANSPORT_INPUT]);
+ sp->transport[MU_TRANSPORT_INPUT] = newstr[MU_TRANSPORT_INPUT];
+ mu_stream_ref (sp->transport[MU_TRANSPORT_INPUT]);
+ status = 0;
+ }
+
+ if (status == 0)
+ {
+ tmp[MU_TRANSPORT_INPUT] = NULL;
+ tmp[MU_TRANSPORT_OUTPUT] = newstr[MU_TRANSPORT_OUTPUT];
+ status = mu_stream_ioctl (sp->transport[MU_TRANSPORT_OUTPUT],
+ MU_IOCTL_SUBSTREAM, MU_IOCTL_OP_SET, tmp);
+ if (status == ENOSYS)
+ {
+ mu_stream_unref (sp->transport[MU_TRANSPORT_OUTPUT]);
+ sp->transport[MU_TRANSPORT_OUTPUT] = newstr[MU_TRANSPORT_OUTPUT];
+ mu_stream_ref (sp->transport[MU_TRANSPORT_OUTPUT]);
+ status = 0;
+ }
+ else
+ {
+ tmp[MU_TRANSPORT_INPUT] = saved[MU_TRANSPORT_INPUT];
+ tmp[MU_TRANSPORT_OUTPUT] = NULL;
+ status = mu_stream_ioctl (sp->transport[MU_TRANSPORT_INPUT],
+ MU_IOCTL_SUBSTREAM, MU_IOCTL_OP_SET, tmp);
+ }
+ }
+
+ mu_stream_unref (saved[MU_TRANSPORT_INPUT]);
+ mu_stream_unref (saved[MU_TRANSPORT_OUTPUT]);
+ return status;
+}
+
+static int
_iostream_ctl (struct _mu_stream *str, int code, int opcode, void *arg)
{
struct _mu_iostream *sp = (struct _mu_iostream *)str;
@@ -147,6 +241,24 @@ _iostream_ctl (struct _mu_stream *str, int code, int opcode, void *arg)
break;
case MU_IOCTL_SUBSTREAM:
+ if (!arg)
+ return EINVAL;
+ else
+ {
+ switch (opcode)
+ {
+ case MU_IOCTL_OP_GET:
+ return _iostream_get_substream (sp, arg);
+
+ case MU_IOCTL_OP_SET:
+ return _iostream_set_substream (sp, arg);
+
+ default:
+ return EINVAL;
+ }
+ }
+ break;
+
case MU_IOCTL_TOPSTREAM:
if (!arg)
return EINVAL;

Return to:

Send suggestions and report system problems to the System administrator.