summaryrefslogtreecommitdiff
path: root/libmailutils/stream/iostream.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmailutils/stream/iostream.c')
-rw-r--r--libmailutils/stream/iostream.c152
1 files changed, 135 insertions, 17 deletions
diff --git a/libmailutils/stream/iostream.c b/libmailutils/stream/iostream.c
index 4e03fe647..0b9c451f0 100644
--- a/libmailutils/stream/iostream.c
+++ b/libmailutils/stream/iostream.c
@@ -1,5 +1,5 @@
/* GNU Mailutils -- a suite of utilities for electronic mail
- Copyright (C) 2010-2019 Free Software Foundation, Inc.
+ Copyright (C) 2010-2024 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
@@ -43,18 +43,6 @@ _iostream_read (struct _mu_stream *str, char *buf, size_t bufsize,
}
static int
-_iostream_readdelim (struct _mu_stream *str, char *buf, size_t bufsize,
- int delim, size_t *pnread)
-{
- struct _mu_iostream *sp = (struct _mu_iostream *)str;
- int rc = mu_stream_readdelim (sp->transport[_MU_STREAM_INPUT], buf,
- bufsize, delim, pnread);
- if (rc)
- sp->last_err_str = _MU_STREAM_INPUT;
- return rc;
-}
-
-static int
_iostream_write (struct _mu_stream *str, const char *buf, size_t bufsize,
size_t *pnwrite)
{
@@ -126,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;
@@ -159,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;
@@ -202,7 +302,9 @@ _iostream_ctl (struct _mu_stream *str, int code, int opcode, void *arg)
}
case MU_IOCTL_TCPSTREAM:
- return mu_stream_ioctl (sp->transport[0], code, opcode, arg);
+ case MU_IOCTL_TIMEOUT:
+ //FIXME: what about output stream?
+ return mu_stream_ioctl (sp->transport[_MU_STREAM_INPUT], code, opcode, arg);
default:
return ENOSYS;
@@ -262,6 +364,20 @@ _iostream_error_string (struct _mu_stream *str, int rc)
return mu_strerror (rc);
}
+static void
+_iostream_event (struct _mu_stream *str, int code,
+ unsigned long lval, void *pval)
+{
+ struct _mu_iostream *sp = (struct _mu_iostream *)str;
+ if (code == _MU_STR_EVENT_CLRFLAG && lval == _MU_STR_ERR)
+ {
+ if (sp->transport[_MU_STREAM_INPUT])
+ mu_stream_clearerr (sp->transport[_MU_STREAM_INPUT]);
+ if (sp->transport[_MU_STREAM_OUTPUT])
+ mu_stream_clearerr (sp->transport[_MU_STREAM_OUTPUT]);
+ }
+}
+
int
mu_iostream_create (mu_stream_t *pref, mu_stream_t in, mu_stream_t out)
{
@@ -275,8 +391,6 @@ mu_iostream_create (mu_stream_t *pref, mu_stream_t in, mu_stream_t out)
sp->stream.flags |= _MU_STR_OPEN;
sp->stream.read = _iostream_read;
- if (in->readdelim)
- sp->stream.readdelim = _iostream_readdelim;
sp->stream.write = _iostream_write;
sp->stream.flush = _iostream_flush;
sp->stream.open = _iostream_open;
@@ -286,9 +400,13 @@ mu_iostream_create (mu_stream_t *pref, mu_stream_t in, mu_stream_t out)
sp->stream.wait = _iostream_wait;
sp->stream.shutdown = _iostream_shutdown;
sp->stream.error_string = _iostream_error_string;
-
+ sp->stream.event_cb = _iostream_event;
+ sp->stream.event_mask = _MU_STR_EVMASK (_MU_STR_EVENT_CLRFLAG);
+
mu_stream_ref (in);
sp->transport[_MU_STREAM_INPUT] = in;
+ if (!out)
+ out = in;
mu_stream_ref (out);
sp->transport[_MU_STREAM_OUTPUT] = out;

Return to:

Send suggestions and report system problems to the System administrator.