Commit 637f4ca5 637f4ca5d9481742b04b5642e8bd57db1895a9e3 by Alain Magloire

For the new mailbox, one of the short coming with the old stream_t

	object was that select() was not cover, meaning it was not possible
	to check if a stream was {read,write} ready.  The old was to get
	the fd (stream_get_fd()) and do the select.  Providing,
	stream_is_readready (stream_t, int timeout);
	stream_is_writeready (stream_t, int timeout);
	stream_is_exceptionpending (stream_t, int timeout);
	stream_is_open (stream_t);
	Takes care of it.  It will work specially for tcp stream.

	* mailbox2/stream.c: New functions for the select calls:
	(stream_is_readready): New function.
	(stream_is_writeready): New function.(stream_t, int timeout);
	(stream_is_exceptionpending): New function.
	(stream_is_open): New function.
	* mailbox2/bstream.c (_bs_readline): Bug was truncating the string
	to early.
	(_bs_is_readready): New file.
	(_bs_is_writeready): New file.
	(_bs_is_exceptionpending): New file.
	(_bs_is_open): New file.
	* mailbox2/fstream.c: stubs for the select functions.
	* mailbox2/memstream.c: stubs for the select functions.
	* mailbox2/mapstream.c: stubs for the select functions.
	* mailbox2/tcpstream.c: stubs for the select functions.
	* mailbox2/include/mailutils/stream.h: Adjust the prototypes
	* mailbox2/include/mailutils/sys/stream.h: Adjust the prototypes

	It is better not to put threading (Pthread) code in the low level
	API.  But instead in mailbox_t framework, where it can be control.
	* mailbox2/include/mailutils/pop3.h: Adjust the prototypes.
	* mailbox2/pop3/*.c: Remove threading code.
1 parent b51239c0
......@@ -27,7 +27,7 @@ libmailbox_la_SOURCES = \
md5-rsa.c \
memstream.c \
message.c \
mstream.c \
mapstream.c \
mutil.c \
observable.c \
observer.c \
......
......@@ -268,9 +268,7 @@ _bs_readline (stream_t stream, char *buf, size_t count, size_t *pnread)
bs->rbuffer.ptr = nl;
memcpy (s, p, len);
total += len;
s[len] = '\0';
if (pnread)
*pnread = total;
s += len;
break;
}
bs->rbuffer.count -= len;
......@@ -371,6 +369,38 @@ _bs_tell (stream_t stream, off_t *off)
return stream_tell (bs->stream, off);
}
static int
_bs_is_readready (stream_t stream, int timeout)
{
struct _bs *bs = (struct _bs *)stream;
/* Drain our buffer first. */
if (bs->rbuffer.count > 0)
return 1;
return stream_is_readready (bs->stream, timeout);
}
static int
_bs_is_writeready (stream_t stream, int timeout)
{
struct _bs *bs = (struct _bs *)stream;
return stream_is_writeready (bs->stream, timeout);
}
static int
_bs_is_exceptionpending (stream_t stream, int timeout)
{
struct _bs *bs = (struct _bs *)stream;
return stream_is_exceptionpending (bs->stream, timeout);
}
static int
_bs_is_open (stream_t stream)
{
struct _bs *bs = (struct _bs *)stream;
return stream_is_open (bs->stream);
}
static struct _stream_vtable _bs_vtable =
{
_bs_add_ref,
......@@ -394,6 +424,12 @@ static struct _stream_vtable _bs_vtable =
_bs_get_fd,
_bs_get_flags,
_bs_get_state,
_bs_is_readready,
_bs_is_writeready,
_bs_is_exceptionpending,
_bs_is_open
};
int
......
......@@ -247,6 +247,36 @@ _fs_get_state (stream_t stream, enum stream_state *state)
}
static int
_fs_is_open (stream_t stream)
{
struct _fs *fs = (struct _fs *)stream;
return (fs->file) ? 1 : 0;
}
static int
_fs_is_readready (stream_t stream, int timeout)
{
(void)timeout;
return _fs_is_open (stream);
}
static int
_fs_is_writeready (stream_t stream, int timeout)
{
(void)timeout;
return _fs_is_open (stream);
}
static int
_fs_is_exceptionpending (stream_t stream, int timeout)
{
(void)stream;
(void)timeout;
return 0;
}
static int
_fs_close (stream_t stream)
{
struct _fs *fs = (struct _fs *)stream;
......@@ -385,7 +415,13 @@ static struct _stream_vtable _fs_vtable =
_fs_get_fd,
_fs_get_flags,
_fs_get_state
_fs_get_state,
_fs_is_readready,
_fs_is_writeready,
_fs_is_exceptionpending,
_fs_is_open
};
int
......
......@@ -36,51 +36,49 @@ extern "C" {
struct _pop3;
typedef struct _pop3* pop3_t;
struct pop3_list_item
{
unsigned int msgno;
unsigned int size;
};
struct pop3_uidl_item
{
unsigned int msgno;
char *uidl;
};
extern int pop3_create __P ((pop3_t *));
extern void pop3_destroy __P ((pop3_t));
extern int pop3_connect __P ((pop3_t, const char *, unsigned int));
extern int pop3_disconnect __P ((pop3_t));
extern int pop3_set_stream __P ((pop3_t, stream_t));
extern int pop3_get_stream __P ((pop3_t, stream_t *));
extern int pop3_set_timeout __P ((pop3_t, unsigned int));
extern int pop3_get_timeout __P ((pop3_t, unsigned int *));
extern int pop3_apop __P ((pop3_t, const char *, const char *));
extern int pop3_capa __P ((pop3_t, iterator_t *));
extern int pop3_dele __P ((pop3_t, unsigned int));
extern int pop3_list __P ((pop3_t, unsigned int, size_t *));
extern int pop3_list_all __P ((pop3_t, iterator_t *));
extern int pop3_noop __P ((pop3_t));
extern int pop3_pass __P ((pop3_t, const char *));
extern int pop3_quit __P ((pop3_t));
extern int pop3_retr __P ((pop3_t, unsigned int, stream_t *));
extern int pop3_rset __P ((pop3_t));
extern int pop3_stat __P ((pop3_t, unsigned int *, size_t *));
extern int pop3_top __P ((pop3_t, unsigned int, unsigned int, stream_t *));
extern int pop3_uidl __P ((pop3_t, unsigned int, char **));
extern int pop3_uidl_all __P ((pop3_t, iterator_t *));
extern int pop3_user __P ((pop3_t, const char *));
extern int pop3_readline __P ((pop3_t, char *, size_t, size_t *));
extern int pop3_response __P ((pop3_t, char *, size_t, size_t *));
extern int pop3_writeline __P ((pop3_t, const char *, ...));
extern int pop3_sendline __P ((pop3_t, const char *));
extern int pop3_send __P ((pop3_t));
extern int pop3_create __P ((pop3_t *));
extern int pop3_destroy __P ((pop3_t));
extern int pop3_connect __P ((pop3_t, const char *, unsigned int));
extern int pop3_disconnect __P ((pop3_t));
extern int pop3_set_carrier __P ((pop3_t, stream_t));
extern int pop3_get_carrier __P ((pop3_t, stream_t *));
extern int pop3_set_timeout __P ((pop3_t, int));
extern int pop3_get_timeout __P ((pop3_t, int *));
extern int pop3_apop __P ((pop3_t, const char *, const char *));
extern int pop3_capa __P ((pop3_t, iterator_t *));
extern int pop3_capa_current __P ((iterator_t, char **));
extern int pop3_dele __P ((pop3_t, unsigned int));
extern int pop3_list __P ((pop3_t, unsigned int, size_t *));
extern int pop3_list_all __P ((pop3_t, iterator_t *));
extern int pop3_list_current __P ((iterator_t, unsigned int *, size_t *));
extern int pop3_noop __P ((pop3_t));
extern int pop3_pass __P ((pop3_t, const char *));
extern int pop3_quit __P ((pop3_t));
extern int pop3_retr __P ((pop3_t, unsigned int, stream_t *));
extern int pop3_rset __P ((pop3_t));
extern int pop3_stat __P ((pop3_t, unsigned int *, size_t *));
extern int pop3_top __P ((pop3_t, unsigned int,
unsigned int, stream_t *));
extern int pop3_uidl __P ((pop3_t, unsigned int, char **));
extern int pop3_uidl_all __P ((pop3_t, iterator_t *));
extern int pop3_uidl_current __P ((iterator_t, unsigned int *, char **));
extern int pop3_user __P ((pop3_t, const char *));
extern int pop3_readline __P ((pop3_t, char *, size_t, size_t *));
extern int pop3_response __P ((pop3_t, char *, size_t, size_t *));
extern int pop3_writeline __P ((pop3_t, const char *, ...));
extern int pop3_sendline __P ((pop3_t, const char *));
extern int pop3_send __P ((pop3_t));
#ifdef __cplusplus
}
......
......@@ -72,6 +72,12 @@ extern int stream_get_fd __P ((stream_t , int *));
extern int stream_get_flags __P ((stream_t, int *));
extern int stream_get_state __P ((stream_t, enum stream_state *));
extern int stream_is_readready __P ((stream_t, int));
extern int stream_is_writeready __P ((stream_t, int));
extern int stream_is_exceptionpending __P ((stream_t, int));
extern int stream_is_open __P ((stream_t));
/* Misc. */
extern int stream_file_create __P ((stream_t *));
extern int stream_mapfile_create __P ((stream_t *));
......
......@@ -23,8 +23,8 @@
#include <mailutils/pop3.h>
#include <mailutils/sys/stream.h>
#include <mailutils/sys/iterator.h>
#include <mailutils/monitor.h>
#include <mailutils/error.h>
#include <mailutils/monitor.h>
#ifdef DMALLOC
# include <dmalloc.h>
......@@ -61,7 +61,7 @@ struct p_iterator
pop3_t pop3;
unsigned int ref;
int done;
void *item;
char *item;
monitor_t lock;
};
......@@ -103,13 +103,11 @@ struct _pop3
unsigned timeout; /* Default is 10 minutes. */
enum pop3_state state;
stream_t stream; /* TCP Connection. */
monitor_t lock;
stream_t carrier; /* TCP Connection. */
};
extern int pop3_iterator_create __P ((pop3_t, iterator_t *));
extern int pop3_stream_create __P ((pop3_t, stream_t *));
extern void pop3_cleanup __P ((void *));
/* Check for non recoverable error. */
#define POP3_CHECK_EAGAIN(pop3, status) \
......
......@@ -47,6 +47,12 @@ struct _stream_vtable
int (*get_fd) __P ((stream_t , int *));
int (*get_flags) __P ((stream_t, int *));
int (*get_state) __P ((stream_t, enum stream_state *));
int (*is_readready) __P ((stream_t, int));
int (*is_writeready) __P ((stream_t, int));
int (*is_exceptionpending) __P ((stream_t, int));
int (*is_open) __P ((stream_t));
};
struct _stream
......
......@@ -238,6 +238,38 @@ _memory_tell (stream_t stream, off_t *off)
}
static int
_memory_is_open (stream_t stream)
{
(void)stream;
return 1;
}
static int
_memory_is_readready (stream_t stream, int timeout)
{
(void)stream;
(void)timeout;
return 1;
}
static int
_memory_is_writeready (stream_t stream, int timeout)
{
(void)stream;
(void)timeout;
return 1;
}
static int
_memory_is_exceptionpending (stream_t stream, int timeout)
{
(void)stream;
(void)timeout;
return 0;
}
static int
_memory_open (stream_t stream, const char *filename, int port, int flags)
{
struct _memory_stream *mem = (struct _memory_stream *)stream;
......@@ -278,7 +310,13 @@ static struct _stream_vtable _mem_vtable =
_memory_get_fd,
_memory_get_flags,
_memory_get_state
_memory_get_state,
_memory_is_readready,
_memory_is_writeready,
_memory_is_exceptionpending,
_memory_is_open
};
int
......
/* GNU mailutils - a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Library Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program 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 Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <mailutils/sys/mstream.h>
#include <mailutils/error.h>
#ifdef _POSIX_MAPPED_FILES
#include <sys/mman.h>
#ifndef MAP_FAILED
# define MAP_FAILED (void*)-1
#endif
static int
_ms_add_ref (stream_t stream)
{
int status;
struct _ms *ms = (struct _ms *)stream;
monitor_lock (ms->lock);
status = ++ms->ref;
monitor_unlock (ms->lock);
return status;
}
static int
_ms_destroy (stream_t stream)
{
struct _ms *ms = (struct _ms *)stream;
if (ms->ptr != MAP_FAILED)
{
if (ms->ptr)
munmap (ms->ptr, ms->size);
if (ms->fd != -1)
close (ms->fd);
monitor_destroy (ms->lock);
}
free (ms);
return 0;
}
static int
_ms_release (stream_t stream)
{
int status;
struct _ms *ms = (struct _ms *)stream;
monitor_lock (ms->lock);
status = --ms->ref;
if (status <= 0)
{
monitor_unlock (ms->lock);
_ms_destroy (stream);
return 0;
}
monitor_unlock (ms->lock);
return status;
}
static int
_ms_read (stream_t stream, void *optr, size_t osize, size_t *nbytes)
{
struct _ms *ms = (struct _ms *)stream;
size_t n = 0;
monitor_lock (ms->lock);
if (ms->ptr != MAP_FAILED && ms->ptr)
{
if (ms->offset < (off_t)ms->size)
{
n = ((ms->offset + osize) > ms->size) ?
ms->size - ms->offset : osize;
memcpy (optr, ms->ptr + ms->offset, n);
ms->offset += n;
}
}
monitor_unlock (ms->lock);
if (nbytes)
*nbytes = n;
return 0;
}
static int
_ms_readline (stream_t stream, char *optr, size_t osize, size_t *nbytes)
{
struct _ms *ms = (struct _ms *)stream;
size_t n = 0;
monitor_lock (ms->lock);
if (ms->ptr != MAP_FAILED && ms->ptr)
{
if (ms->offset < (off_t)ms->size)
{
/* Save space for the null byte. */
char *nl;
osize--;
nl = memchr (ms->ptr + ms->offset, '\n', ms->size - ms->offset);
n = (nl) ? nl - (ms->ptr + ms->offset) + 1 : ms->size - ms->offset;
n = (n > osize) ? osize : n;
memcpy (optr, ms->ptr + ms->offset, n);
optr[n] = '\0';
ms->offset += n;
}
}
monitor_unlock (ms->lock);
if (nbytes)
*nbytes = n;
return 0;
}
static int
_ms_write (stream_t stream, const void *iptr, size_t isize, size_t *nbytes)
{
struct _ms *ms = (struct _ms *)stream;
int err = 0;
size_t n = 0;
monitor_lock (ms->lock);
if (ms->mflags & PROT_WRITE)
{
/* Bigger we have to remmap. */
if (ms->size < (ms->offset + isize))
{
if (ms->ptr != MAP_FAILED && munmap (ms->ptr, ms->size) == 0)
{
ms->ptr = MAP_FAILED;
if (ftruncate (ms->fd, ms->offset + isize) == 0)
{
ms->ptr = mmap (0, ms->offset + isize, ms->mflags,
MAP_SHARED, ms->fd, 0);
if (ms->ptr != MAP_FAILED)
ms->size = ms->offset + isize;
}
}
}
if (ms->ptr != MAP_FAILED)
{
if (isize > 0)
memcpy (ms->ptr + ms->offset, iptr, isize);
ms->offset += isize;
n = isize;
}
else
err = MU_ERROR_IO;
}
else
err = MU_ERROR_IO;
monitor_unlock (ms->lock);
if (nbytes)
*nbytes = n;
return err;
}
static int
_ms_truncate (stream_t stream, off_t len)
{
struct _ms *ms = (struct _ms *)stream;
int err = 0;
monitor_lock (ms->lock);
if (ms->ptr != MAP_FAILED)
{
/* Remap. */
if (ms->ptr && munmap (ms->ptr, ms->size) == 0)
{
if (ftruncate (ms->fd, len) == 0)
{
ms->ptr = (len) ?
mmap (0, len, ms->mflags, MAP_SHARED, ms->fd, 0) : NULL;
if (ms->ptr != MAP_FAILED)
{
ms->size = len;
}
else
err = errno;
}
else
err = errno;
}
}
monitor_unlock (ms->lock);
return err;
}
static int
_ms_get_size (stream_t stream, off_t *psize)
{
struct _ms *ms = (struct _ms *)stream;
struct stat stbuf;
int err = 0;
monitor_lock (ms->lock);
stbuf.st_size = 0;
if (ms->ptr != MAP_FAILED)
{
if (ms->ptr)
msync (ms->ptr, ms->size, MS_SYNC);
if (fstat(ms->fd, &stbuf) == 0)
{
/* Remap. */
if (ms->size != (size_t)stbuf.st_size)
{
if (ms->ptr && munmap (ms->ptr, ms->size) == 0)
{
if (ms->size)
{
ms->ptr = mmap (0, ms->size, ms->mflags , MAP_SHARED,
ms->fd, 0);
if (ms->ptr != MAP_FAILED)
ms->size = stbuf.st_size;
else
err = errno;
}
else
ms->ptr = NULL;
}
else
err = errno;
}
}
}
monitor_unlock (ms->lock);
if (psize)
*psize = stbuf.st_size;
return err;
}
static int
_ms_flush (stream_t stream)
{
int err = 0;
struct _ms *ms = (struct _ms *)stream;
monitor_lock (ms->lock);
if (ms->ptr != MAP_FAILED && ms->ptr != NULL)
err = msync (ms->ptr, ms->size, MS_SYNC);
monitor_unlock (ms->lock);
return 0;
}
static int
_ms_get_fd (stream_t stream, int *pfd)
{
struct _ms *ms = (struct _ms *)stream;
if (pfd)
*pfd = ms->fd;
return 0;
}
static int
_ms_get_flags (stream_t stream, int *flags)
{
struct _ms *ms = (struct _ms *)stream;
if (flags == NULL)
return MU_ERROR_INVALID_PARAMETER;
*flags = ms->flags;
return 0;
}
static int
_ms_get_state (stream_t stream, enum stream_state *state)
{
(void)stream;
if (state == NULL)
return MU_ERROR_INVALID_PARAMETER;
*state = MU_STREAM_NO_STATE;
return 0;
}
static int
_ms_seek (stream_t stream, off_t off, enum stream_whence whence)
{
struct _ms *ms = (struct _ms *)stream;
off_t noff = ms->offset;
int err = 0;
if (whence == MU_STREAM_WHENCE_SET)
noff = off;
else if (whence == MU_STREAM_WHENCE_CUR)
noff += off;
else if (whence == MU_STREAM_WHENCE_END)
noff = ms->size + off;
else
noff = -1; /* error. */
if (noff >= 0)
{
if (noff > ms->offset)
_ms_truncate (stream, noff);
ms->offset = noff;
}
else
err = MU_ERROR_INVALID_PARAMETER;
return err;
}
static int
_ms_tell (stream_t stream, off_t *off)
{
struct _ms *ms = (struct _ms *)stream;
if (off == NULL)
return MU_ERROR_INVALID_PARAMETER;
*off = ms->offset;
return 0;
}
static int
_ms_close (stream_t stream)
{
struct _ms *ms = (struct _ms *)stream;
int err = 0;
monitor_lock (ms->lock);
if (ms->ptr != MAP_FAILED)
{
if (ms->ptr && munmap (ms->ptr, ms->size) != 0)
err = errno;
ms->ptr = MAP_FAILED;
}
if (ms->fd != -1)
if (close (ms->fd) != 0)
err = errno;
ms->fd = -1;
monitor_unlock (ms->lock);
return err;
}
static int
_ms_open (stream_t stream, const char *filename, int port, int flags)
{
struct _ms *ms = (struct _ms *)stream;
int mflag, flg;
struct stat st;
(void)port; /* Ignored. */
/* Close any previous file. */
if (ms->ptr != MAP_FAILED)
{
if (ms->ptr)
munmap (ms->ptr, ms->size);
ms->ptr = MAP_FAILED;
}
if (ms->fd != -1)
{
close (ms->fd);
ms->fd = -1;
}
/* Map the flags to the system equivalent */
if ((flags & MU_STREAM_WRITE) && (flags & MU_STREAM_READ))
return EINVAL;
else if (flags & MU_STREAM_WRITE)
{
mflag = PROT_WRITE;
flg = O_WRONLY;
}
else if (flags & MU_STREAM_RDWR)
{
mflag = PROT_READ | PROT_WRITE;
flg = O_RDWR;
}
else if (flags & MU_STREAM_CREAT)
return ENOSYS;
else /* default */
{
mflag = PROT_READ;
flg = O_RDONLY;
}
ms->fd = open (filename, flg);
if (ms->fd < 0)
return errno;
if (fstat (ms->fd, &st) != 0)
{
int err = errno;
close (ms->fd);
return err;
}
ms->size = st.st_size;
if (ms->size)
{
ms->ptr = mmap (0, ms->size, mflag , MAP_SHARED, ms->fd, 0);
if (ms->ptr == MAP_FAILED)
{
int err = errno;
close (ms->fd);
ms->ptr = MAP_FAILED;
return err;
}
}
else
ms->ptr = NULL;
ms->mflags = mflag;
ms->flags = flags;
return 0;
}
static struct _stream_vtable _ms_vtable =
{
_ms_add_ref,
_ms_release,
_ms_destroy,
_ms_open,
_ms_close,
_ms_read,
_ms_readline,
_ms_write,
_ms_seek,
_ms_tell,
_ms_get_size,
_ms_truncate,
_ms_flush,
_ms_get_fd,
_ms_get_flags,
_ms_get_state,
};
#endif /* _POSIX_MAPPED_FILES */
int
stream_mapfile_create (stream_t *pstream)
{
#ifndef _POSIX_MAPPED_FILES
return ENOSYS;
#else
struct _ms *ms;
if (pstream == NULL)
return MU_ERROR_INVALID_PARAMETER;
ms = calloc (1, sizeof *ms);
if (ms == NULL)
return MU_ERROR_NO_MEMORY;
ms->base.vtable = &_ms_vtable;
ms->ref = 1;
ms->fd = -1;
ms->offset = -1;
ms->flags = 0;
ms->mflags = 0;
monitor_create (&(ms->lock));
*pstream = &ms->base;
return 0;
#endif /* _POSIX_MAPPED_FILES */
}
......@@ -25,20 +25,19 @@
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#include <string.h>
#include <time.h>
#include <pwd.h>
#include <unistd.h>
#include <string.h>
#include <mailutils/mutil.h>
#ifdef HAVE_MYSQL
#include "../MySql/MySql.h"
#endif
#include <mailutils/list.h>
#include <mailutils/iterator.h>
/* convert a sequence of hex characters into an integer */
unsigned long mu_hex2ul(char hex)
unsigned long
mu_hex2ul (char hex)
{
if (hex >= '0' && hex <= '9')
return hex - '0';
......@@ -52,21 +51,22 @@ unsigned long mu_hex2ul(char hex)
return -1;
}
size_t mu_hexstr2ul(unsigned long* ul, const char* hex, size_t len)
size_t
mu_hexstr2ul (unsigned long *ul, const char *hex, size_t len)
{
size_t r;
*ul = 0;
for (r = 0; r < len; r++)
{
unsigned long v = mu_hex2ul(hex[r]);
{
unsigned long v = mu_hex2ul (hex[r]);
if (v == (unsigned long)-1)
return r;
if (v == (unsigned long)-1)
return r;
*ul = *ul * 16 + v;
}
*ul = *ul * 16 + v;
}
return r;
}
......@@ -86,18 +86,18 @@ mu_tm2time (struct tm *timeptr, mu_timezone* tz)
{
int offset = tz ? tz->utc_offset : 0;
return mktime(timeptr) + mu_utc_offset() - offset;
return mktime (timeptr) + mu_utc_offset () - offset;
}
/* Convert time 0 at UTC to our localtime, that tells us the offset
of our current timezone from UTC. */
time_t
mu_utc_offset(void)
mu_utc_offset (void)
{
time_t t = 0;
struct tm* tm = gmtime(&t);
struct tm* tm = gmtime (&t);
return - mktime(tm);
return - mktime (tm);
}
static const char *months[] =
......@@ -246,7 +246,6 @@ mu_parse_ctime_date_time (const char **p, struct tm *tm, mu_timezone * tz)
return 0;
}
char *
mu_get_homedir (void)
{
......@@ -255,7 +254,7 @@ mu_get_homedir (void)
{
struct passwd *pwd;
pwd = getpwuid(getuid());
pwd = getpwuid (getuid ());
if (!pwd)
return NULL;
homedir = pwd->pw_dir;
......@@ -298,11 +297,7 @@ mu_tilde_expansion (const char *ref, const char *delim, const char *homedir)
name = calloc (s - p + 1, 1);
memcpy (name, p, s - p);
name [s - p] = '\0';
pw = getpwnam (name);
#ifdef HAVE_MYSQL
if (!pw)
pw = getMpwnam(name);
#endif /* HAVE_MYSQL */
pw = mu_getpwnam (name);
free (name);
if (pw)
{
......@@ -333,3 +328,80 @@ util_cpystr (char *dst, const char *src, size_t size)
dst[len] = '\0';
return len;
}
static list_t _app_getpwnam = NULL;
void
mu_register_getpwnam (struct passwd *(*fun) __P((const char *)))
{
if (!_app_getpwnam && list_create (&_app_getpwnam))
return;
list_append (_app_getpwnam, fun);
}
struct passwd *
mu_getpwnam (const char *name)
{
struct passwd *p;
iterator_t itr;
p = getpwnam (name);
if (!p && iterator_create (&itr, _app_getpwnam) == 0)
{
struct passwd *(*fun) __P((const char *));
for (iterator_first (itr); !p && !iterator_is_done (itr);
iterator_next (itr))
{
iterator_current (itr, (void **)&fun);
p = (*fun) (name);
}
iterator_destroy (&itr);
}
return p;
}
int mu_virtual_domain;
#ifdef USE_VIRTUAL_DOMAINS
struct passwd *
getpwnam_virtual (const char *u)
{
struct passwd *pw = NULL;
FILE *pfile;
size_t i = 0, len = strlen (u), delim = 0;
char *filename;
mu_virtual_domain = 0;
for (i = 0; i < len && delim == 0; i++)
if (u[i] == '!' || u[i] == ':' || u[i] == '@')
delim = i;
if (delim == 0)
return NULL;
filename = malloc (strlen (SITE_VIRTUAL_PWDDIR) +
strlen (&u[delim + 1]) + 2 /* slash and null byte */);
if (filename == NULL)
return NULL;
sprintf (filename, "%s/%s", SITE_VIRTUAL_PWDDIR, &u[delim + 1]);
pfile = fopen (filename, "r");
free (filename);
if (pfile)
while ((pw = fgetpwent (pfile)) != NULL)
{
if (strlen (pw->pw_name) == delim && !strncmp (u, pw->pw_name, delim))
{
mu_virtual_domain = 1;
break;
}
}
return pw;
}
#endif
......
......@@ -10,6 +10,7 @@ lib_LTLIBRARIES = libpop3.la
libmailbox_la_SOURCES = \
pop3_apop.c \
pop3_capa.c \
pop3_carrier.c \
pop3_cleanup.c \
pop3_connect.c \
pop3_create.c \
......
......@@ -29,12 +29,16 @@
APOP name digest
a string identifying a mailbox and a MD5 digest string (both required)
*/
static int
pop3_apop0 (pop3_t pop3, const char *user, const char *secret)
int
pop3_apop (pop3_t pop3, const char *user, const char *secret)
{
int status;
/* The server did not offer a time stamp in the greeting, bailout early. */
/* Sanity checks. */
if (pop3 == NULL || user == NULL || secret == NULL)
return MU_ERROR_INVALID_PARAMETER;
/* The server did not offer a timestamp in the greeting, bailout early. */
if (pop3->timestamp == NULL)
return MU_ERROR_NOT_SUPPORTED;
......@@ -49,9 +53,6 @@ pop3_apop0 (pop3_t pop3, const char *user, const char *secret)
char *tmp;
size_t n;
if (user == NULL || secret == NULL)
return MU_ERROR_INVALID_PARAMETER;
MD5Init (&md5context);
MD5Update (&md5context, (unsigned char *)pop3->timestamp,
strlen (pop3->timestamp));
......@@ -90,19 +91,3 @@ pop3_apop0 (pop3_t pop3, const char *user, const char *secret)
return status;
}
int
pop3_apop (pop3_t pop3, const char *user, const char *secret)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_apop0 (pop3, user, secret);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -24,11 +24,14 @@
#include <stddef.h>
#include <mailutils/sys/pop3.h>
static int
pop3_capa0 (pop3_t pop3, iterator_t *piterator)
int
pop3_capa (pop3_t pop3, iterator_t *piterator)
{
int status;
if (pop3 == NULL || piterator == NULL)
return MU_ERROR_INVALID_PARAMETER;
switch (pop3->state)
{
case POP3_NO_STATE:
......@@ -64,19 +67,3 @@ pop3_capa0 (pop3_t pop3, iterator_t *piterator)
return status;
}
int
pop3_capa (pop3_t pop3, iterator_t *piterator)
{
int status;
if (pop3 == NULL || piterator == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_capa0 (pop3, piterator);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
/* GNU mailutils - a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Library Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program 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 Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <stdlib.h>
#include <mailutils/sys/pop3.h>
int
pop3_set_carrier (pop3_t pop3, stream_t carrier)
{
/* Sanity checks. */
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
if (pop3->carrier)
{
stream_close (pop3->carrier);
stream_release (pop3->carrier);
}
pop3->carrier = carrier;
return 0;
}
int
pop3_get_carrier (pop3_t pop3, stream_t *pcarrier)
{
/* Sanity checks. */
if (pop3 == NULL || pcarrier == NULL)
return MU_ERROR_INVALID_PARAMETER;
if (pop3->carrier == NULL)
{
stream_t carrier = NULL;
int status = stream_tcp_create (&carrier);
if (status != 0)
return status;
status = stream_buffer_create (&(pop3->carrier), carrier, 1024);
if (status != 0)
{
stream_release (carrier);
return status;
}
}
/* Incremente the ref count, since we are exposing it. */
stream_add_ref (pop3->carrier);
*pcarrier = pop3->carrier;
return 0;
}
......@@ -33,11 +33,15 @@ static int pop3_sleep (int seconds);
/* Open the connection to the server. The server sends an affirmative greeting
that may contain a timestamp for APOP. */
static int
pop3_connect0 (pop3_t pop3, const char *host, unsigned int port)
int
pop3_connect (pop3_t pop3, const char *host, unsigned int port)
{
int status;
/* Sanity checks. */
if (pop3 == NULL || host == NULL)
return MU_ERROR_INVALID_PARAMETER;
/* Default is 110. */
if (!port)
port = 110;
......@@ -46,15 +50,18 @@ pop3_connect0 (pop3_t pop3, const char *host, unsigned int port)
switch (pop3->state)
{
default:
/* __Fallthrough__, they want to clear an error. */
/* FALLTHROUGH */
/* If pop3 was in an error state going through here should clear it. */
case POP3_NO_STATE:
/* Create the networking stack. */
if (pop3->stream == NULL)
if (pop3->carrier == NULL)
{
status = stream_tcp_create (&(pop3->stream));
stream_t carrier;
status = pop3_get_carrier (pop3, &carrier);
POP3_CHECK_ERROR (pop3, status);
/* Using the awkward stream_t buffering. */
/*stream_setbufsiz (pop3->stream, 1024); */
/* A add_ref was done part of pop3_get_carrier(). */
stream_release (carrier);
}
else
{
......@@ -65,8 +72,8 @@ pop3_connect0 (pop3_t pop3, const char *host, unsigned int port)
to read a new message, closing the connection and immediately
contacting the server again, and he'll end up having
"-ERR Mail Lock busy" or something similar. To prevent this race
condition we sleep 2 seconds. This really obvious for in
environment where QPopper is use, the user as a big mailbox. */
condition we sleep 2 seconds. This is really obvious for in
environment where QPopper is use and the user as a big mailbox. */
pop3_disconnect (pop3);
pop3_sleep (2);
}
......@@ -74,7 +81,7 @@ pop3_connect0 (pop3_t pop3, const char *host, unsigned int port)
case POP3_CONNECT:
/* Establish the connection. */
status = stream_open (pop3->stream, host, port,
status = stream_open (pop3->carrier, host, port,
MU_STREAM_READ|MU_STREAM_WRITE);
POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
......@@ -89,7 +96,7 @@ pop3_connect0 (pop3_t pop3, const char *host, unsigned int port)
POP3_CHECK_EAGAIN (pop3, status);
if (strncasecmp (pop3->ack.buf, "+OK", 3) != 0)
{
stream_close (pop3->stream);
stream_close (pop3->carrier);
pop3->state = POP3_NO_STATE;
return MU_ERROR_OPERATION_DENIED;
}
......@@ -106,7 +113,7 @@ pop3_connect0 (pop3_t pop3, const char *host, unsigned int port)
pop3->timestamp = calloc (len + 1, 1);
if (pop3->timestamp == NULL)
{
stream_close (pop3->stream);
stream_close (pop3->carrier);
POP3_CHECK_ERROR (pop3, MU_ERROR_NO_MEMORY);
}
/* Do not copy the surrounding '<>'. */
......@@ -130,21 +137,3 @@ pop3_sleep (int seconds)
tval.tv_usec = 0;
return select (1, NULL, NULL, NULL, &tval);
}
int
pop3_connect (pop3_t pop3, const char *host, unsigned int port)
{
int status;
/* Sanity checks. */
if (pop3 == NULL || host == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_connect0 (pop3, host, port);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -24,11 +24,13 @@
#include <mailutils/sys/pop3.h>
/* Initialise a pop3_t handle. */
int
pop3_create (pop3_t *ppop3)
{
pop3_t pop3;
/* Sanity check. */
if (ppop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
......@@ -36,32 +38,33 @@ pop3_create (pop3_t *ppop3)
if (pop3 == NULL)
return MU_ERROR_NO_MEMORY;
/* Reserve space for the ack(nowledgement) response. */
/* According to RFC 2449: The maximum length of the first line of a
command response (including the initial greeting) is unchanged at
512 octets (including the terminating CRLF). */
pop3->ack.len = 512;
pop3->ack.ptr = pop3->ack.buf = calloc (pop3->ack.len, 1);
pop3->ack.buf = calloc (pop3->ack.len, 1);
if (pop3->ack.buf == NULL)
{
pop3_destroy (pop3);
return MU_ERROR_NO_MEMORY;
}
pop3->ack.ptr = pop3->ack.buf;
/* RFC 2449 recommands 255, but we grow it as needed. */
pop3->io.len = 255;
pop3->io.ptr = pop3->io.buf = calloc (pop3->io.len, 1);
pop3->io.buf = calloc (pop3->io.len, 1);
if (pop3->io.buf == NULL)
{
pop3_destroy (pop3);
return MU_ERROR_NO_MEMORY;
}
pop3->io.ptr = pop3->io.buf;
pop3->state = POP3_NO_STATE; /* Init with no state. */
pop3->timeout = 10 * 60; /* The default Timeout is 10 minutes. */
pop3->timeout = (10 * 60) * 100; /* The default Timeout is 10 minutes. */
pop3->acknowledge = 0; /* No Ack received. */
monitor_create (&(pop3->lock));
*ppop3 = pop3;
return 0; /* Okdoke. */
}
......
......@@ -26,11 +26,14 @@
#include <mailutils/sys/pop3.h>
static int
pop3_dele0 (pop3_t pop3, unsigned msgno)
int
pop3_dele (pop3_t pop3, unsigned msgno)
{
int status;
if (pop3 == NULL || msgno == 0)
return MU_ERROR_INVALID_PARAMETER;
switch (pop3->state)
{
case POP3_NO_STATE:
......@@ -61,19 +64,3 @@ pop3_dele0 (pop3_t pop3, unsigned msgno)
}
return status;
}
int
pop3_dele (pop3_t pop3, unsigned msgno)
{
int status;
if (pop3 == NULL || msgno == 0)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_dele0 (pop3, msgno);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -23,7 +23,7 @@
#include <mailutils/sys/pop3.h>
#include <stdlib.h>
void
int
pop3_destroy (pop3_t pop3)
{
if (pop3)
......@@ -37,8 +37,7 @@ pop3_destroy (pop3_t pop3)
if (pop3->timestamp)
free (pop3->timestamp);
monitor_destroy (pop3->lock);
free (pop3);
}
return 0;
}
......
......@@ -23,10 +23,14 @@
#include <stdlib.h>
#include <string.h>
/* Sudden death. */
static int
pop3_disconnect0 (pop3_t pop3)
int
pop3_disconnect (pop3_t pop3)
{
/* Sanity checks. */
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
/* We can keep some of the fields, if they decide to pop3_open() again but
clear the states. */
pop3->state = POP3_NO_STATE;
......@@ -40,24 +44,7 @@ pop3_disconnect0 (pop3_t pop3)
free (pop3->timestamp);
pop3->timestamp = NULL;
}
if (pop3->stream)
return stream_close (pop3->stream);
if (pop3->carrier)
return stream_close (pop3->carrier);
return 0;
}
int
pop3_disconnect (pop3_t pop3)
{
int status;
/* Sanity checks. */
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_disconnect0 (pop3);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -123,7 +123,6 @@ p_destroy (iterator_t iterator)
return 0;
}
static int
p_first (iterator_t iterator)
{
......@@ -149,108 +148,20 @@ p_next (iterator_t iterator)
{
if (n)
{
switch (p_iterator->pop3->state)
char *buf;
buf = calloc (n + 1, 1);
if (buf)
{
case POP3_CAPA_RX:
{
char *buf;
buf = calloc (n + 1, 1);
if (buf)
{
/* Consume. */
pop3_readline (p_iterator->pop3, buf, n + 1, NULL);
if (buf[n - 1] == '\n')
buf[n - 1] = '\0';
if (p_iterator->item)
free (p_iterator->item);
p_iterator->item = buf;
}
else
status = MU_ERROR_NO_MEMORY;
break;
}
case POP3_UIDL_RX:
{
struct pop3_uidl_item *pitem;
char *buf = calloc (n + 1, 1);
if (buf)
{
if (p_iterator->item)
{
pitem = p_iterator->item;
if (pitem->uidl)
free (pitem->uidl);
free (pitem);
}
p_iterator->item = calloc (1, sizeof *pitem);
pitem = p_iterator->item;
if (pitem)
{
unsigned msgno;
char *space;
/* Consume. */
pop3_readline (p_iterator->pop3, buf,
n + 1, NULL);
msgno = 0;
/* The format is:
msgno uidlsttring */
space = strchr (buf, ' ');
if (space)
{
*space++ = '\0';
msgno = strtoul (buf, NULL, 10);
}
if (space && space[strlen (space) - 1] == '\n')
space[strlen (space) - 1] = '\0';
if (space == NULL)
space = (char *)"";
pitem->msgno = msgno;
pitem->uidl = strdup (space);
}
else
status = MU_ERROR_NO_MEMORY;
free (buf);
}
else
status = MU_ERROR_NO_MEMORY;
break;
}
case POP3_LIST_RX:
{
struct pop3_list_item *pitem;
char *buf = calloc (n + 1, 1);
if (buf)
{
if (p_iterator->item)
free (p_iterator->item);
pitem = calloc (1, sizeof *pitem);
p_iterator->item = pitem;
if (pitem)
{
unsigned msgno;
size_t size;
/* Consume. */
pop3_readline (p_iterator->pop3, buf,
n + 1, NULL);
size = msgno = 0;
sscanf (buf, "%d %d", &msgno, &size);
pitem->msgno = msgno;
pitem->size = size;
}
else
status = MU_ERROR_NO_MEMORY;
free (buf);
}
else
status = MU_ERROR_NO_MEMORY;
break;
}
default:
/* Consume. */
pop3_readline (p_iterator->pop3, buf, n + 1, NULL);
if (buf[n - 1] == '\n')
buf[n - 1] = '\0';
if (p_iterator->item)
free (p_iterator->item);
p_iterator->item = buf;
}
else
status = MU_ERROR_NO_MEMORY;
}
else
{
......@@ -287,21 +198,9 @@ p_current (iterator_t iterator, void *item)
monitor_lock (p_iterator->lock);
if (item)
{
switch (p_iterator->pop3->state)
{
case POP3_CAPA_RX:
case POP3_UIDL_RX:
*((char **)item) = p_iterator->item;
break;
case POP3_LIST_RX:
*((struct pop3_list_item **)item) = p_iterator->item;
break;
default:
}
*((char **)item) = p_iterator->item;
p_iterator->item = NULL;
}
p_iterator->item = NULL;
monitor_unlock (p_iterator->lock);
}
return 0;
......
......@@ -28,11 +28,14 @@
#include <stdio.h>
#include <mailutils/sys/pop3.h>
static int
pop3_list0 (pop3_t pop3, unsigned msgno, size_t *psize)
int
pop3_list (pop3_t pop3, unsigned int msgno, size_t *psize)
{
int status;
if (pop3 == NULL || msgno == 0 || psize == NULL)
return MU_ERROR_INVALID_PARAMETER;
switch (pop3->state)
{
case POP3_NO_STATE:
......@@ -70,18 +73,3 @@ pop3_list0 (pop3_t pop3, unsigned msgno, size_t *psize)
return status;
}
int
pop3_list (pop3_t pop3, unsigned msgno, size_t *psize)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_list0 (pop3, msgno, psize);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -25,19 +25,21 @@
# include <strings.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <mailutils/sys/pop3.h>
static int
pop3_list_all0 (pop3_t pop3, iterator_t *piterator)
int
pop3_list_all (pop3_t pop3, iterator_t *piterator)
{
int status;
if (pop3 == NULL || piterator == NULL)
return MU_ERROR_INVALID_PARAMETER;
switch (pop3->state)
{
case POP3_NO_STATE:
if (piterator == NULL)
return MU_ERROR_INVALID_PARAMETER;
status = pop3_writeline (pop3, "LIST\r\n");
POP3_CHECK_ERROR (pop3, status);
pop3->state = POP3_LIST;
......@@ -72,17 +74,21 @@ pop3_list_all0 (pop3_t pop3, iterator_t *piterator)
}
int
pop3_list_all (pop3_t pop3, iterator_t *piterator)
pop3_list_current (iterator_t iterator, unsigned int *pno, size_t *plen)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_list_all0 (pop3, piterator);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
char *buf;
int status = iterator_current (iterator, (void *)&buf);
if (status == 0)
{
size_t size;
unsigned int msgno;
size = msgno = 0;
sscanf (buf, "%d %d", &msgno, &size);
if (pno)
*pno = msgno;
if (plen)
*plen = size;
free (buf);
}
return status;
}
......
......@@ -27,11 +27,14 @@
#include <mailutils/sys/pop3.h>
static int
pop3_noop0 (pop3_t pop3)
int
pop3_noop (pop3_t pop3)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
switch (pop3->state)
{
case POP3_NO_STATE:
......@@ -63,20 +66,3 @@ pop3_noop0 (pop3_t pop3)
return status;
}
int
pop3_noop (pop3_t pop3)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_noop0 (pop3);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -27,16 +27,17 @@
#include <mailutils/sys/pop3.h>
static int
pop3_pass0 (pop3_t pop3, const char *passwd)
int
pop3_pass (pop3_t pop3, const char *passwd)
{
int status;
if (pop3 == NULL || passwd == NULL)
return MU_ERROR_INVALID_PARAMETER;
switch (pop3->state)
{
case POP3_NO_STATE:
if (passwd == NULL)
return MU_ERROR_INVALID_PARAMETER;
status = pop3_writeline (pop3, "PASS %s\r\n", passwd);
POP3_CHECK_ERROR (pop3, status);
pop3->state = POP3_PASS;
......@@ -65,19 +66,3 @@ pop3_pass0 (pop3_t pop3, const char *passwd)
return status;
}
int
pop3_pass (pop3_t pop3, const char *passwd)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_pass0 (pop3, passwd);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -27,11 +27,14 @@
#include <mailutils/sys/pop3.h>
static int
pop3_quit0 (pop3_t pop3)
int
pop3_quit (pop3_t pop3)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
switch (pop3->state)
{
case POP3_NO_STATE:
......@@ -58,19 +61,3 @@ pop3_quit0 (pop3_t pop3)
return status;
}
int
pop3_quit (pop3_t pop3)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_quit0 (pop3);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -19,9 +19,9 @@
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <mailutils/sys/pop3.h>
......@@ -29,7 +29,7 @@
/* Read a complete line from the pop server. Transform CRLF to LF, remove
the stuff byte termination octet ".", put a null in the buffer
when done. */
when done. And Do a select() (stream_is_readready()) for the timeout. */
static int
pop3_getline (pop3_t pop3)
{
......@@ -44,38 +44,12 @@ pop3_getline (pop3_t pop3)
since on linux tv is modified when error. */
if (pop3->timeout)
{
/* Heavy hand but continue if select trip on a signal. */
for (;;)
{
int fd = -1;
struct timeval tv;
fd_set rfds;
status = stream_get_fd (pop3->stream, &fd);
if (status != 0)
return status;
if (fd == -1)
return MU_ERROR_IO;
FD_ZERO (&rfds);
FD_SET (fd, &rfds);
tv.tv_sec = pop3->timeout;
tv.tv_usec = 0;
status = select (fd + 1, &rfds, NULL, NULL, &tv);
if (status == 0)
return MU_ERROR_TIMEOUT;
else if (status == -1)
{
if (errno == EINTR)
continue;
return MU_ERROR_IO;
}
break;
}
int ready = stream_is_readready (pop3->carrier, pop3->timeout);
if (ready == 0)
return MU_ERROR_TIMEOUT;
}
status = stream_readline (pop3->stream, pop3->io.buf + total,
status = stream_readline (pop3->carrier, pop3->io.buf + total,
pop3->io.len - total, &n);
if (status != 0)
return status;
......@@ -90,7 +64,7 @@ pop3_getline (pop3_t pop3)
if (pop3->io.nl == NULL) /* Do we have a full line. */
{
/* Allocate a bigger buffer ? */
if (total >= pop3->io.len -1)
if (total >= pop3->io.len - 1)
{
pop3->io.len *= 2;
pop3->io.buf = realloc (pop3->io.buf, pop3->io.len + 1);
......@@ -134,6 +108,11 @@ pop3_getline (pop3_t pop3)
return status;
} /* if need to fill up. */
/* Call pop3_getline() for the dirty work, and consume i.e. put
in the user buffer only buflen. If buflen == 0 or buffer == NULL
nothing is consume, the data is save for another call to pop3_readline()
with a buffer != NULL.
*/
int
pop3_readline (pop3_t pop3, char *buffer, size_t buflen, size_t *pnread)
{
......@@ -142,7 +121,7 @@ pop3_readline (pop3_t pop3, char *buffer, size_t buflen, size_t *pnread)
int status;
/* Do we need to fill up? Yes if no NL or the buffer is empty. */
if (pop3->stream && (pop3->io.nl == NULL || pop3->io.ptr == pop3->io.buf))
if (pop3->carrier && (pop3->io.nl == NULL || pop3->io.ptr == pop3->io.buf))
{
status = pop3_getline (pop3);
if (status != 0)
......
......@@ -27,11 +27,14 @@
#include <mailutils/sys/pop3.h>
static int
pop3_retr0 (pop3_t pop3, unsigned msgno, stream_t *pstream)
int
pop3_retr (pop3_t pop3, unsigned int msgno, stream_t *pstream)
{
int status;
if (pop3 == NULL || msgno == 0 || pstream == NULL)
return MU_ERROR_INVALID_PARAMETER;
switch (pop3->state)
{
case POP3_NO_STATE:
......@@ -67,19 +70,3 @@ pop3_retr0 (pop3_t pop3, unsigned msgno, stream_t *pstream)
return status;
}
int
pop3_retr (pop3_t pop3, unsigned msgno, stream_t *pstream)
{
int status;
if (pop3 == NULL || pstream == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_retr0 (pop3, msgno, pstream);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -27,11 +27,14 @@
#include <mailutils/sys/pop3.h>
static int
pop3_rset0 (pop3_t pop3)
int
pop3_rset (pop3_t pop3)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
switch (pop3->state)
{
case POP3_NO_STATE:
......@@ -63,19 +66,3 @@ pop3_rset0 (pop3_t pop3)
return status;
}
int
pop3_rset (pop3_t pop3)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_rset0 (pop3);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -40,7 +40,7 @@ int
pop3_send (pop3_t pop3)
{
int status = 0;
if (pop3->stream && (pop3->io.ptr > pop3->io.buf))
if (pop3->carrier && (pop3->io.ptr > pop3->io.buf))
{
size_t n = 0;
size_t len = pop3->io.ptr - pop3->io.buf;
......@@ -49,34 +49,12 @@ pop3_send (pop3_t pop3)
since on linux tv is modified when error. */
if (pop3->timeout)
{
for (;;)
{
int fd = -1;
struct timeval tv;
fd_set wfds;
status = stream_get_fd (pop3->stream, &fd);
if (status != 0)
return status;
FD_ZERO (&wfds);
FD_SET (fd, &wfds);
tv.tv_sec = pop3->timeout;
tv.tv_usec = 0;
status = select (fd + 1, NULL, &wfds, NULL, &tv);
if (status == 0)
return MU_ERROR_TIMEOUT;
else if (status == -1)
{
if (errno == EINTR)
continue;
return MU_ERROR_IO;
}
break;
}
int ready = stream_is_writeready (pop3->carrier, pop3->timeout);
if (ready == 0)
return MU_ERROR_TIMEOUT;
}
status = stream_write (pop3->stream, pop3->io.buf, len, &n);
status = stream_write (pop3->carrier, pop3->io.buf, len, &n);
if (n)
{
/* Consume what we sent. */
......
......@@ -28,16 +28,17 @@
#include <mailutils/sys/pop3.h>
static int
pop3_stat0 (pop3_t pop3, unsigned *msg_count, size_t *size)
int
pop3_stat (pop3_t pop3, unsigned *msg_count, size_t *size)
{
int status;
if (pop3 == NULL || msg_count == NULL || size == NULL)
return MU_ERROR_INVALID_PARAMETER;
switch (pop3->state)
{
case POP3_NO_STATE:
if (msg_count == NULL || size == NULL)
return MU_ERROR_INVALID_PARAMETER;
status = pop3_writeline (pop3, "STAT\r\n");
POP3_CHECK_ERROR (pop3, status);
pop3->state = POP3_STAT;
......@@ -71,19 +72,3 @@ pop3_stat0 (pop3_t pop3, unsigned *msg_count, size_t *size)
return status;
}
int
pop3_stat (pop3_t pop3, unsigned *msg_count, size_t *size)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_stat0 (pop3, msg_count, size);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -27,37 +27,6 @@
#include <stdlib.h>
#include <mailutils/sys/pop3.h>
int
pop3_set_stream (pop3_t pop3, stream_t stream)
{
/* Sanity checks. */
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
/* If the stream was set before we will leak. But do what they say. */
pop3->stream = stream;
return 0;
}
int
pop3_get_stream (pop3_t pop3, stream_t *pstream)
{
/* Sanity checks. */
if (pop3 == NULL || pstream == NULL)
return MU_ERROR_INVALID_PARAMETER;
if (pop3->stream == NULL)
{
stream_t stream = NULL;
int status = stream_tcp_create (&stream);
if (status)
return status;
stream_buffer_create (&(pop3->stream), stream, 1024);
}
*pstream = pop3->stream;
return 0;
}
/* Implementation of the stream for TOP and RETR. */
static int p_add_ref __P ((stream_t));
static int p_release __P ((stream_t));
......@@ -81,6 +50,12 @@ static int p_get_fd __P ((stream_t, int *));
static int p_get_flags __P ((stream_t, int *));
static int p_get_state __P ((stream_t, enum stream_state *));
static int p_is_readready __P ((stream_t, int timeout));
static int p_is_writeready __P ((stream_t, int timeout));
static int p_is_exceptionpending __P ((stream_t, int timeout));
static int p_is_open __P ((stream_t));
static struct _stream_vtable p_s_vtable =
{
p_add_ref,
......@@ -104,6 +79,12 @@ static struct _stream_vtable p_s_vtable =
p_get_fd,
p_get_flags,
p_get_state,
p_is_readready,
p_is_writeready,
p_is_exceptionpending,
p_is_open
};
int
......@@ -207,10 +188,9 @@ p_read (stream_t stream, void *buf, size_t buflen, size_t *pn)
size_t nread = 0;
/* The pop3_readline () function will always read one less to
be able to terminate the buffer, this will cause serious grief
for stream_read() where it is legitimate to have a buffer of
1 char. So we must catch it here or change the behaviour of
XXX_readline. */
be able to null terminate the buffer, this will cause
serious grief for stream_read() where it is legitimate to
have a buffer of 1 char. So we must catch it here. */
if (buflen == 1)
{
char buffer[2];
......@@ -271,61 +251,89 @@ static int
p_write (stream_t stream, const void *buf, size_t buflen, size_t *pn)
{
struct p_stream *p_stream = (struct p_stream *)stream;
return stream_write (p_stream->pop3->stream, buf, buflen, pn);
return stream_write (p_stream->pop3->carrier, buf, buflen, pn);
}
static int
p_seek (stream_t stream, off_t offset, enum stream_whence whence)
{
struct p_stream *p_stream = (struct p_stream *)stream;
return stream_seek (p_stream->pop3->stream, offset, whence);
return stream_seek (p_stream->pop3->carrier, offset, whence);
}
static int
p_tell (stream_t stream, off_t *offset)
{
struct p_stream *p_stream = (struct p_stream *)stream;
return stream_tell (p_stream->pop3->stream, offset);
return stream_tell (p_stream->pop3->carrier, offset);
}
static int
p_get_size (stream_t stream, off_t *size)
{
struct p_stream *p_stream = (struct p_stream *)stream;
return stream_get_size (p_stream->pop3->stream, size);
return stream_get_size (p_stream->pop3->carrier, size);
}
static int
p_truncate (stream_t stream, off_t size)
{
struct p_stream *p_stream = (struct p_stream *)stream;
return stream_truncate (p_stream->pop3->stream, size);
return stream_truncate (p_stream->pop3->carrier, size);
}
static int
p_flush (stream_t stream)
{
struct p_stream *p_stream = (struct p_stream *)stream;
return stream_flush (p_stream->pop3->stream);
return stream_flush (p_stream->pop3->carrier);
}
static int
p_get_fd (stream_t stream, int *fd)
{
struct p_stream *p_stream = (struct p_stream *)stream;
return stream_get_fd (p_stream->pop3->stream, fd);
return stream_get_fd (p_stream->pop3->carrier, fd);
}
static int
p_get_flags (stream_t stream, int *flags)
{
struct p_stream *p_stream = (struct p_stream *)stream;
return stream_get_flags (p_stream->pop3->stream, flags);
return stream_get_flags (p_stream->pop3->carrier, flags);
}
static int
p_get_state (stream_t stream, enum stream_state *state)
{
struct p_stream *p_stream = (struct p_stream *)stream;
return stream_get_state (p_stream->pop3->stream, state);
return stream_get_state (p_stream->pop3->carrier, state);
}
static int
p_is_readready (stream_t stream, int timeout)
{
struct p_stream *p_stream = (struct p_stream *)stream;
return stream_is_readready (p_stream->pop3->carrier, timeout);
}
static int
p_is_writeready (stream_t stream, int timeout)
{
struct p_stream *p_stream = (struct p_stream *)stream;
return stream_is_writeready (p_stream->pop3->carrier, timeout);
}
static int
p_is_exceptionpending (stream_t stream, int timeout)
{
struct p_stream *p_stream = (struct p_stream *)stream;
return stream_is_exceptionpending (p_stream->pop3->carrier, timeout);
}
static int
p_is_open (stream_t stream)
{
struct p_stream *p_stream = (struct p_stream *)stream;
return stream_is_open (p_stream->pop3->carrier);
}
......
......@@ -23,7 +23,7 @@
#include <stdlib.h>
int
pop3_set_timeout (pop3_t pop3, unsigned int timeout)
pop3_set_timeout (pop3_t pop3, int timeout)
{
/* Sanity checks. */
if (pop3 == NULL)
......@@ -34,7 +34,7 @@ pop3_set_timeout (pop3_t pop3, unsigned int timeout)
}
int
pop3_get_timeout (pop3_t pop3, unsigned int *ptimeout)
pop3_get_timeout (pop3_t pop3, int *ptimeout)
{
/* Sanity checks. */
if (pop3 == NULL || ptimeout == NULL)
......
......@@ -27,16 +27,18 @@
#include <mailutils/sys/pop3.h>
static int
pop3_top0 (pop3_t pop3, unsigned msgno, size_t lines, stream_t *pstream)
int
pop3_top (pop3_t pop3, unsigned msgno, unsigned int lines, stream_t *pstream)
{
int status;
if (pop3 == NULL || msgno == 0 || pstream == NULL)
return MU_ERROR_INVALID_PARAMETER;
switch (pop3->state)
{
case POP3_NO_STATE:
if (pstream == NULL)
return MU_ERROR_INVALID_PARAMETER;
status = pop3_writeline (pop3, "TOP %d %d\r\n", msgno, lines);
POP3_CHECK_ERROR (pop3, status);
pop3->state = POP3_TOP;
......@@ -69,19 +71,3 @@ pop3_top0 (pop3_t pop3, unsigned msgno, size_t lines, stream_t *pstream)
return status;
}
int
pop3_top (pop3_t pop3, unsigned msgno, size_t lines, stream_t *pstream)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_top0 (pop3, msgno, lines, pstream);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -28,16 +28,17 @@
#include <stdlib.h>
#include <mailutils/sys/pop3.h>
static int
pop3_uidl0 (pop3_t pop3, unsigned msgno, char **uidl)
int
pop3_uidl (pop3_t pop3, unsigned msgno, char **uidl)
{
int status;
if (pop3 == NULL || uidl == NULL)
return MU_ERROR_INVALID_PARAMETER;
switch (pop3->state)
{
case POP3_NO_STATE:
if (uidl == NULL)
return MU_ERROR_INVALID_PARAMETER;
status = pop3_writeline (pop3, "UIDL %d\r\n", msgno);
POP3_CHECK_ERROR (pop3, status);
pop3->state = POP3_UIDL;
......@@ -98,19 +99,3 @@ pop3_uidl0 (pop3_t pop3, unsigned msgno, char **uidl)
return status;
}
int
pop3_uidl (pop3_t pop3, unsigned msgno, char **uidl)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_uidl0 (pop3, msgno, uidl);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -28,16 +28,17 @@
#include <stdlib.h>
#include <mailutils/sys/pop3.h>
static int
pop3_uidl_all0 (pop3_t pop3, iterator_t *piterator)
int
pop3_uidl_all (pop3_t pop3, iterator_t *piterator)
{
int status;
if (pop3 == NULL || piterator == NULL)
return MU_ERROR_INVALID_PARAMETER;
switch (pop3->state)
{
case POP3_NO_STATE:
if (piterator == NULL)
return MU_ERROR_INVALID_PARAMETER;
status = pop3_writeline (pop3, "UIDL\r\n");
POP3_CHECK_ERROR (pop3, status);
pop3->state = POP3_UIDL;
......@@ -72,17 +73,30 @@ pop3_uidl_all0 (pop3_t pop3, iterator_t *piterator)
}
int
pop3_uidl_all (pop3_t pop3, iterator_t *piterator)
pop3_uidl_current (iterator_t iterator, unsigned int *pno, char **puidl)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_uidl_all0 (pop3, piterator);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
char *buf;
int status = iterator_current (iterator, (void *)&buf);
if (status == 0)
{
char *space;
unsigned int msgno = 0;
/* The format is: msgno uidlstring */
space = strchr (buf, ' ');
if (space)
{
*space++ = '\0';
msgno = strtoul (buf, NULL, 10);
}
if (space && space[strlen (space) - 1] == '\n')
space[strlen (space) - 1] = '\0';
if (space == NULL)
space = (char *)"";
if (pno)
*pno = msgno;
if (puidl)
*puidl = strdup (space);
free (buf);
}
return status;
}
......
......@@ -27,16 +27,17 @@
#include <mailutils/sys/pop3.h>
static int
pop3_user0 (pop3_t pop3, const char *user)
int
pop3_user (pop3_t pop3, const char *user)
{
int status;
if (pop3 == NULL || user == NULL)
return MU_ERROR_INVALID_PARAMETER;
switch (pop3->state)
{
case POP3_NO_STATE:
if (user == NULL)
return MU_ERROR_INVALID_PARAMETER;
status = pop3_writeline (pop3, "USER %s\r\n", user);
POP3_CHECK_ERROR (pop3, status);
pop3->state = POP3_USER;
......@@ -65,19 +66,3 @@ pop3_user0 (pop3_t pop3, const char *user)
return status;
}
int
pop3_user (pop3_t pop3, const char *user)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_user0 (pop3, user);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -32,6 +32,7 @@ typedef struct {
/* The names of functions that actually do the manipulation. */
int com_apop (char *);
int com_capa (char *);
int com_disconnect (char *);
int com_dele (char *);
int com_exit (char *);
......@@ -61,6 +62,7 @@ void sig_int (int);
COMMAND commands[] = {
{ "apop", com_apop, "Authenticate with APOP: APOP user secret" },
{ "capa", com_capa, "List capabilities: capa" },
{ "disconnect", com_disconnect, "Close connection: disconnect" },
{ "dele", com_dele, "Mark message: DELE msgno" },
{ "exit", com_exit, "exit program" },
......@@ -333,6 +335,29 @@ com_apop (char *arg)
}
int
com_capa (char *arg)
{
iterator_t iterator;
int status = pop3_capa (pop3, &iterator);
(void)arg;
print_response ();
if (status == 0)
{
for (iterator_first (iterator);
!iterator_is_done (iterator);
iterator_next (iterator))
{
char *capa = (char *)"";
iterator_current (iterator, &capa);
printf ("Capa: %s\n", capa);
free (capa);
}
iterator_destroy (iterator);
}
return status;
}
int
com_uidl (char *arg)
{
if (arg == NULL || *arg == '\0')
......@@ -346,10 +371,11 @@ com_uidl (char *arg)
!iterator_is_done (uidl_iterator);
iterator_next (uidl_iterator))
{
struct pop3_uidl_item *pl;
iterator_current (uidl_iterator, (void *)&pl);
printf ("Msg: %d UIDL: %s\n", pl->msgno, pl->uidl);
free (pl);
unsigned int msgno = 0;
char *uidl = (char *)"";
pop3_uidl_current (uidl_iterator, &msgno, &uidl);
printf ("Msg: %d UIDL: %s\n", msgno, uidl);
free (uidl);
}
iterator_destroy (uidl_iterator);
}
......@@ -380,10 +406,10 @@ com_list (char *arg)
!iterator_is_done (list_iterator);
iterator_next (list_iterator))
{
struct pop3_list_item *pl;
iterator_current (list_iterator, (void *)&pl);
printf ("Msg: %d Size: %d\n", pl->msgno, pl->size);
free (pl);
unsigned int msgno = 0;
size_t size = 0;
pop3_list_current (list_iterator, &msgno, &size);
printf ("Msg: %d Size: %d\n", msgno, size);
}
iterator_destroy (list_iterator);
}
......
......@@ -24,7 +24,7 @@
#include <mailutils/sys/stream.h>
int
(stream_add_ref) (stream_t stream)
stream_add_ref (stream_t stream)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->add_ref == NULL)
......@@ -33,7 +33,7 @@ int
}
int
(stream_release) (stream_t stream)
stream_release (stream_t stream)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->release == NULL)
......@@ -42,7 +42,7 @@ int
}
int
(stream_destroy) (stream_t stream)
stream_destroy (stream_t stream)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->destroy == NULL)
......@@ -51,7 +51,7 @@ int
}
int
(stream_open) (stream_t stream, const char *host, int port, int flag)
stream_open (stream_t stream, const char *host, int port, int flag)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->open == NULL)
......@@ -60,7 +60,7 @@ int
}
int
(stream_close) (stream_t stream)
stream_close (stream_t stream)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->close == NULL)
......@@ -69,7 +69,7 @@ int
}
int
(stream_read) (stream_t stream, void *buf, size_t buflen, size_t *n)
stream_read (stream_t stream, void *buf, size_t buflen, size_t *n)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->read == NULL)
......@@ -78,7 +78,7 @@ int
}
int
(stream_readline) (stream_t stream, char *buf, size_t buflen, size_t *n)
stream_readline (stream_t stream, char *buf, size_t buflen, size_t *n)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->readline == NULL)
......@@ -87,7 +87,7 @@ int
}
int
(stream_write) (stream_t stream, const void *buf, size_t buflen, size_t *n)
stream_write (stream_t stream, const void *buf, size_t buflen, size_t *n)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->write == NULL)
......@@ -96,7 +96,7 @@ int
}
int
(stream_seek) (stream_t stream, off_t off, enum stream_whence whence)
stream_seek (stream_t stream, off_t off, enum stream_whence whence)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->seek == NULL)
......@@ -105,7 +105,7 @@ int
}
int
(stream_tell) (stream_t stream, off_t *off)
stream_tell (stream_t stream, off_t *off)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->tell == NULL)
......@@ -114,7 +114,7 @@ int
}
int
(stream_get_size) (stream_t stream, off_t *off)
stream_get_size (stream_t stream, off_t *off)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->get_size == NULL)
......@@ -123,7 +123,7 @@ int
}
int
(stream_truncate) (stream_t stream, off_t off)
stream_truncate (stream_t stream, off_t off)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->truncate == NULL)
......@@ -132,7 +132,7 @@ int
}
int
(stream_flush) (stream_t stream)
stream_flush (stream_t stream)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->flush == NULL)
......@@ -141,7 +141,7 @@ int
}
int
(stream_get_fd) (stream_t stream, int *fd)
stream_get_fd (stream_t stream, int *fd)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->get_fd == NULL)
......@@ -150,7 +150,7 @@ int
}
int
(stream_get_flags) (stream_t stream, int *flags)
stream_get_flags (stream_t stream, int *flags)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->get_flags == NULL)
......@@ -158,11 +158,48 @@ int
return stream->vtable->get_flags (stream, flags);
}
int
(stream_get_state) (stream_t stream, enum stream_state *state)
stream_get_state (stream_t stream, enum stream_state *state)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->get_state == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->get_state (stream, state);
}
int
stream_is_readready (stream_t stream, int timeout)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->is_readready == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->is_readready (stream, timeout);
}
int
stream_is_writeready (stream_t stream, int timeout)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->is_writeready == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->is_writeready (stream, timeout);
}
int
stream_is_exceptionpending (stream_t stream, int timeout)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->is_exceptionpending == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->is_exceptionpending (stream, timeout);
}
int
stream_is_open (stream_t stream)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->is_open == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->is_open (stream);
}
......
......@@ -31,6 +31,9 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <mailutils/sys/tcpstream.h>
#include <mailutils/error.h>
......@@ -354,6 +357,67 @@ _tcp_get_state (stream_t stream, enum stream_state *state)
return 0;
}
static int
_tcp_is_readready (stream_t stream, int timeout)
{
struct _tcp_instance *tcp = (struct _tcp_instance *)stream;
int ready;
struct timeval tv;
fd_set fds;
FD_ZERO (&fds);
FD_SET (tcp->fd, &fds);
tv.tv_sec = timeout / 100;
tv.tv_usec = (timeout % 1000) * 1000;
ready = select (tcp->fd + 1, &fds, NULL, NULL, (timeout == -1) ? NULL: &tv);
return (ready == -1) ? 0 : 1;
}
static int
_tcp_is_writeready (stream_t stream, int timeout)
{
struct _tcp_instance *tcp = (struct _tcp_instance *)stream;
int ready;
struct timeval tv;
fd_set fds;
FD_ZERO (&fds);
FD_SET (tcp->fd, &fds);
tv.tv_sec = timeout / 100;
tv.tv_usec = (timeout % 1000) * 1000;
ready = select (tcp->fd + 1, NULL, &fds, NULL, (timeout == -1) ? NULL: &tv);
return (ready == -1) ? 0 : 1;
}
static int
_tcp_is_exceptionpending (stream_t stream, int timeout)
{
struct _tcp_instance *tcp = (struct _tcp_instance *)stream;
int ready;
struct timeval tv;
fd_set fds;
FD_ZERO (&fds);
FD_SET (tcp->fd, &fds);
tv.tv_sec = timeout / 100;
tv.tv_usec = (timeout % 1000) * 1000;
ready = select (tcp->fd + 1, NULL, NULL, &fds, (timeout == -1) ? NULL: &tv);
return (ready == -1) ? 0 : 1;
}
static int
_tcp_is_open (stream_t stream)
{
struct _tcp_instance *tcp = (struct _tcp_instance *)stream;
return tcp->fd >= 0;
}
static struct _stream_vtable _tcp_vtable =
{
_tcp_add_ref,
......@@ -376,7 +440,13 @@ static struct _stream_vtable _tcp_vtable =
_tcp_get_fd,
_tcp_get_flags,
_tcp_get_state
_tcp_get_state,
_tcp_is_readready,
_tcp_is_writeready,
_tcp_is_exceptionpending,
_tcp_is_open
};
int
......