diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-11-05 09:12:05 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-11-05 09:12:05 +0000 |
commit | 1f6c71fcb9f5b51cf79c0cb5212031f14adb631e (patch) | |
tree | e9b87900724896ac660c11ee8b2ee32f800db00f | |
parent | a1dc0f56e3b24e7c042ea90f3ace824f156403c8 (diff) | |
download | mailutils-1f6c71fcb9f5b51cf79c0cb5212031f14adb631e.tar.gz mailutils-1f6c71fcb9f5b51cf79c0cb5212031f14adb631e.tar.bz2 |
* mailbox/socket_stream.c: New file.
* include/mailutils/stream.h (mu_socket_stream_create)
(mu_stream_shutdown, mu_stream_set_shutdown): New functions.
* libproto/include/stream0.h (struct _mu_stream): New member
`_shutdown'.
* mailbox/file_stream.c (mu_stream_create): Bugfix.
* mailbox/stream.c (mu_stream_shutdown)
(mu_stream_set_shutdown): New functions.
* mailbox/tcp.c (_tcp_shutdown): New function.
(_tcp_stream_init): New function.
(mu_tcp_stream_create_with_source_ip): Register _tcp_shutdown.
-rw-r--r-- | include/mailutils/stream.h | 6 | ||||
-rw-r--r-- | libproto/include/stream0.h | 1 | ||||
-rw-r--r-- | mailbox/file_stream.c | 2 | ||||
-rw-r--r-- | mailbox/socket_stream.c | 243 | ||||
-rw-r--r-- | mailbox/stream.c | 33 | ||||
-rw-r--r-- | mailbox/tcp.c | 45 |
6 files changed, 321 insertions, 9 deletions
diff --git a/include/mailutils/stream.h b/include/mailutils/stream.h index aed8803a2..5bc9c3870 100644 --- a/include/mailutils/stream.h +++ b/include/mailutils/stream.h @@ -56,6 +56,8 @@ extern int mu_tcp_stream_create_with_source_host (mu_stream_t *stream, const char *host, int port, const char *source_host, int flags); +extern int mu_socket_stream_create (mu_stream_t *stream, const char *filename, + int flags); extern int mu_mapfile_stream_create (mu_stream_t *stream, const char* filename, int flags); @@ -91,6 +93,7 @@ extern int mu_stream_write (mu_stream_t, const char *, size_t, mu_off_t, size_t *); extern int mu_stream_setbufsiz (mu_stream_t stream, size_t size); extern int mu_stream_flush (mu_stream_t); +extern int mu_stream_shutdown (mu_stream_t stream, int how); extern int mu_stream_vprintf (mu_stream_t os, mu_off_t *poff, const char *fmt, va_list ap); @@ -166,6 +169,9 @@ extern int mu_stream_set_strerror (mu_stream_t stream, extern int mu_stream_set_wait (mu_stream_t stream, int (*wait) (mu_stream_t, int *, struct timeval *), void *owner); + +extern int mu_stream_set_shutdown (mu_stream_t stream, + int (*_shutdown) (mu_stream_t, int how), void *owner); extern int mu_stream_sequential_read (mu_stream_t stream, char *buf, size_t size, size_t *nbytes); diff --git a/libproto/include/stream0.h b/libproto/include/stream0.h index 89563bdaf..8d4a17ae1 100644 --- a/libproto/include/stream0.h +++ b/libproto/include/stream0.h @@ -65,6 +65,7 @@ struct _mu_stream int (*_setbufsiz)(mu_stream_t, size_t); int (*_strerror) (mu_stream_t, const char **); int (*_wait) (mu_stream_t, int *pflags, struct timeval *tvp); + int (*_shutdown) (mu_stream_t, int how); }; #ifdef __cplusplus diff --git a/mailbox/file_stream.c b/mailbox/file_stream.c index 26ed126c2..2ea796e33 100644 --- a/mailbox/file_stream.c +++ b/mailbox/file_stream.c @@ -546,8 +546,8 @@ mu_file_stream_create (mu_stream_t *stream, const char* filename, int flags) ret = mu_stream_create (stream, flags|MU_STREAM_NO_CHECK, fs); if (ret != 0) { - free (fs); free (fs->filename); + free (fs); return ret; } diff --git a/mailbox/socket_stream.c b/mailbox/socket_stream.c new file mode 100644 index 000000000..11c70d777 --- /dev/null +++ b/mailbox/socket_stream.c @@ -0,0 +1,243 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 1999, 2000, 2001, 2002, 2004, + 2005, 2006, 2007 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 the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <unistd.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <string.h> +#include <signal.h> +#include <errno.h> + +#include <mailutils/stream.h> +#include <mailutils/error.h> +#include <mailutils/errno.h> + +struct _socket_stream +{ + mu_stream_t fstream; + char *filename; + int ec; /* Last error code if fstream == NULL */ +}; + +static void +_s_destroy (mu_stream_t stream) +{ + struct _socket_stream *s = mu_stream_get_owner (stream); + + if (s->filename) + free (s->filename); + mu_stream_destroy (&s->fstream, mu_stream_get_owner (s->fstream)); + free (s); +} + +static int +_s_read (mu_stream_t stream, char *optr, size_t osize, + mu_off_t offset, size_t *nbytes) +{ + struct _socket_stream *s = mu_stream_get_owner (stream); + return mu_stream_read (s->fstream, optr, osize, offset, nbytes); +} + +static int +_s_readline (mu_stream_t stream, char *optr, size_t osize, + mu_off_t offset, size_t *nbytes) +{ + struct _socket_stream *s = mu_stream_get_owner (stream); + return mu_stream_readline (s->fstream, optr, osize, offset, nbytes); +} + +static int +_s_write (mu_stream_t stream, const char *iptr, size_t isize, + mu_off_t offset, size_t *nbytes) +{ + struct _socket_stream *s = mu_stream_get_owner (stream); + return mu_stream_write (s->fstream, iptr, isize, offset, nbytes); +} + +static int +_s_open (mu_stream_t stream) +{ + struct _socket_stream *s = mu_stream_get_owner (stream); + int fd, rc; + FILE *fp; + struct sockaddr_un addr; + char *fstr; + int flags; + + if (!s) + return EINVAL; + + fd = socket (PF_UNIX, SOCK_STREAM, 0); + if (fd < 0) + return errno; + + memset (&addr, 0, sizeof addr); + addr.sun_family = AF_UNIX; + strncpy (addr.sun_path, s->filename, sizeof addr.sun_path - 1); + addr.sun_path[sizeof addr.sun_path - 1] = 0; + if (connect (fd, (struct sockaddr *) &addr, sizeof(addr))) + { + close (fd); + return errno; + } + + mu_stream_get_flags(stream, &flags); + if (flags & MU_STREAM_WRITE) + fstr = "w"; + else if (flags & MU_STREAM_RDWR) + fstr = "w+"; + else /* default, also if flags & MU_STREAM_READ */ + fstr = "r"; + + fp = fdopen (fd, fstr); + if (!fp) + { + close (fd); + return errno; + } + + rc = mu_stdio_stream_create (&s->fstream, fp, flags); + if (rc) + { + fclose (fp); + return rc; + } + + rc = mu_stream_open (s->fstream); + if (rc) + { + mu_stream_destroy (&s->fstream, mu_stream_get_owner (s->fstream)); + fclose (fp); + } + return rc; +} + +static int +_s_close (mu_stream_t stream) +{ + struct _socket_stream *s = mu_stream_get_owner (stream); + return mu_stream_close (s->fstream); +} + +static int +_s_flush (mu_stream_t stream) +{ + struct _socket_stream *s = mu_stream_get_owner (stream); + return mu_stream_flush (s->fstream); +} + +int +_s_wait (mu_stream_t stream, int *pflags, struct timeval *tvp) +{ + struct _socket_stream *s = mu_stream_get_owner (stream); + return mu_stream_wait (s->fstream, pflags, tvp); +} + +int +_s_strerror (mu_stream_t stream, const char **pstr) +{ + struct _socket_stream *s = mu_stream_get_owner (stream); + return mu_stream_strerror (s->fstream, pstr); +} + +static int +_s_get_transport2 (mu_stream_t stream, + mu_transport_t *pin, mu_transport_t *pout) +{ + struct _socket_stream *s = mu_stream_get_owner (stream); + return mu_stream_get_transport2 (s->fstream, pin, pout); +} + +int +_s_shutdown (mu_stream_t stream, int how) +{ + struct _socket_stream *s = mu_stream_get_owner (stream); + int flag; + mu_transport_t trans; + + if (s->fstream == NULL) + return EINVAL; + + mu_stream_get_transport(s->fstream, &trans); + switch (how) + { + case MU_STREAM_READ: + flag = SHUT_RD; + break; + + case MU_STREAM_WRITE: + flag = SHUT_WR; + } + + if (shutdown ((int) trans, flag)) + return errno; + return 0; +} + +int +mu_socket_stream_create (mu_stream_t *stream, const char *filename, int flags) +{ + struct _socket_stream *s; + int rc; + + if (stream == NULL) + return MU_ERR_OUT_PTR_NULL; + + s = calloc (1, sizeof (struct _socket_stream)); + if (s == NULL) + return ENOMEM; + + if ((s->filename = strdup (filename)) == NULL) + { + free (s); + return ENOMEM; + } + + rc = mu_stream_create (stream, flags | MU_STREAM_NO_CHECK, s); + if (rc) + { + free (s); + free (s->filename); + return rc; + } + + mu_stream_set_open (*stream, _s_open, s); + mu_stream_set_close (*stream, _s_close, s); + mu_stream_set_get_transport2 (*stream, _s_get_transport2, s); + mu_stream_set_read (*stream, _s_read, s); + mu_stream_set_readline (*stream, _s_readline, s); + mu_stream_set_write (*stream, _s_write, s); + mu_stream_set_flush (*stream, _s_flush, s); + mu_stream_set_destroy (*stream, _s_destroy, s); + mu_stream_set_strerror (*stream, _s_strerror, s); + mu_stream_set_wait (*stream, _s_wait, s); + mu_stream_set_shutdown (*stream, _s_shutdown, s); + + return 0; +} + + + + diff --git a/mailbox/stream.c b/mailbox/stream.c index 1b24c15ff..8343e22b9 100644 --- a/mailbox/stream.c +++ b/mailbox/stream.c @@ -669,6 +669,25 @@ mu_stream_get_state (mu_stream_t stream, int *pstate) } int +mu_stream_shutdown (mu_stream_t stream, int how) +{ + if (stream == NULL) + return EINVAL; + if (!stream->_shutdown) + return ENOSYS; + switch (how) + { + case MU_STREAM_READ: + case MU_STREAM_WRITE: + break; + + default: + return EINVAL; + } + return stream->_shutdown (stream, how); +} + +int mu_stream_set_destroy (mu_stream_t stream, void (*_destroy) (mu_stream_t), void *owner) { @@ -849,6 +868,20 @@ mu_stream_set_wait (mu_stream_t stream, } int +mu_stream_set_shutdown (mu_stream_t stream, + int (*_shutdown) (mu_stream_t, int how), void *owner) +{ + if (stream == NULL) + return EINVAL; + if (owner == stream->owner) + { + stream->_shutdown = _shutdown; + return 0; + } + return EACCES; +} + +int mu_stream_sequential_read (mu_stream_t stream, char *buf, size_t size, size_t *nbytes) { diff --git a/mailbox/tcp.c b/mailbox/tcp.c index b0e7fd17c..84cc2b142 100644 --- a/mailbox/tcp.c +++ b/mailbox/tcp.c @@ -266,6 +266,42 @@ _tcp_wait (mu_stream_t stream, int *pflags, struct timeval *tvp) } int +_tcp_shutdown (mu_stream_t stream, int how) +{ + struct _tcp_instance *tcp = mu_stream_get_owner (stream); + int flag; + if (tcp->fd == -1) + return EINVAL; + + switch (how) + { + case MU_STREAM_READ: + flag = SHUT_RD; + break; + + case MU_STREAM_WRITE: + flag = SHUT_WR; + } + + if (shutdown (tcp->fd, flag)) + return errno; + return 0; +} + +static void +_tcp_stream_init (mu_stream_t stream, struct _tcp_instance *tcp) +{ + mu_stream_set_open (stream, _tcp_open, tcp); + mu_stream_set_close (stream, _tcp_close, tcp); + mu_stream_set_read (stream, _tcp_read, tcp); + mu_stream_set_write (stream, _tcp_write, tcp); + mu_stream_set_get_transport2 (stream, _tcp_get_transport2, tcp); + mu_stream_set_destroy (stream, _tcp_destroy, tcp); + mu_stream_set_wait (stream, _tcp_wait, tcp); + mu_stream_set_shutdown (stream, _tcp_shutdown, tcp); +} + +int mu_tcp_stream_create_with_source_ip (mu_stream_t *stream, const char *host, int port, unsigned long source_ip, @@ -301,14 +337,7 @@ mu_tcp_stream_create_with_source_ip (mu_stream_t *stream, return ret; } - mu_stream_set_open (*stream, _tcp_open, tcp); - mu_stream_set_close (*stream, _tcp_close, tcp); - mu_stream_set_read (*stream, _tcp_read, tcp); - mu_stream_set_write (*stream, _tcp_write, tcp); - mu_stream_set_get_transport2 (*stream, _tcp_get_transport2, tcp); - mu_stream_set_destroy (*stream, _tcp_destroy, tcp); - mu_stream_set_wait (*stream, _tcp_wait, tcp); - + _tcp_stream_init (*stream, tcp); return 0; } |