diff options
Diffstat (limited to 'libmailutils/stream/iostream.c')
-rw-r--r-- | libmailutils/stream/iostream.c | 152 |
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; |