summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mailutils/datetime.h47
-rw-r--r--include/mailutils/stream.h63
-rw-r--r--include/mailutils/sys/file_stream.h1
-rw-r--r--libmailutils/diag/errors6
-rw-r--r--libmailutils/stream/file_stream.c112
-rw-r--r--libmailutils/stream/iostream.c4
-rw-r--r--libmailutils/stream/stream.c217
-rw-r--r--libmu_auth/tls.c59
8 files changed, 424 insertions, 85 deletions
diff --git a/include/mailutils/datetime.h b/include/mailutils/datetime.h
index 47447e698..912c748d6 100644
--- a/include/mailutils/datetime.h
+++ b/include/mailutils/datetime.h
@@ -22,6 +22,7 @@
extern "C" {
#endif
+#include <sys/time.h>
#include <time.h>
#include <mailutils/types.h>
@@ -107,7 +108,53 @@ int mu_scan_datetime (const char *input, const char *fmt, struct tm *tm,
one for outputting and one for scanning: */
#define MU_DATETIME_FORM_RFC822 "%a, %e %b %Y %H:%M:%S %z"
#define MU_DATETIME_SCAN_RFC822 "%[%a, %]%e %b %Y %H:%M%[:%S%] %z"
+
+static inline int
+mu_timeval_cmp (struct timeval const *a, struct timeval const *b)
+{
+ if (a->tv_sec < b->tv_sec)
+ return -1;
+ if (a->tv_sec > b->tv_sec)
+ return 1;
+ if (a->tv_usec < b->tv_usec)
+ return -1;
+ if (a->tv_usec > b->tv_usec)
+ return 1;
+ return 0;
+}
+static inline struct timeval
+mu_timeval_add (struct timeval const *a, struct timeval const *b)
+{
+ struct timeval sum;
+
+ sum.tv_sec = a->tv_sec + b->tv_sec;
+ sum.tv_usec = a->tv_usec + b->tv_usec;
+ if (sum.tv_usec >= 1000000)
+ {
+ ++sum.tv_sec;
+ sum.tv_usec -= 1000000;
+ }
+
+ return sum;
+}
+
+static inline struct timeval
+mu_timeval_sub (struct timeval const *a, struct timeval const *b)
+{
+ struct timeval diff;
+
+ diff.tv_sec = a->tv_sec - b->tv_sec;
+ diff.tv_usec = a->tv_usec - b->tv_usec;
+ if (diff.tv_usec < 0)
+ {
+ --diff.tv_sec;
+ diff.tv_usec += 1000000;
+ }
+
+ return diff;
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/include/mailutils/stream.h b/include/mailutils/stream.h
index fd2d555c6..f5c8a673e 100644
--- a/include/mailutils/stream.h
+++ b/include/mailutils/stream.h
@@ -17,8 +17,9 @@
#ifndef _MAILUTILS_STREAM_H
#define _MAILUTILS_STREAM_H
-#include <mailutils/types.h>
+#include <stdlib.h>
#include <stdarg.h>
+#include <mailutils/types.h>
#ifdef __cplusplus
extern "C" {
@@ -79,7 +80,10 @@ enum mu_buffer_type
#define MU_IOCTL_TLSSTREAM 13 /* TLS stream */
#define MU_IOCTL_WORDWRAPSTREAM 14 /* Word-wrapper stream */
#define MU_IOCTL_TCPSTREAM 15 /* TCP stream */
-
+
+#define MU_IOCTL_TIMEOUT 16 /* Get or set the I/O timeout value
+ (struct timeval) */
+
/* Opcodes common for various families */
#define MU_IOCTL_OP_GET 0
#define MU_IOCTL_OP_SET 1
@@ -337,13 +341,54 @@ int mu_stream_set_buffer (mu_stream_t stream, enum mu_buffer_type type,
int mu_stream_get_buffer (mu_stream_t stream,
struct mu_buffer_query *qry);
int mu_stream_read (mu_stream_t stream, void *buf, size_t size, size_t *pread);
-int mu_stream_readdelim (mu_stream_t stream, char *buf, size_t size,
- int delim, size_t *pread);
-int mu_stream_readline (mu_stream_t stream, char *buf, size_t size, size_t *pread);
-int mu_stream_getdelim (mu_stream_t stream, char **pbuf, size_t *psize,
- int delim, size_t *pread);
-int mu_stream_getline (mu_stream_t stream, char **pbuf, size_t *psize,
- size_t *pread);
+int mu_stream_timed_readdelim (mu_stream_t stream, char *buf, size_t size,
+ int delim, struct timeval *to, size_t *pread);
+static inline int
+mu_stream_readdelim (mu_stream_t stream, char *buf, size_t size,
+ int delim, size_t *pread)
+{
+ return mu_stream_timed_readdelim (stream, buf, size, delim, NULL, pread);
+}
+
+static inline int
+mu_stream_timed_readline (mu_stream_t stream, char *buf, size_t size,
+ struct timeval *tv,
+ size_t *pread)
+{
+ return mu_stream_timed_readdelim (stream, buf, size, '\n', tv, pread);
+}
+
+static inline int
+mu_stream_readline (mu_stream_t stream, char *buf, size_t size, size_t *pread)
+{
+ return mu_stream_timed_readline (stream, buf, size, NULL, pread);
+}
+
+int mu_stream_timed_getdelim (mu_stream_t stream, char **pbuf, size_t *psize,
+ int delim, struct timeval *to, size_t *pread);
+
+static inline int
+mu_stream_getdelim (mu_stream_t stream, char **pbuf, size_t *psize,
+ int delim, size_t *pread)
+{
+ return mu_stream_timed_getdelim (stream, pbuf, psize, delim, NULL, pread);
+}
+
+static inline int
+mu_stream_timed_getline (mu_stream_t stream, char **pbuf, size_t *psize,
+ struct timeval *to,
+ size_t *pread)
+{
+ return mu_stream_timed_getdelim (stream, pbuf, psize, '\n', to, pread);
+}
+
+static inline int
+mu_stream_getline (mu_stream_t stream, char **pbuf, size_t *psize,
+ size_t *pread)
+{
+ return mu_stream_timed_getline (stream, pbuf, psize, NULL, pread);
+}
+
int mu_stream_write (mu_stream_t stream, const void *buf, size_t size,
size_t *pwrite);
int mu_stream_writeline (mu_stream_t stream, const char *buf, size_t size);
diff --git a/include/mailutils/sys/file_stream.h b/include/mailutils/sys/file_stream.h
index c54f9dc49..52583691e 100644
--- a/include/mailutils/sys/file_stream.h
+++ b/include/mailutils/sys/file_stream.h
@@ -33,6 +33,7 @@ struct _mu_file_stream
int flags;
char *filename;
void *echo_state;
+ unsigned io_timeout;
};
int _mu_file_stream_create (struct _mu_file_stream **pstream, size_t size,
diff --git a/libmailutils/diag/errors b/libmailutils/diag/errors
index ca563ec27..54df0b0f1 100644
--- a/libmailutils/diag/errors
+++ b/libmailutils/diag/errors
@@ -141,3 +141,9 @@ MU_ERR_USER6 _("User-defined error 6")
MU_ERR_USER7 _("User-defined error 7")
MU_ERR_BASE64 _("invalid base64 input")
+
+MU_ERR_TIMEOUT _("timed out")
+MU_ERR_SET_TIMEOUT _("error setting timeout")
+
+MU_ERR_WRITE _("write error")
+MU_ERR_TLS _("TLS error")
diff --git a/libmailutils/stream/file_stream.c b/libmailutils/stream/file_stream.c
index f8283b5b8..781fae98c 100644
--- a/libmailutils/stream/file_stream.c
+++ b/libmailutils/stream/file_stream.c
@@ -22,6 +22,8 @@
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
+#include <poll.h>
+
#if HAVE_TERMIOS_H
# include <termios.h>
#endif
@@ -40,7 +42,38 @@ static int
fd_read (struct _mu_stream *str, char *buf, size_t size, size_t *pret)
{
struct _mu_file_stream *fstr = (struct _mu_file_stream *) str;
- ssize_t n = read (fstr->fd, buf, size);
+ ssize_t n;
+
+ if (fstr->io_timeout > 0)
+ {
+ struct pollfd pfd;
+ pfd.fd = fstr->fd;
+ pfd.events = POLLIN;
+ switch (poll (&pfd, 1, fstr->io_timeout))
+ {
+ case 0:
+ return MU_ERR_TIMEOUT;
+
+ case -1:
+ return errno;
+
+ case 1:
+ break;
+
+ default:
+ /* Should not happen */
+ return MU_ERR_FAILURE;
+ }
+
+ if (!(pfd.revents & POLLIN))
+ {
+ if (pfd.revents & POLLHUP)
+ return 0;
+ return MU_ERR_READ;
+ }
+ }
+
+ n = read (fstr->fd, buf, size);
if (n == -1)
return errno;
*pret = n;
@@ -51,7 +84,36 @@ static int
fd_write (struct _mu_stream *str, const char *buf, size_t size, size_t *pret)
{
struct _mu_file_stream *fstr = (struct _mu_file_stream *) str;
- ssize_t n = write (fstr->fd, (char*) buf, size);
+ ssize_t n;
+
+ if (fstr->io_timeout > 0)
+ {
+ struct pollfd pfd;
+ pfd.fd = fstr->fd;
+ pfd.events = POLLOUT;
+ switch (poll (&pfd, 1, fstr->io_timeout))
+ {
+ case 0:
+ return MU_ERR_TIMEOUT;
+
+ case -1:
+ return errno;
+
+ case 1:
+ break;
+
+ default:
+ /* Should not happen */
+ return MU_ERR_FAILURE;
+ }
+
+ if (!(pfd.revents & POLLOUT))
+ {
+ return MU_ERR_FAILURE; //FIXME: MU_ERR_WRITE?
+ }
+ }
+
+ n = write (fstr->fd, (char*) buf, size);
if (n == -1)
return errno;
*pret = n;
@@ -188,6 +250,9 @@ fd_ioctl (struct _mu_stream *str, int code, int opcode, void *ptr)
ptrans = ptr;
fstr->fd = (int) (intptr_t) ptrans[0];
break;
+
+ default:
+ return EINVAL;
}
break;
@@ -201,8 +266,12 @@ fd_ioctl (struct _mu_stream *str, int code, int opcode, void *ptr)
{
case MU_IOCTL_OP_GET:
return mu_stream_get_buffer (str, qp);
+
case MU_IOCTL_OP_SET:
return mu_stream_set_buffer (str, qp->buftype, qp->bufsize);
+
+ default:
+ return EINVAL;
}
}
break;
@@ -268,6 +337,9 @@ fd_ioctl (struct _mu_stream *str, int code, int opcode, void *ptr)
return ENOSYS;
#endif
}
+
+ default:
+ return EINVAL;
}
break;
@@ -286,9 +358,43 @@ fd_ioctl (struct _mu_stream *str, int code, int opcode, void *ptr)
else
fstr->flags &= ~_MU_FILE_STREAM_FD_BORROWED;
break;
+
+ default:
+ return EINVAL;
+ }
+ break;
+
+ case MU_IOCTL_TIMEOUT:
+ if (!ptr)
+ return EINVAL;
+ else
+ {
+ unsigned n;
+ struct timeval *tv = ptr;
+# define MSEC_PER_SECOND 1000
+ switch (opcode)
+ {
+ case MU_IOCTL_OP_GET:
+ tv->tv_sec = fstr->io_timeout / MSEC_PER_SECOND;
+ tv->tv_usec = (fstr->io_timeout % MSEC_PER_SECOND) * 1000;
+ break;
+
+ case MU_IOCTL_OP_SET:
+ if (tv->tv_sec > UINT_MAX / MSEC_PER_SECOND)
+ return ERANGE;
+ n = tv->tv_sec * MSEC_PER_SECOND;
+ if (UINT_MAX - n < (unsigned long) tv->tv_usec / 1000)
+ return ERANGE;
+ n += tv->tv_usec / 1000;
+ fstr->io_timeout = n;
+ break;
+
+ default:
+ return EINVAL;
+ }
}
break;
-
+
default:
return ENOSYS;
}
diff --git a/libmailutils/stream/iostream.c b/libmailutils/stream/iostream.c
index 83b142a92..0f7b767b5 100644
--- a/libmailutils/stream/iostream.c
+++ b/libmailutils/stream/iostream.c
@@ -190,7 +190,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;
diff --git a/libmailutils/stream/stream.c b/libmailutils/stream/stream.c
index c816d9d05..9e0ae846e 100644
--- a/libmailutils/stream/stream.c
+++ b/libmailutils/stream/stream.c
@@ -23,6 +23,7 @@
#ifndef SIZE_MAX
# define SIZE_MAX (~((size_t)0))
#endif
+#include <sys/time.h>
#include <mailutils/types.h>
#include <mailutils/alloc.h>
@@ -31,6 +32,7 @@
#include <mailutils/nls.h>
#include <mailutils/stream.h>
#include <mailutils/cstr.h>
+#include <mailutils/datetime.h>
#include <mailutils/sys/stream.h>
size_t mu_stream_default_buffer_size = MU_STREAM_DEFBUFSIZ;
@@ -776,16 +778,26 @@ mu_stream_read (mu_stream_t stream, void *buf, size_t size, size_t *pread)
return 0;
}
-int
+static int
_stream_scandelim (mu_stream_t stream, char *buf, size_t size, int delim,
- size_t *pnread)
+ struct timeval *to, size_t *pnread)
{
int rc = 0;
size_t nread = 0;
+
+ struct timeval stop_time, saved_timeout;
+
+ if (to)
+ {
+ gettimeofday (&stop_time, NULL);
+ stop_time = mu_timeval_add (&stop_time, to);
+
+ rc = mu_stream_ioctl (stream, MU_IOCTL_TIMEOUT, MU_IOCTL_OP_GET,
+ &saved_timeout);
+ if (rc)
+ return MU_ERR_SET_TIMEOUT;
+ }
- size--;
- if (size == 0)
- return MU_ERR_BUFSPACE;
while (size)
{
char *p, *q;
@@ -793,6 +805,26 @@ _stream_scandelim (mu_stream_t stream, char *buf, size_t size, int delim,
if (stream->pos == stream->level)
{
+ if (to)
+ {
+ struct timeval now, d;
+
+ gettimeofday (&now, NULL);
+ if (mu_timeval_cmp (&now, &stop_time) >= 0)
+ {
+ rc = MU_ERR_TIMEOUT;
+ break;
+ }
+ d = mu_timeval_sub (&stop_time, &now);
+ rc = mu_stream_ioctl (stream, MU_IOCTL_TIMEOUT, MU_IOCTL_OP_SET,
+ &d);
+ if (rc)
+ {
+ rc = MU_ERR_SET_TIMEOUT;
+ break;
+ }
+ }
+
if ((rc = _stream_flush_buffer (stream, FLUSH_RDWR)))
break;
if ((rc = _stream_fill_buffer (stream)) || stream->level == 0)
@@ -814,47 +846,99 @@ _stream_scandelim (mu_stream_t stream, char *buf, size_t size, int delim,
if (p) /* Delimiter found */
break;
}
- *buf = 0;
+
+ if (to)
+ {
+ mu_stream_ioctl (stream, MU_IOCTL_TIMEOUT, MU_IOCTL_OP_SET,
+ &saved_timeout);
+ }
+
*pnread = nread;
return rc;
}
static int
_stream_readdelim (mu_stream_t stream, char *buf, size_t size,
- int delim, size_t *pread)
+ int delim,
+ struct timeval *to,
+ size_t *pread)
{
int rc;
char c;
size_t n = 0, rdn;
- size--;
- if (size == 0)
- return MU_ERR_BUFSPACE;
- for (n = 0;
- n < size && (rc = mu_stream_read (stream, &c, 1, &rdn)) == 0 && rdn;)
+ struct timeval stop_time, saved_timeout;
+
+ if (to)
{
+ gettimeofday (&stop_time, NULL);
+ stop_time = mu_timeval_add (&stop_time, to);
+
+ rc = mu_stream_ioctl (stream, MU_IOCTL_TIMEOUT, MU_IOCTL_OP_GET,
+ &saved_timeout);
+ if (rc)
+ return MU_ERR_SET_TIMEOUT;
+ }
+
+ n = 0;
+ while (n < size)
+ {
+ if (to)
+ {
+ struct timeval now, d;
+
+ gettimeofday (&now, NULL);
+ if (mu_timeval_cmp (&now, &stop_time) >= 0)
+ {
+ rc = MU_ERR_TIMEOUT;
+ break;
+ }
+ d = mu_timeval_sub (&stop_time, &now);
+ rc = mu_stream_ioctl (stream, MU_IOCTL_TIMEOUT, MU_IOCTL_OP_SET,
+ &d);
+ if (rc)
+ {
+ rc = MU_ERR_SET_TIMEOUT;
+ break;
+ }
+ }
+
+ rc = mu_stream_read (stream, &c, 1, &rdn);
+ if (rc || rdn == 0)
+ break;
+
*buf++ = c;
n++;
if (c == delim)
break;
+ }
+
+ if (to)
+ {
+ mu_stream_ioctl (stream, MU_IOCTL_TIMEOUT, MU_IOCTL_OP_SET,
+ &saved_timeout);
}
- *buf = 0;
+
if (pread)
*pread = n;
return rc;
}
int
-mu_stream_readdelim (mu_stream_t stream, char *buf, size_t size,
- int delim, size_t *pread)
+mu_stream_timed_readdelim (mu_stream_t stream, char *buf, size_t size,
+ int delim, struct timeval *to, size_t *pread)
{
int rc;
-
+ size_t n;
_bootstrap_event (stream);
if (size == 0)
return EINVAL;
+ size--;
+ if (size == 0)
+ return MU_ERR_BUFSPACE;
+
if (!(stream->flags & _MU_STR_OPEN))
{
if (stream->open)
@@ -864,26 +948,60 @@ mu_stream_readdelim (mu_stream_t stream, char *buf, size_t size,
if (stream->buftype == mu_buffer_none)
{
- rc = _stream_readdelim (stream, buf, size, delim, pread);
+ rc = _stream_readdelim (stream, buf, size, delim, to, &n);
}
else
{
if ((rc = _stream_flush_buffer (stream, FLUSH_WRITE)))
return rc;
- rc = _stream_scandelim (stream, buf, size, delim, pread);
+ rc = _stream_scandelim (stream, buf, size, delim, to, &n);
+ }
+
+ if (rc == 0)
+ {
+ buf[n] = 0;
+ if (pread)
+ *pread = n;
}
+
return rc;
}
-int
-mu_stream_readline (mu_stream_t stream, char *buf, size_t size, size_t *pread)
+static int
+bufexpand (char **pbuf, size_t *pn, size_t cur_len)
{
- return mu_stream_readdelim (stream, buf, size, '\n', pread);
+ size_t n = *pn;
+
+ if (n == 0)
+ *pbuf = NULL;
+ if (cur_len == n)
+ {
+ char *p;
+
+ if (!*pbuf)
+ {
+ if (!n)
+ {
+ n = 64;
+ }
+ }
+ else if ((size_t) -1 / 3 * 2 <= n)
+ return ENOMEM;
+ else
+ n += (n + 1) / 2;
+
+ p = realloc (*pbuf, n);
+ if (!p)
+ return errno;
+ *pbuf = p;
+ *pn = n;
+ }
+ return 0;
}
int
-mu_stream_getdelim (mu_stream_t stream, char **pbuf, size_t *psize,
- int delim, size_t *pread)
+mu_stream_timed_getdelim (mu_stream_t stream, char **pbuf, size_t *psize,
+ int delim, struct timeval *to, size_t *pread)
{
int rc;
char *lineptr = *pbuf;
@@ -902,53 +1020,19 @@ mu_stream_getdelim (mu_stream_t stream, char **pbuf, size_t *psize,
if ((rc = _stream_flush_buffer (stream, FLUSH_WRITE)))
return rc;
- if (lineptr == NULL || n == 0)
- {
- char *new_lineptr;
- n = 120;
- new_lineptr = realloc (lineptr, n);
- if (new_lineptr == NULL)
- return ENOMEM;
- lineptr = new_lineptr;
- }
-
for (;;)
{
size_t rdn;
- /* Make enough space for len+1 (for final NUL) bytes. */
- if (cur_len + 1 >= n)
- {
- size_t needed_max =
- SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX;
- size_t needed = 2 * n + 1; /* Be generous. */
- char *new_lineptr;
-
- if (needed_max < needed)
- needed = needed_max;
- if (cur_len + 1 >= needed)
- {
- rc = EOVERFLOW;
- break;
- }
-
- new_lineptr = realloc (lineptr, needed);
- if (new_lineptr == NULL)
- {
- rc = ENOMEM;
- break;
- }
-
- lineptr = new_lineptr;
- n = needed;
- }
+ if ((rc = bufexpand (&lineptr, &n, cur_len)) != 0)
+ break;
if (stream->buftype == mu_buffer_none)
rc = _stream_readdelim (stream, lineptr + cur_len, n - cur_len, delim,
- &rdn);
+ to, &rdn);
else
rc = _stream_scandelim (stream, lineptr + cur_len, n - cur_len, delim,
- &rdn);
+ to, &rdn);
if (rc || rdn == 0)
break;
@@ -957,7 +1041,9 @@ mu_stream_getdelim (mu_stream_t stream, char **pbuf, size_t *psize,
if (lineptr[cur_len - 1] == delim)
break;
}
- lineptr[cur_len] = '\0';
+
+ if (rc == 0 && (rc = bufexpand (&lineptr, &n, cur_len)) == 0)
+ lineptr[cur_len] = '\0';
*pbuf = lineptr;
*psize = n;
@@ -967,13 +1053,6 @@ mu_stream_getdelim (mu_stream_t stream, char **pbuf, size_t *psize,
return rc;
}
-int
-mu_stream_getline (mu_stream_t stream, char **pbuf, size_t *psize,
- size_t *pread)
-{
- return mu_stream_getdelim (stream, pbuf, psize, '\n', pread);
-}
-
/* Return 1 if no more data can be written to the current buffer. */
static inline int
_stream_buffer_full_p (struct _mu_stream *stream)
diff --git a/libmu_auth/tls.c b/libmu_auth/tls.c
index 44469efd0..7db0982b6 100644
--- a/libmu_auth/tls.c
+++ b/libmu_auth/tls.c
@@ -253,16 +253,47 @@ _tls_open (mu_stream_t stream)
rc = gnutls_handshake (sp->session);
if (rc != GNUTLS_E_SUCCESS)
{
+ mu_transport_t t[2];
+
mu_debug (MU_DEBCAT_STREAM, MU_DEBUG_ERROR,
("gnutls_handshake: %s", gnutls_strerror (rc)));
sp->tls_err = rc;
+ switch (rc)
+ {
+ case GNUTLS_E_PULL_ERROR:
+ if (mu_stream_ioctl (sp->transport[0],
+ MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET,
+ &t) == 0 &&
+ mu_stream_err (t[0]))
+ rc = mu_stream_last_error (t[0]);
+ else
+ rc = MU_ERR_READ;
+ break;
+
+ case GNUTLS_E_PUSH_ERROR:
+ if (mu_stream_ioctl (sp->transport[1],
+ MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET,
+ &t) == 0 &&
+ mu_stream_err (t[1]))
+ rc = mu_stream_last_error (t[1]);
+ else
+ rc = MU_ERR_WRITE;
+ break;
+
+ default:
+ rc = MU_ERR_TLS;
+ }
+
gnutls_deinit (sp->session);
sp->session = NULL;
sp->state = state_init;
}
else
- /* FIXME: if (ssl_cafile) verify_certificate (s->session); */
- sp->state = state_open;
+ {
+ /* FIXME: if (ssl_cafile) verify_certificate (s->session); */
+ sp->state = state_open;
+ rc = 0;
+ }
break;
default:
@@ -391,7 +422,29 @@ _tls_ioctl (struct _mu_stream *stream, int code, int opcode, void *arg)
case MU_IOCTL_TCPSTREAM:
return mu_stream_ioctl (sp->transport[0], code, opcode, arg);
-
+
+ case MU_IOCTL_TIMEOUT:
+ {
+ int rc;
+
+ switch (opcode)
+ {
+ case MU_IOCTL_OP_SET:
+ rc = mu_stream_ioctl (sp->transport[0], code, opcode, arg);
+ if (rc == 0)
+ rc = mu_stream_ioctl (sp->transport[1], code, opcode, arg);
+ break;
+
+ case MU_IOCTL_OP_GET:
+ rc = mu_stream_ioctl (sp->transport[0], code, opcode, arg);
+ break;
+
+ default:
+ return EINVAL;
+ }
+ return rc;
+ }
+
default:
return ENOSYS;
}

Return to:

Send suggestions and report system problems to the System administrator.