Commit 62624d8b 62624d8baa93b8306db0bc08b2dd2dbfaa4a5ff4 by Alain Magloire

First attempt at the new API.

1 parent 7c43bb82
/* 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. */
#ifndef _MAILUTILS_BASE_H
#define _MAILUTILS_BASE_H
#include <sys/types.h>
#ifdef __cplusplus
# define __MAILUTILS_START_DECLS extern "C" {
# define __MAILUTILS_END_DECLS }
#else
# define __MAILUTILS_BEGIN_DECLS
# define __MAILUTILS_END_DECLS
#endif
#ifndef __P
# ifdef __STDC__
# define __P(args) args
# else
# define __P(args) ()
# endif
#endif /*__P */
__MAILUTILS_BEGIN_DECLS
/* Forward declarations. */
struct _url;
typedef struct _url *url_t;
struct _mailer;
typedef struct _mailer *mailer_t;
struct _folder;
typedef struct _folder *folder_t;
struct _mailbox;
typedef struct _mailbox *mailbox_t;
struct _mime;
struct _mime *mime_t;
struct _message;
typedef struct _message *message_t;
struct _attribute;
typedef struct _attribute *attribute_t;
struct _envelope;
typedef struct _envelope *envelope_t;
struct _header;
typedef struct _header *header_t;
struct _body;
typedef struct _body *body_t;
struct _ticket;
typedef struct _ticket *ticket_t;
struct _authority;
typedef struct _authority *authority_t;
struct _observable;
typedef struct _observable *observable_t;
struct _locker;
typedef struct _locker *locker_t;
struct _address;
typedef struct _address *address_t;
struct _debug;
typedef struct _debug *debug_t;
struct _stream;
typedef struct _stream *stream_t;
struct _filter;
typedef struct _filter *filter_t;
struct _iterator;
typedef struct _iterator *iterator_t;
struct _property;
typedef struct _property *property_t;
struct _monitor;
typedef struct _monitor *monitory_t;
struct _list;
typedef struct _list *list_t;
__MAILUTILS_END_DECLS
#endif /*_MAILUTILS_BASE_H */
/* 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. */
#ifndef _MAILUTILS_ERROR_H
#define _MAILUTILS_ERROR_H
#include <errno.h>
#include <stdarg.h>
#ifndef __P
#ifdef __STDC__
#define __P(args) args
#else
#define __P(args) ()
#endif
#endif /*__P */
#ifdef __cplusplus
extern "C" {
#endif
/* When Possible use the platform error for our needs. */
#ifndef MU_ERROR_RANGE
# define MU_ERROR_RANGE 600
#endif
/* Error codes. */
#define MU_ERROR_OK 0
#if defined (EINVAL)
# define MU_ERROR_INVALID_PARAMETER EINVAL
#else
# define MU_ERROR_INVALID_PARAMETER (MU_ERROR_RANGE + 1)
#endif
#if defined (ENOMEM)
# define MU_ERROR_NO_MEMORY ENOMEM
#else
# define MU_ERROR_NO_MEMORY (MU_ERROR_RANGE + 2)
#endif
#if defined (EIO)
# define MU_ERROR_IO EIO
#else
# define MU_ERROR_IO (MU_ERROR_RANGE + 3)
#endif
#if defined (EINTR)
# define MU_ERROR_INTERRUPT EINTR
#else
# define MU_ERROR_INTERRUPT (MU_ERROR_RANGE + 4)
#endif
#if defined (ENOSYS)
# define MU_ERROR_NOT_SUPPORTED ENOSYS
#else
# define MU_ERROR_NOT_SUPPORTED (MU_ERROR_RANGE + 5)
#endif
#if defined (EACCESS)
# define MU_ERROR_OPERATION_DENIED EACCESS
#else
# define MU_ERROR_OPERATION_DENIED (MU_ERROR_RANGE + 6)
#endif
#if defined (ETIMEOUT)
# define MU_ERROR_TIMEOUT ETIMEOUT
#else
# define MU_ERROR_TIMEOUT (MU_ERROR_RANGE + 7)
#endif
#if defined (EAGAIN)
# define MU_ERROR_TRY_AGAIN EAGAIN
#else
# define MU_ERROR_TRY_AGAIN (MU_ERROR_RANGE + 8)
#endif
#if defined (ENOLCK)
# define MU_ERROR_NO_LOCK ENOLCK
#else
# define MU_ERROR_NO_LOCK (MU_ERROR_RANGE + 9)
#endif
#if defined (EINPROGRESS)
# define MU_ERROR_OPERATION_IN_PROGRESS EINPROGRESS
#else
# define MU_ERROR_OPERATION_IN_PROGRESS (MU_ERROR_RANGE + 10)
#endif
#if defined (EBUSY)
# define MU_ERROR_RESOURCE_BUSY EBUSY
#else
# define MU_ERROR_RESOURCE_BUSY (MU_ERROR_RANGE + 11)
#endif
#if defined (ESPIPE)
# define MU_ERROR_INVALID_SEEK ESPIPE
#else
# define MU_ERROR_INVALID_SEEK (MU_ERROR_RANGE + 12)
#endif
typedef int (*error_pfn_t) __P ((const char *fmt, va_list ap));
extern int mu_error __P ((const char *fmt, ...));
extern void mu_error_set_print __P ((error_pfn_t));
#ifdef __cplusplus
}
#endif
#endif /* _MAILUTILS_ERROR_H */
/* 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. */
#ifndef _MAILUTILS_ITERATOR_H
#define _MAILUTILS_ITERATOR_H
#include <mailutils/base.h>
__MAILUTILS_BEGIN_DECLS
extern int iterator_add_ref __P ((iterator_t));
extern int iterator_destroy __P ((iterator_t));
extern int iterator_release __P ((iterator_t));
extern int iterator_first __P ((iterator_t));
extern int iterator_next __P ((iterator_t));
extern int iterator_current __P ((iterator_t, void *));
extern int iterator_is_done __P ((iterator_t));
__MAILUTILS_END_DECLS
#endif /* _MAILUTILS_ITERATOR_H */
/* MD5.H - header file for MD5C.C
*/
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
/* GLOBAL.H - RSAREF types and constants
*/
/* PROTOTYPES should be set to one if and only if the compiler supports
function argument prototyping.
The following makes PROTOTYPES default to 0 if it has not already
been defined with C compiler flags.
*/
#ifndef PROTOTYPES
#define PROTOTYPES 0
#endif
/* POINTER defines a generic pointer type */
typedef unsigned char *POINTER;
/* UINT2 defines a two byte word */
typedef unsigned short int UINT2;
/* UINT4 defines a four byte word */
typedef unsigned long int UINT4;
/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
returns an empty list.
*/
#if __STDC__
#define PROTO_LIST(list) list
#else
#define PROTO_LIST(list) ()
#endif
/* MD5 context. */
typedef struct {
UINT4 state[4]; /* state (ABCD) */
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
} MD5_CTX;
void MD5Init PROTO_LIST ((MD5_CTX *));
void MD5Update PROTO_LIST ((MD5_CTX *, unsigned char *, unsigned int));
void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
/* 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. */
#ifndef _MAILUTILS_POP3_H
#define _MAILUTILS_POP3_H
#include <mailutils/iterator.h>
#include <mailutils/stream.h>
__MAILUTILS_BEGIN_DECLS
struct _pop3;
typedef struct _pop3* pop3_t;
enum pop3_state
{
POP3_NO_STATE,
POP3_OPEN, POP3_GREETINGS,
POP3_APOP, POP3_APOP_ACK,
POP3_AUTH, POP3_AUTH_ACK,
POP3_CAPA, POP3_CAPA_ACK, POP3_CAPA_RX,
POP3_DELE, POP3_DELE_ACK,
POP3_LIST, POP3_LIST_ACK, POP3_LIST_RX,
POP3_NOOP, POP3_NOOP_ACK,
POP3_PASS, POP3_PASS_ACK,
POP3_QUIT, POP3_QUIT_ACK,
POP3_RETR, POP3_RETR_ACK, POP3_RETR_RX,
POP3_RSET, POP3_RSET_ACK,
POP3_STAT, POP3_STAT_ACK,
POP3_TOP, POP3_TOP_ACK, POP3_TOP_RX,
POP3_UIDL, POP3_UIDL_ACK, POP3_UIDL_RX,
POP3_USER, POP3_USER_ACK,
POP3_DONE, POP3_UNKNOWN, POP3_ERROR
};
struct list_item
{
unsigned int msgno;
unsigned int size;
};
struct uidl_item
{
unsigned int msgno;
char *uidl;
};
extern int pop3_create __P ((pop3_t *));
extern void pop3_destroy __P ((pop3_t));
extern int pop3_open __P ((pop3_t, const char *, unsigned int, int));
extern int pop3_close __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_get_state __P ((pop3_t, enum pop3_state *));
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));
__MAILUTILS_END_DECLS
#endif /* _MAILUTILS_POP3_H */
/* 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. */
#ifndef _MAILUTILS_STREAM_H
# define _MAILUTILS_STREAM_H
#include <mailutils/base.h>
#include <sys/types.h>
__MAILUTILS_BEGIN_DECLS
#define MU_STREAM_READ 0x00000001
#define MU_STREAM_WRITE 0x00000002
#define MU_STREAM_RDWR (MU_STREAM_READ|MU_STREAM_WRITE)
#define MU_STREAM_APPEND 0x00000004
#define MU_STREAM_CREAT 0x00000008
#define MU_STREAM_NONBLOCK 0x00000010
enum stream_whence
{
MU_STREAM_WHENCE_SET,
MU_STREAM_WHENCE_CUR,
MU_STREAM_WHENCE_END
};
enum stream_state
{
MU_STREAM_NO_STATE,
MU_STREAM_STATE_OPEN,
MU_STREAM_STATE_READ,
MU_STREAM_STATE_WRITE,
MU_STREAM_STATE_CLOSE
};
extern int stream_add_ref __P ((stream_t));
extern int stream_release __P ((stream_t));
extern int stream_destroy __P ((stream_t));
extern int stream_open __P ((stream_t, const char *, int, int));
extern int stream_close __P ((stream_t));
extern int stream_read __P ((stream_t, char *, size_t, size_t *));
extern int stream_readline __P ((stream_t, char *, size_t, size_t *));
extern int stream_write __P ((stream_t, const char *, size_t, size_t*));
extern int stream_seek __P ((stream_t, off_t, enum stream_whence));
extern int stream_tell __P ((stream_t, off_t *));
extern int stream_get_size __P ((stream_t, off_t *));
extern int stream_truncate __P ((stream_t, off_t));
extern int stream_flush __P ((stream_t));
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 *));
/* Misc. */
extern int stream_file_create __P ((stream_t *));
extern int stream_mapfile_create __P ((stream_t *));
extern int stream_memory_create __P ((stream_t *));
extern int stream_tcp_create __P ((stream_t *));
__MAILUTILS_END_DECLS
#endif /* _MAILUTILS_STREAM_H */
/* 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. */
#ifndef _MAILUTILS_SYS_ITERATOR_H
#define _MAILUTILS_SYS_ITERATOR_H
#include <mailutils/iterator.h>
__MAILUTILS_BEGIN_DECLS
struct _iterator_vtable
{
/* Base */
int (*add_ref) __P ((iterator_t));
int (*release) __P ((iterator_t));
int (*destroy) __P ((iterator_t));
int (*first) __P ((iterator_t));
int (*next) __P ((iterator_t));
int (*current) __P ((iterator_t, void *));
int (*is_done) __P ((iterator_t));
};
struct _iterator
{
struct _iterator_vtable *vtable;
};
/* Use macros for the implentation. */
#define iterator_add_ref(i) ((i)->vtable->add_ref)(i)
#define iterator_release(i) ((i)->vtable->release)(i)
#define iterator_destroy(i) ((i)->vtable->destroy)(i)
#define iterator_firs(i) ((i)->vtable->first)(i)
#define iterator_next(i) ((i)->vtable->next)(i)
#define iterator_current(i, a) ((i)->vtable->current)(i, a)
#define iterator_is_done(i) ((i)->vtable->is_done)(i)
__MAILUTILS_END_DECLS
#endif /* _MAILUTILS_SYS_ITERATOR_H */
/* 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. */
#ifndef _MAILUTILS_SYS_POP3_H
#define _MAILUTILS_SYS_POP3_H
#include <sys/types.h>
#include <mailutils/pop3.h>
#include <mailutils/sys/stream.h>
#include <mailutils/sys/iterator.h>
#include <mailutils/error.h>
__MAILUTILS_BEGIN_DECLS
struct p_iterator
{
struct _iterator base;
pop3_t pop3;
unsigned int ref;
int done;
void *item;
};
struct p_stream
{
struct _stream base;
pop3_t pop3;
unsigned ref;
int done;
};
struct work_buf
{
char *buf;
char *ptr;
char *nl;
size_t len;
};
/* Structure to hold things general to POP3 mailbox, like its state, etc ... */
struct _pop3
{
/* Working I/O buffers. */
/* io.buf: Working io buffer. */
/* io.ptr: Points to the end of the buffer, the non consume chars. */
/* io.nl: Points to the '\n' char in the string. */
/* io.len: Len of io_buf. */
struct work_buf io;
/* Holds the first line response of the last command, i.e the ACK. */
/* ack.buf: Buffer for the ack. */
/* ack.ptr: Working pointer. */
/* ack.len: Size 512 according to RFC2449. */
struct work_buf ack;
int acknowledge;
char *timestamp; /* For apop, if supported. */
unsigned timeout; /* Default is 10 minutes. */
enum pop3_state state;
stream_t stream; /* TCP Connection. */
};
extern int pop3_iterator_create __P ((pop3_t, iterator_t *));
extern int pop3_stream_create __P ((pop3_t, stream_t *));
/* Check for non recoverable error. */
#define POP3_CHECK_EAGAIN(pop3, status) \
do \
{ \
if (status != 0) \
{ \
if (status != MU_ERROR_TRY_AGAIN && status != MU_ERROR_INTERRUPT) \
{ \
pop3->io.ptr = pop3->io.buf; \
pop3->state = POP3_ERROR; \
} \
return status; \
} \
} \
while (0)
/* If error return. */
#define POP3_CHECK_ERROR(pop3, status) \
do \
{ \
if (status != 0) \
{ \
pop3->io.ptr = pop3->io.buf; \
pop3->state = POP3_ERROR; \
return status; \
} \
} \
while (0)
/* Check if we got "+OK". */
#define POP3_CHECK_OK(pop3) \
do \
{ \
if (strncasecmp (pop3->ack.buf, "+OK", 3) != 0) \
{ \
pop3->state = POP3_NO_STATE; \
return MU_ERROR_OPERATION_DENIED; \
} \
} \
while (0)
__MAILUTILS_END_DECLS
#endif /* _MAILUTILS_SYS_POP3_H */
/* 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. */
#ifndef _MAILUTILS_SYS_STREAM_H
#define _MAILUTILS_SYS_STREAM_H
#include <mailutils/base.h>
#include <mailutils/stream.h>
__MAILUTILS_BEGIN_DECLS
struct _stream_vtable
{
int (*add_ref) __P ((stream_t));
int (*release) __P ((stream_t));
int (*destroy) __P ((stream_t));
int (*open) __P ((stream_t, const char *, int, int));
int (*close) __P ((stream_t));
int (*read) __P ((stream_t, char *, size_t, size_t *));
int (*readline) __P ((stream_t, char *, size_t, size_t *));
int (*write) __P ((stream_t, const char *, size_t, size_t *));
int (*seek) __P ((stream_t, off_t, enum stream_whence));
int (*tell) __P ((stream_t, off_t *));
int (*get_size) __P ((stream_t, off_t *));
int (*truncate) __P ((stream_t, off_t));
int (*flush) __P ((stream_t));
int (*get_fd) __P ((stream_t , int *));
int (*get_flags) __P ((stream_t, int *));
int (*get_state) __P ((stream_t, enum stream_state *));
};
struct _stream
{
struct _stream_vtable *vtable;
};
#define stream_destroy(s) ((s)->vtable->destroy)(s)
#define stream_release(s) ((s)->vtable->release)(s)
#define stream_open(s,h,p,f) ((s)->vtable->open)(s,h,p,f)
#define stream_close(s) ((s)->vtable->close)(s)
#define stream_read(s, b, l, n) ((s)->vtable->read)(s, b, l, n)
#define stream_readline(s, b, l, n) ((s)->vtable->readline)(s, b, l, n)
#define stream_write(s, b, l, n) ((s)->vtable->write)(s, b, l, n)
#define stream_seek(s, o, w) ((s)->vtable->seek)(s, o, w)
#define stream_tell(s, o) ((s)->vtable->tell)(s, o)
#define stream_get_size(s, o) ((s)->vtable->get_size)(s, o)
#define stream_flush(s) ((s)->vtable->flush)(s)
#define stream_truncate(s, o) ((s)->vtable->truncate)(s, o)
#define stream_get_fd(s, f) ((s)->vtable->get_fd)(s, f)
#define stream_get_flags(s, f) ((s)->vtable->get_flags)(s, f)
#define stream_get_state(s, f) ((s)->vtable->get_state)(s, f)
__MAILUTILS_END_DECLS
#endif /* _MAILUTILS_SYS_STREAM_H */
/* 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 Library General 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 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. */
#ifndef MAILUTILS_SYS_TCP_H
#define MAILUTILS_SYS_TCP_H
#include <mailutils/sys/stream.h>
enum _tcp_state
{
TCP_STATE_INIT,
TCP_STATE_RESOLVE,
TCP_STATE_RESOLVING,
TCP_STATE_CONNECTING,
TCP_STATE_CONNECTED
};
struct _tcp_instance
{
struct _stream base;
int ref;
int fd;
char *host;
int port;
int state;
int flags;
unsigned long address;
};
#endif /* _MAILUTILS_SYS_TCP_H */
/* 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 <stdlib.h>
#include <mailutils/sys/iterator.h>
#include <mailutils/error.h>
int
(iterator_release) (iterator_t iterator)
{
if (iterator == NULL || iterator->vtable == NULL
|| iterator->vtable->release == NULL)
return MU_ERROR_NOT_SUPPORTED;
return iterator->vtable->release (iterator);
}
int
(iterator_destroy) (iterator_t iterator)
{
if (iterator == NULL || iterator->vtable == NULL
|| iterator->vtable->destroy == NULL)
return MU_ERROR_NOT_SUPPORTED;
return iterator->vtable->destroy (iterator);
}
int
(iterator_first) (iterator_t iterator)
{
if (iterator == NULL || iterator->vtable == NULL
|| iterator->vtable->first == NULL)
return MU_ERROR_NOT_SUPPORTED;
return iterator->vtable->first (iterator);
}
int
(iterator_next) (iterator_t iterator)
{
if (iterator == NULL || iterator->vtable == NULL
|| iterator->vtable->next == NULL)
return MU_ERROR_NOT_SUPPORTED;
return iterator->vtable->next (iterator);
}
int
(iterator_current) (iterator_t iterator, void *pitem)
{
if (iterator == NULL || iterator->vtable == NULL
|| iterator->vtable->current == NULL)
return MU_ERROR_NOT_SUPPORTED;
return iterator->vtable->current (iterator, pitem);
}
int
(iterator_is_done) (iterator_t iterator)
{
if (iterator == NULL || iterator->vtable == NULL
|| iterator->vtable->is_done == NULL)
return MU_ERROR_NOT_SUPPORTED;
return iterator->vtable->is_done (iterator);
}
/* 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 <stdio.h>
#include <string.h>
#include <mailutils/sys/pop3.h>
#include <mailutils/md5-rsa.h>
int
pop3_apop (pop3_t pop3, const char *user, const char *secret)
{
int status = 0;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
/* The server did not offer a time stamp, bail early. */
if (pop3->timestamp == NULL)
return MU_ERROR_NOT_SUPPORTED;
switch (pop3->state)
{
case POP3_NO_STATE:
{
MD5_CTX md5context;
unsigned char md5digest[16];
char digest[64]; /* Really it just has to be 32 + 1(null). */
char *tmp;
size_t n;
if (user == NULL || secret == NULL)
return MU_ERROR_INVALID_PARAMETER;
/* Generate md5 digest. */
MD5Init (&md5context);
MD5Update (&md5context, (unsigned char *)pop3->timestamp,
strlen (pop3->timestamp));
MD5Update (&md5context, (unsigned char *)secret, strlen (secret));
MD5Final (md5digest, &md5context);
for (tmp = digest, n = 0; n < 16; n++, tmp += 2)
sprintf (tmp, "%02x", md5digest[n]);
*tmp = '\0';
status = pop3_writeline (pop3, "APOP %s %s\r\n", user, digest);
POP3_CHECK_ERROR (pop3, status);
pop3->state = POP3_APOP;
}
case POP3_APOP:
status = pop3_send (pop3);
POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = POP3_APOP_ACK;
case POP3_APOP_ACK:
status = pop3_response (pop3, NULL, 0, NULL);
POP3_CHECK_EAGAIN (pop3, status);
POP3_CHECK_OK (pop3);
pop3->state = POP3_NO_STATE;
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
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>
#include <stddef.h>
#include <mailutils/sys/pop3.h>
int
pop3_capa (pop3_t pop3, iterator_t *piterator)
{
int status = 0;
if (pop3 == NULL || piterator == NULL)
return MU_ERROR_INVALID_PARAMETER;
switch (pop3->state)
{
case POP3_NO_STATE:
status = pop3_writeline (pop3, "CAPA\r\n");
POP3_CHECK_ERROR (pop3, status);
pop3->state = POP3_CAPA;
case POP3_CAPA:
status = pop3_send (pop3);
POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = POP3_CAPA_ACK;
case POP3_CAPA_ACK:
status = pop3_response (pop3, NULL, 0, NULL);
POP3_CHECK_EAGAIN (pop3, status);
POP3_CHECK_OK (pop3);
pop3->state = POP3_CAPA_RX;
case POP3_CAPA_RX:
status = pop3_iterator_create (pop3, piterator);
POP3_CHECK_ERROR (pop3, status);
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
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 <mailutils/sys/pop3.h>
#include <stdlib.h>
#include <string.h>
/* Sudden death. */
int
pop3_close (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;
pop3->acknowledge = 0;
memset (pop3->io.buf, '\0', pop3->io.len);
memset (pop3->ack.buf, '\0', pop3->ack.len);
/* Free the timestamp, it will be different on each connection. */
if (pop3->timestamp)
{
free (pop3->timestamp);
pop3->timestamp = NULL;
}
return stream_close (pop3->stream);
}
/* 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 <stdlib.h>
#include <mailutils/error.h>
#include <mailutils/sys/pop3.h>
/* Initialise a pop3_t handle. */
int
pop3_create (pop3_t *ppop3)
{
pop3_t pop3;
if (ppop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
pop3 = calloc (1, sizeof *pop3);
if (pop3 == NULL)
return MU_ERROR_NO_MEMORY;
/* 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);
if (pop3->ack.buf == NULL)
{
pop3_destroy (pop3);
return MU_ERROR_NO_MEMORY;
}
/* 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);
if (pop3->io.buf == NULL)
{
pop3_destroy (pop3);
return MU_ERROR_NO_MEMORY;
}
pop3->state = POP3_NO_STATE; /* Init with no state. */
pop3->timeout = 10 * 60; /* The default Timeout is 10 minutes. */
pop3->acknowledge = 0; /* No Ack received. */
*ppop3 = pop3;
return 0; /* Okdoke. */
}
/* 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 <mailutils/sys/pop3.h>
int
pop3_dele (pop3_t pop3, unsigned msgno)
{
int status = 0;
if (pop3 == NULL || msgno == 0)
return MU_ERROR_INVALID_PARAMETER;
switch (pop3->state)
{
case POP3_NO_STATE:
status = pop3_writeline (pop3, "DELE %d\r\n", msgno);
POP3_CHECK_ERROR (pop3, status);
pop3->state = POP3_DELE;
case POP3_DELE:
status = pop3_send (pop3);
POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = POP3_DELE_ACK;
case POP3_DELE_ACK:
status = pop3_response (pop3, NULL, 0, NULL);
POP3_CHECK_EAGAIN (pop3, status);
POP3_CHECK_OK (pop3);
pop3->state = POP3_NO_STATE;
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
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 <mailutils/error.h>
#include <mailutils/sys/pop3.h>
#include <stdlib.h>
void
pop3_destroy (pop3_t pop3)
{
if (pop3)
{
if (pop3->ack.buf)
free (pop3->ack.buf);
if (pop3->io.buf)
free (pop3->io.buf);
if (pop3->timestamp)
free (pop3->timestamp);
free (pop3);
}
}
/* 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>
#include <strings.h>
#include <stdlib.h>
#include <stdio.h>
#include <mailutils/sys/pop3.h>
#include <mailutils/sys/iterator.h>
static int p_add_ref __P ((iterator_t));
static int p_release __P ((iterator_t));
static int p_destroy __P ((iterator_t));
static int p_first __P ((iterator_t));
static int p_next __P ((iterator_t));
static int p_current __P ((iterator_t, void *));
static int p_is_done __P ((iterator_t));
static struct _iterator_vtable p_i_vtable =
{
/* Base. */
p_add_ref,
p_release,
p_destroy,
p_first,
p_next,
p_current,
p_is_done
};
int
pop3_iterator_create (pop3_t pop3, iterator_t *piterator)
{
struct p_iterator *p_iterator;
p_iterator = malloc (sizeof *p_iterator);
if (p_iterator == NULL)
return MU_ERROR_NO_MEMORY;
p_iterator->base.vtable = &p_i_vtable;
p_iterator->ref = 1;
p_iterator->item = NULL;
p_iterator->done = 0;
p_iterator->pop3= pop3;
*piterator = &p_iterator->base;
return 0;
}
static int
p_add_ref (iterator_t iterator)
{
struct p_iterator *p_iterator = (struct p_iterator *)iterator;
return ++p_iterator->ref;
}
static int
p_release (iterator_t iterator)
{
struct p_iterator *p_iterator = (struct p_iterator *)iterator;
if (--p_iterator->ref == 0)
{
p_destroy (iterator);
return 0;
}
return p_iterator->ref;
}
static int
p_destroy (iterator_t iterator)
{
struct p_iterator *p_iterator = (struct p_iterator *)iterator;
if (!p_iterator->done)
{
char buf[128];
size_t n = 0;
while (pop3_readline (p_iterator->pop3, buf, sizeof buf, &n) > 0
&& n > 0)
n = 0;
}
if (p_iterator->item)
free (p_iterator->item);
p_iterator->pop3->state = POP3_NO_STATE;
free (iterator);
return 0;
}
static int
p_first (iterator_t iterator)
{
return p_next (iterator);
}
static int
p_next (iterator_t iterator)
{
struct p_iterator *p_iterator = (struct p_iterator *)iterator;
size_t n = 0;
int status;
if (p_iterator->done)
return 0;
status = pop3_readline (p_iterator->pop3, NULL, 0, &n);
if (status != 0)
return status;
if (n == 0)
{
p_iterator->done = 1;
p_iterator->pop3->state = POP3_NO_STATE;
return 0;
}
if (p_iterator->item)
free (p_iterator->item);
switch (p_iterator->pop3->state)
{
case POP3_CAPA_RX:
{
char *buf;
buf = calloc (n + 1, 1);
if (buf == NULL)
return MU_ERROR_NO_MEMORY;
/* Consume. */
pop3_readline (p_iterator->pop3, buf, n + 1, NULL);
if (n && buf[n - 1] == '\n')
buf[n - 1] = '\0';
p_iterator->item = buf;
}
break;
case POP3_UIDL_RX:
{
unsigned msgno;
char *space;
char *buf = calloc (n + 1, 1);
if (buf == NULL)
return MU_ERROR_NO_MEMORY;
p_iterator->item = calloc (1, sizeof (struct list_item));
if (p_iterator->item == NULL)
return MU_ERROR_NO_MEMORY;
/* Consume. */
pop3_readline (p_iterator->pop3, buf, n + 1, NULL);
msgno = 0;
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 *)"";
((struct uidl_item *)(p_iterator->item))->msgno = msgno;
((struct uidl_item *)(p_iterator->item))->uidl = strdup (space);
free (buf);
}
break;
case POP3_LIST_RX:
{
char *buf = calloc (n + 1, 1);
unsigned msgno;
size_t size;
if (buf == NULL)
return MU_ERROR_NO_MEMORY;
p_iterator->item = calloc (1, sizeof (struct list_item));
if (p_iterator->item == NULL)
return MU_ERROR_NO_MEMORY;
/* Consume. */
pop3_readline (p_iterator->pop3, buf, n + 1, NULL);
size = msgno = 0;
sscanf (buf, "%d %d", &msgno, &size);
((struct list_item *)(p_iterator->item))->msgno = msgno;
((struct list_item *)(p_iterator->item))->size = size;
free (buf);
}
break;
default:
}
return 0;
}
static int
p_is_done (iterator_t iterator)
{
struct p_iterator *p_iterator = (struct p_iterator *)iterator;
return p_iterator->done;
}
static int
p_current (iterator_t iterator, void *item)
{
struct p_iterator *p_iterator = (struct p_iterator *)iterator;
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 list_item **)item) = p_iterator->item;
break;
default:
}
}
p_iterator->item = NULL;
return 0;
}
/* 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 <stdio.h>
#include <mailutils/sys/pop3.h>
int
pop3_list (pop3_t pop3, unsigned msgno, size_t *psize)
{
int status = 0;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
switch (pop3->state)
{
case POP3_NO_STATE:
if (psize == NULL)
return MU_ERROR_INVALID_PARAMETER;
status = pop3_writeline (pop3, "LIST %d\r\n", msgno);
POP3_CHECK_ERROR (pop3, status);
pop3->state = POP3_LIST;
case POP3_LIST:
status = pop3_send (pop3);
POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = POP3_LIST_ACK;
case POP3_LIST_ACK:
status = pop3_response (pop3, NULL, 0, NULL);
POP3_CHECK_EAGAIN (pop3, status);
POP3_CHECK_OK (pop3);
pop3->state = POP3_NO_STATE;
/* Parse the answer. */
*psize = 0;
sscanf (pop3->ack.buf, "+OK %d %d", &msgno, psize);
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
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_list_all (pop3_t pop3, iterator_t *piterator)
{
int status = 0;
if (pop3 == 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;
case POP3_LIST:
status = pop3_send (pop3);
POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = POP3_LIST_ACK;
case POP3_LIST_ACK:
status = pop3_response (pop3, NULL, 0, NULL);
POP3_CHECK_EAGAIN (pop3, status);
POP3_CHECK_OK (pop3);
pop3->state = POP3_LIST_RX;
case POP3_LIST_RX:
status = pop3_iterator_create (pop3, piterator);
POP3_CHECK_ERROR (pop3, status);
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
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 <mailutils/sys/pop3.h>
int
pop3_noop (pop3_t pop3)
{
int status = 0;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
switch (pop3->state)
{
case POP3_NO_STATE:
status = pop3_writeline (pop3, "NOOP\r\n");
POP3_CHECK_ERROR (pop3, status);
pop3->state = POP3_NOOP;
case POP3_NOOP:
status = pop3_send (pop3);
POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = POP3_NOOP_ACK;
case POP3_NOOP_ACK:
status = pop3_response (pop3, NULL, 0, NULL);
POP3_CHECK_EAGAIN (pop3, status);
POP3_CHECK_OK (pop3);
pop3->state = POP3_NO_STATE;
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
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 <sys/time.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <mailutils/sys/pop3.h>
static int pop3_sleep (int seconds);
/* Open the connection to the server. */
int
pop3_open (pop3_t pop3, const char *host, unsigned int port, int flags)
{
int status = 0;
/* Sanity checks. */
if (pop3 == NULL || host == NULL)
return MU_ERROR_INVALID_PARAMETER;
/* Default is 110. */
if (!port)
port = 110;
/* Enter the pop state machine, and boogy: AUTHORISATION State. */
switch (pop3->state)
{
default:
/* __Fallthrough__, they want to clear an error. */
/* status = MU_ERROR_OPERATION_IN_PROGRESS; */
case POP3_NO_STATE:
/* Create the networking stack. */
if (pop3->stream == NULL)
{
status = stream_tcp_create (&(pop3->stream));
POP3_CHECK_ERROR (pop3, status);
/* Using the awkward stream_t buffering. */
/*stream_setbufsiz (pop3->stream, 1024); */
}
else
{
/* This is sudden death: for many pop servers, it is important to
let them time to remove locks or move the .user.pop files. This
happen when we do close() and immediately open(). For example,
the user does not want to read the entire file, and wants start
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. */
stream_close (pop3->stream);
pop3_sleep (2);
}
pop3->state = POP3_OPEN;
case POP3_OPEN:
/* Establish the connection. */
status = stream_open (pop3->stream, host, port, flags);
POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = POP3_GREETINGS;
case POP3_GREETINGS:
/* Get the greetings. */
{
size_t len = 0;
char *right, *left;
status = pop3_response (pop3, NULL, 0, &len);
POP3_CHECK_EAGAIN (pop3, status);
if (strncasecmp (pop3->ack.buf, "+OK", 3) != 0)
{
stream_close (pop3->stream);
pop3->state = POP3_NO_STATE;
return MU_ERROR_OPERATION_DENIED;
}
/* Get the timestamp. */
right = memchr (pop3->ack.buf, '<', len);
if (right)
{
len = len - (right - pop3->ack.buf);
left = memchr (right, '>', len);
if (left)
{
len = left - right;
pop3->timestamp = calloc (len + 1, 1);
if (pop3->timestamp == NULL)
{
stream_close (pop3->stream);
POP3_CHECK_ERROR (pop3, MU_ERROR_NO_MEMORY);
}
/* Do not copy the surrounding '<>'. */
memcpy (pop3->timestamp, right + 1, len - 1);
}
}
pop3->state = POP3_NO_STATE;
}
} /* End AUTHORISATION state. */
return status;
}
/* GRRRRR!! We can not use sleep in the library since this we'll
muck up any alarm() done by the user. */
static int
pop3_sleep (int seconds)
{
struct timeval tval;
tval.tv_sec = seconds;
tval.tv_usec = 0;
return select (1, NULL, NULL, NULL, &tval);
}
/* 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 <mailutils/sys/pop3.h>
int
pop3_pass (pop3_t pop3, const char *passwd)
{
int status = 0;
if (pop3 == 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;
case POP3_PASS:
status = pop3_send (pop3);
POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = POP3_PASS_ACK;
case POP3_PASS_ACK:
status = pop3_response (pop3, NULL, 0, NULL);
POP3_CHECK_EAGAIN (pop3, status);
POP3_CHECK_OK (pop3);
pop3->state = POP3_NO_STATE;
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
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 <mailutils/sys/pop3.h>
int
pop3_quit (pop3_t pop3)
{
int status = 0;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
switch (pop3->state)
{
case POP3_NO_STATE:
status = pop3_writeline (pop3, "QUIT\r\n");
POP3_CHECK_ERROR (pop3, status);
pop3->state = POP3_QUIT;
case POP3_QUIT:
status = pop3_send (pop3);
POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = POP3_QUIT_ACK;
case POP3_QUIT_ACK:
status = pop3_response (pop3, NULL, 0, NULL);
POP3_CHECK_EAGAIN (pop3, status);
POP3_CHECK_OK (pop3);
pop3->state = POP3_NO_STATE;
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
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 <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <mailutils/sys/pop3.h>
#include <mailutils/error.h>
/* 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. */
static int
pop3_getline (pop3_t pop3)
{
size_t n = 0;
size_t total = pop3->io.ptr - pop3->io.buf;
int status = 0;
/* Must get a full line before bailing out. */
do
{
/* Timeout with select(), note that we have to reset select()
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;
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;
}
}
status = stream_readline (pop3->stream, pop3->io.buf + total,
pop3->io.len - total, &n);
if (status != 0)
return status;
/* The server went away: It maybe a timeout and some pop server
does not send the -ERR. Consider this like an error. */
if (n == 0)
return MU_ERROR_IO;
total += n;
pop3->io.nl = memchr (pop3->io.buf, '\n', total);
if (pop3->io.nl == NULL) /* Do we have a full line. */
{
/* Allocate a bigger buffer ? */
if (total >= pop3->io.len -1)
{
pop3->io.len *= 2;
pop3->io.buf = realloc (pop3->io.buf, pop3->io.len + 1);
if (pop3->io.buf == NULL)
return MU_ERROR_NO_MEMORY;
}
}
pop3->io.ptr = pop3->io.buf + total;
}
while (pop3->io.nl == NULL); /* Bail only if we have a complete line. */
/* When examining a multi-line response, the client checks to see if the
line begins with the termination octet "."(DOT). If yes and if octets
other than CRLF follow, the first octet of the line (the termination
octet) is stripped away. */
if (total >= 3 && pop3->io.buf[0] == '.')
{
if (pop3->io.buf[1] != '\r' && pop3->io.buf[2] != '\n')
{
memmove (pop3->io.buf, pop3->io.buf + 1, total - 1);
pop3->io.ptr--;
pop3->io.nl--;
}
/* And if CRLF immediately follows the termination character, then
the response from the POP server is ended and the line containing
".CRLF" is not considered part of the multi-line response. */
else if (pop3->io.buf[1] == '\r' && pop3->io.buf[2] == '\n')
{
pop3->io.buf[0] = '\0';
pop3->io.ptr = pop3->io.buf;
pop3->io.nl = NULL;
}
}
/* \r\n --> \n\0, conversion. */
if (pop3->io.nl > pop3->io.buf)
{
*(pop3->io.nl - 1) = '\n';
*(pop3->io.nl) = '\0';
pop3->io.ptr = pop3->io.nl;
}
return status;
} /* if need to fill up. */
int
pop3_readline (pop3_t pop3, char *buffer, size_t buflen, size_t *pnread)
{
size_t nread = 0;
size_t n = 0;
int status;
/* Do we need to fill up? Yes if no NL or the buffer is empty. */
if (pop3->io.nl == NULL || pop3->io.ptr == pop3->io.buf)
{
status = pop3_getline (pop3);
if (status != 0)
return status;
}
/* How much we can copy ? */
n = pop3->io.ptr - pop3->io.buf;
/* Consume the line? */
if (buffer && buflen)
{
buflen--; /* For the null. */
if (buflen)
{
int nleft = buflen - n;
/* We got more then requested. */
if (nleft < 0)
{
size_t sentinel;
nread = buflen;
sentinel = pop3->io.ptr - (pop3->io.buf + nread);
memcpy (buffer, pop3->io.buf, nread);
memmove (pop3->io.buf, pop3->io.buf + nread, sentinel);
pop3->io.ptr = pop3->io.buf + sentinel;
}
else
{
/* Drain our buffer. */;
nread = n;
memcpy (buffer, pop3->io.buf, nread);
pop3->io.ptr = pop3->io.buf;
/* Clear of all residue. */
memset (pop3->io.buf, '\0', pop3->io.len);
}
}
buffer[nread] = '\0';
}
else
nread = n;
if (pnread)
*pnread = nread;
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>
#include <mailutils/sys/pop3.h>
/* If we did not grap the ack already, call pop3_readline() but handle
Nonblocking also. */
int
pop3_response (pop3_t pop3, char *buffer, size_t buflen, size_t *pnread)
{
size_t n = 0;
int status = 0;
if (!pop3->acknowledge)
{
size_t len = pop3->ack.len - (pop3->ack.ptr - pop3->ack.buf);
status = pop3_readline (pop3, pop3->ack.ptr, len, &n);
pop3->ack.ptr += n;
if (status != 0)
return status;
pop3->acknowledge = 1; /* Flag that we have the ack. */
pop3->ack.ptr = pop3->ack.buf;
}
else
n = strlen (pop3->ack.buf);
if (buffer)
{
buflen--; /* Leave space for the NULL. */
n = (buflen < n) ? buflen : n;
memcpy (buffer, pop3->ack.buf, n);
buffer[n] = '\0';
}
if (pnread)
*pnread = n;
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>
#include <stdlib.h>
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <mailutils/sys/pop3.h>
int
pop3_retr (pop3_t pop3, unsigned msgno, stream_t *pstream)
{
int status = 0;
if (pop3 == NULL || pstream == NULL)
return MU_ERROR_INVALID_PARAMETER;
switch (pop3->state)
{
case POP3_NO_STATE:
status = pop3_writeline (pop3, "RETR %d\r\n", msgno);
POP3_CHECK_ERROR (pop3, status);
pop3->state = POP3_RETR;
case POP3_RETR:
status = pop3_send (pop3);
POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = POP3_RETR_ACK;
case POP3_RETR_ACK:
status = pop3_response (pop3, NULL, 0, NULL);
POP3_CHECK_EAGAIN (pop3, status);
POP3_CHECK_OK (pop3);
pop3->state = POP3_RETR_RX;
case POP3_RETR_RX:
status = pop3_stream_create (pop3, pstream);
POP3_CHECK_ERROR (pop3, status);
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
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 <mailutils/sys/pop3.h>
int
pop3_rset (pop3_t pop3)
{
int status = 0;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
switch (pop3->state)
{
case POP3_NO_STATE:
status = pop3_writeline (pop3, "RSET\r\n");
POP3_CHECK_ERROR (pop3, status);
pop3->state = POP3_RSET;
case POP3_RSET:
status = pop3_send (pop3);
POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = POP3_RSET_ACK;
case POP3_RSET_ACK:
status = pop3_response (pop3, NULL, 0, NULL);
POP3_CHECK_EAGAIN (pop3, status);
POP3_CHECK_OK (pop3);
pop3->state = POP3_NO_STATE;
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
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
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <mailutils/sys/pop3.h>
#include <mailutils/error.h>
/* A socket may write less then expected but stream.c:stream_write() will
always try to send the entire buffer unless an error is reported. We have
to cope with nonblocking, it is done by keeping track with the pop3->ptr
pointer if the write failed we keep track and restart where we left. */
int
pop3_send (pop3_t pop3)
{
int status = 0;
if (pop3->io.ptr > pop3->io.buf)
{
size_t n = 0;
size_t len = pop3->io.ptr - pop3->io.buf;
/* Timeout with select(), note that we have to reset select()
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;
}
}
status = stream_write (pop3->stream, pop3->io.buf, len, &n);
if (n)
{
/* Consume what we sent. */
memmove (pop3->io.buf, pop3->io.buf + n, len - n);
pop3->io.ptr -= n;
}
}
else
pop3->io.ptr = pop3->io.buf;
return status;
}
/* According to RFC 2449: The maximum length of a command is increased from
47 characters (4 character command, single space, 40 character argument,
CRLF) to 255 octets, including the terminating CRLF. But we are flexible
on this and realloc() as needed. NOTE: The terminated CRLF is not
included. */
int
pop3_writeline (pop3_t pop3, const char *format, ...)
{
int len;
va_list ap;
int done = 1;
va_start(ap, format);
/* C99 says that a conforming implementation of snprintf () should
return the number of char that would have been call but many old
GNU/Linux && BSD implementations return -1 on error. Worse,
QnX/Neutrino actually does not put the terminal null char. So
let's try to cope. */
do
{
len = vsnprintf (pop3->io.buf, pop3->io.len - 1, format, ap);
if (len < 0 || len >= (int)pop3->io.len
|| !memchr (pop3->io.buf, '\0', len + 1))
{
pop3->io.len *= 2;
pop3->io.buf = realloc (pop3->io.buf, pop3->io.len);
if (pop3->io.buf == NULL)
return ENOMEM;
done = 0;
}
else
done = 1;
}
while (!done);
va_end(ap);
pop3->io.ptr = pop3->io.buf + len;
return 0;
}
int
pop3_sendline (pop3_t pop3, const char *line)
{
if (line)
{
int status = pop3_writeline (pop3, line);
if (status)
return status;
}
return pop3_send (pop3);
}
/* 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 <stdio.h>
#include <string.h>
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <mailutils/sys/pop3.h>
int
pop3_stat (pop3_t pop3, unsigned *msg_count, size_t *size)
{
int status = 0;
if (pop3 == 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;
case POP3_STAT:
status = pop3_send (pop3);
POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = POP3_STAT_ACK;
case POP3_STAT_ACK:
status = pop3_response (pop3, NULL, 0, NULL);
POP3_CHECK_EAGAIN (pop3, status);
POP3_CHECK_OK (pop3);
pop3->state = POP3_NO_STATE;
/* Parse the answer. */
*msg_count = 0;
*size = 0;
sscanf (pop3->ack.buf, "+OK %d %d", msg_count, size);
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
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_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)
{
int status = stream_tcp_create (&(pop3->stream));
if (status)
return status;
/* Using the awkward stream_t buffering. */
/* stream_setbufsiz (pop3->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));
static int p_destroy __P ((stream_t));
static int p_open __P ((stream_t, const char *, int, int));
static int p_close __P ((stream_t));
static int p_read __P ((stream_t, char *, size_t, size_t *));
static int p_readline __P ((stream_t, char *, size_t, size_t *));
static int p_write __P ((stream_t, const char *, size_t, size_t *));
static int p_seek __P ((stream_t, off_t, enum stream_whence));
static int p_tell __P ((stream_t, off_t *));
static int p_get_size __P ((stream_t, off_t *));
static int p_truncate __P ((stream_t, off_t));
static int p_flush __P ((stream_t));
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 struct _stream_vtable p_s_vtable =
{
p_add_ref,
p_release,
p_destroy,
p_open,
p_close,
p_read,
p_readline,
p_write,
p_seek,
p_tell,
p_get_size,
p_truncate,
p_flush,
p_get_fd,
p_get_flags,
p_get_state,
};
int
pop3_stream_create (pop3_t pop3, stream_t *pstream)
{
struct p_stream *p_stream;
p_stream = malloc (sizeof *p_stream);
if (p_stream == NULL)
return MU_ERROR_NO_MEMORY;
p_stream->base.vtable = &p_s_vtable;
p_stream->ref = 1;
p_stream->done = 0;
p_stream->pop3 = pop3;
*pstream = &p_stream->base;
return 0;
}
static int
p_add_ref (stream_t stream)
{
struct p_stream *p_stream = (struct p_stream *)stream;
return ++p_stream->ref;
}
static int
p_release (stream_t stream)
{
struct p_stream *p_stream = (struct p_stream *)stream;
if (--p_stream->ref == 0)
{
p_destroy (stream);
return 0;
}
return p_stream->ref;
}
static int
p_destroy (stream_t stream)
{
struct p_stream *p_stream = (struct p_stream *)stream;
if (!p_stream->done)
{
char buf[128];
size_t n = 0;
while (pop3_readline (p_stream->pop3, buf, sizeof buf, &n) > 0
&& n > 0)
n = 0;
}
p_stream->pop3->state = POP3_NO_STATE;
free (stream);
return 0;
}
static int
p_open (stream_t stream, const char *h, int p, int f)
{
struct p_stream *p_stream = (struct p_stream *)stream;
return pop3_open (p_stream->pop3, h, p, f);
}
static int
p_close (stream_t stream)
{
struct p_stream *p_stream = (struct p_stream *)stream;
return pop3_close (p_stream->pop3);
}
static int
p_read (stream_t stream, char *buf, size_t buflen, size_t *pn)
{
struct p_stream *p_stream = (struct p_stream *)stream;
size_t n = 0;
int status = 0;
if (!p_stream->done)
{
do
{
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 here or change the behavoiour of
XXX_readline. */
if (buflen == 1)
{
char buffer[2];
*buffer = '\0';
status = pop3_readline (p_stream->pop3, buffer, 2, &nread);
*buf = *buffer;
}
else
status = pop3_readline (p_stream->pop3, buf, buflen, &nread);
if (status != 0)
break;
if (nread == 0)
{
p_stream->pop3->state = POP3_NO_STATE;
p_stream->done = 1;
break;
}
n += nread;
buflen -= nread;
buf += nread;
}
while (buflen > 0);
}
if (pn)
*pn = n;
return status;
}
static int
p_readline (stream_t stream, char *buf, size_t buflen, size_t *pn)
{
struct p_stream *p_stream = (struct p_stream *)stream;
size_t n = 0;
int status = 0;
if (!p_stream->done)
{
status = pop3_readline (p_stream->pop3, buf, buflen, &n);
if (n == 0)
{
p_stream->pop3->state = POP3_NO_STATE;
p_stream->done = 1;
}
}
if (pn)
*pn = n;
return status;
}
static int
p_write (stream_t stream, const char *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);
}
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);
}
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);
}
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);
}
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);
}
static int
p_flush (stream_t stream)
{
struct p_stream *p_stream = (struct p_stream *)stream;
return stream_flush (p_stream->pop3->stream);
}
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);
}
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);
}
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);
}
/* 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 <mailutils/sys/pop3.h>
#include <stdlib.h>
int
pop3_set_timeout (pop3_t pop3, unsigned int timeout)
{
/* Sanity checks. */
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
pop3->timeout = timeout;
return 0;
}
int
pop3_get_timeout (pop3_t pop3, unsigned int *ptimeout)
{
/* Sanity checks. */
if (pop3 == NULL || ptimeout == NULL)
return MU_ERROR_INVALID_PARAMETER;
*ptimeout = pop3->timeout;
return 0;
}
/* 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 <mailutils/sys/pop3.h>
int
pop3_top (pop3_t pop3, unsigned msgno, size_t lines, stream_t *pstream)
{
int status = 0;
if (pop3 == 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;
case POP3_TOP:
status = pop3_send (pop3);
POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = POP3_TOP_ACK;
case POP3_TOP_ACK:
status = pop3_response (pop3, NULL, 0, NULL);
POP3_CHECK_EAGAIN (pop3, status);
POP3_CHECK_OK (pop3);
pop3->state = POP3_TOP_RX;
case POP3_TOP_RX:
status = pop3_stream_create (pop3, pstream);
POP3_CHECK_ERROR (pop3, status);
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
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_uidl (pop3_t pop3, unsigned msgno, char **uidl)
{
int status = 0;
if (pop3 == 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;
case POP3_UIDL:
status = pop3_send (pop3);
POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = POP3_UIDL_ACK;
case POP3_UIDL_ACK:
status = pop3_response (pop3, NULL, 0, NULL);
POP3_CHECK_EAGAIN (pop3, status);
POP3_CHECK_OK (pop3);
pop3->state = POP3_NO_STATE;
*uidl = NULL;
{
char *space;
/* Pass the "+OK". */
space = strchr (pop3->ack.buf, ' ');
if (space)
{
/* Pass the number. */
space = strchr (space, ' ');
if (space)
{
size_t len = strlen (space);
if (space[len - 1] == '\n')
{
space[len - 1] = '\0';
len--;
}
*uidl = calloc (len + 1, 1);
if (*uidl)
memcpy (*uidl, space, len);
}
}
}
if (*uidl == NULL) /* What can we do? */
{
*uidl = malloc (1);
if (*uidl)
**uidl = '\0';
else
status = MU_ERROR_NO_MEMORY;
}
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
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_uidl_all (pop3_t pop3, iterator_t *piterator)
{
int status = 0;
if (pop3 == 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;
case POP3_UIDL:
status = pop3_send (pop3);
POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = POP3_UIDL_ACK;
case POP3_UIDL_ACK:
status = pop3_response (pop3, NULL, 0, NULL);
POP3_CHECK_EAGAIN (pop3, status);
POP3_CHECK_OK (pop3);
pop3->state = POP3_UIDL_RX;
case POP3_UIDL_RX:
status = pop3_iterator_create (pop3, piterator);
POP3_CHECK_ERROR (pop3, status);
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
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 <mailutils/sys/pop3.h>
int
pop3_user (pop3_t pop3, const char *user)
{
int status = 0;
if (pop3 == 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;
case POP3_USER:
status = pop3_send (pop3);
POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = POP3_USER_ACK;
case POP3_USER_ACK:
status = pop3_response (pop3, NULL, 0, NULL);
POP3_CHECK_EAGAIN (pop3, status);
POP3_CHECK_OK (pop3);
pop3->state = POP3_NO_STATE;
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
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 <stdlib.h>
#include <mailutils/error.h>
#include <mailutils/sys/stream.h>
int
(stream_add_ref) (stream_t stream)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->add_ref == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->add_ref (stream);
}
int
(stream_release) (stream_t stream)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->release == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->release (stream);
}
int
(stream_destroy) (stream_t stream)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->destroy == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->destroy (stream);
}
int
(stream_open) (stream_t stream, const char *host, int port, int flag)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->open == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->open (stream, host, port, flag);
}
int
(stream_close) (stream_t stream)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->close == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->close (stream);
}
int
(stream_read) (stream_t stream, char *buf, size_t buflen, size_t *n)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->read == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->read (stream, buf, buflen, n);
}
int
(stream_readline) (stream_t stream, char *buf, size_t buflen, size_t *n)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->readline == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->readline (stream, buf, buflen, n);
}
int
(stream_write) (stream_t stream, const char *buf, size_t buflen, size_t *n)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->write == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->write (stream, buf, buflen, n);
}
int
(stream_seek) (stream_t stream, off_t off, enum stream_whence whence)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->seek == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->seek (stream, off, whence);
}
int
(stream_tell) (stream_t stream, off_t *off)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->tell == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->tell (stream, off);
}
int
(stream_get_size) (stream_t stream, off_t *off)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->get_size == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->get_size (stream, off);
}
int
(stream_truncate) (stream_t stream, off_t off)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->truncate == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->truncate (stream, off);
}
int
(stream_flush) (stream_t stream)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->flush == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->flush (stream);
}
int
(stream_get_fd) (stream_t stream, int *fd)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->get_fd == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->get_fd (stream, fd);
}
int
(stream_get_flags) (stream_t stream, int *flags)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->get_flags == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->get_flags (stream, flags);
}
int
(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);
}
/* 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 Library General 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 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 <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <netdb.h>
#include <fcntl.h>
#define __USE_BSD
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <mailutils/sys/tcp.h>
#include <mailutils/error.h>
/* On solaris inet_addr() return -1. */
#ifndef INADDR_NONE
# define INADDR_NONE (unsigned long)-1
#endif
static int
_tcp_add_ref (stream_t stream)
{
struct _tcp_instance *tcp = (struct _tcp_instance *)stream;
return ++tcp->ref;
}
static int
_tcp_destroy (stream_t stream)
{
struct _tcp_instance *tcp = (struct _tcp_instance *)stream;
if (tcp->host)
free (tcp->host);
if (tcp->fd != -1)
close (tcp->fd);
free (tcp);
return 0;
}
static int
_tcp_release (stream_t stream)
{
struct _tcp_instance *tcp = (struct _tcp_instance *)stream;
if (--tcp->ref == 0)
{
_tcp_destroy (stream);
return 0;
}
return tcp->ref;
}
static int
_tcp_close (stream_t stream)
{
struct _tcp_instance *tcp = (struct _tcp_instance *)stream;
if (tcp->fd != -1)
close (tcp->fd);
tcp->fd = -1;
tcp->state = TCP_STATE_INIT;
return 0;
}
static int
_tcp_open (stream_t stream, const char *host, int port, int flags)
{
struct _tcp_instance *tcp = (struct _tcp_instance *)stream;
int flgs, ret;
size_t namelen;
struct sockaddr_in peer_addr;
struct hostent *phe;
struct sockaddr_in soc_addr;
if (tcp->state == TCP_STATE_INIT)
{
tcp->port = port;
tcp->host = strdup (host);
if (tcp->host == NULL)
return MU_ERROR_NO_MEMORY;
tcp->flags = flags;
}
switch (tcp->state)
{
case TCP_STATE_INIT:
if (tcp->fd == -1)
{
tcp->fd = socket (AF_INET, SOCK_STREAM, 0);
if (tcp->fd == -1)
return errno;
}
if (tcp->flags & MU_STREAM_NONBLOCK)
{
flgs = fcntl (tcp->fd, F_GETFL);
flgs |= O_NONBLOCK;
fcntl (tcp->fd, F_SETFL, flgs);
}
tcp->state = TCP_STATE_RESOLVING;
case TCP_STATE_RESOLVING:
if (tcp->host == NULL || tcp->port == -1)
return MU_ERROR_INVALID_PARAMETER;
tcp->address = inet_addr (tcp->host);
if (tcp->address == INADDR_NONE)
{
phe = gethostbyname (tcp->host);
if (!phe)
{
_tcp_close (stream);
return MU_ERROR_INVALID_PARAMETER;
}
tcp->address = *(((unsigned long **)phe->h_addr_list)[0]);
}
tcp->state = TCP_STATE_RESOLVE;
case TCP_STATE_RESOLVE:
memset (&soc_addr, 0, sizeof (soc_addr));
soc_addr.sin_family = AF_INET;
soc_addr.sin_port = htons (tcp->port);
soc_addr.sin_addr.s_addr = tcp->address;
if ((connect (tcp->fd, (struct sockaddr *)&soc_addr, sizeof (soc_addr))) == -1)
{
ret = errno;
if (ret == EINPROGRESS || ret == EAGAIN)
{
tcp->state = TCP_STATE_CONNECTING;
ret = MU_ERROR_TRY_AGAIN;
}
else
_tcp_close (stream);
return ret;
}
tcp->state = TCP_STATE_CONNECTING;
case TCP_STATE_CONNECTING:
namelen = sizeof (peer_addr);
if (getpeername (tcp->fd, (struct sockaddr *)&peer_addr, &namelen) == 0)
tcp->state = TCP_STATE_CONNECTED;
else
{
ret = errno;
_tcp_close (stream);
return ret;
}
break;
}
return 0;
}
static int
_tcp_get_fd (stream_t stream, int *fd)
{
struct _tcp_instance *tcp = (struct _tcp_instance *)stream;
if (fd == NULL || tcp->fd == EINVAL)
return MU_ERROR_INVALID_PARAMETER;
*fd = tcp->fd;
return 0;
}
static int
_tcp_read (stream_t stream, char *buf, size_t buf_size, size_t *br)
{
struct _tcp_instance *tcp = (struct _tcp_instance *)stream;
int bytes;
if (br == NULL)
return MU_ERROR_INVALID_PARAMETER;
*br = 0;
bytes = recv (tcp->fd, buf, buf_size, 0);
if (bytes == -1)
{
*br = 0;
return errno;
}
*br = bytes;
return 0;
}
static int
_tcp_readline (stream_t stream, char *buf, size_t buf_size, size_t *br)
{
struct _tcp_instance *tcp = (struct _tcp_instance *)stream;
int status = 0;
size_t n;
int nr = 0;
char c;
/* Grossly inefficient hopefully they override this */
for (n = 1; n < buf_size; n++)
{
nr = recv (tcp->fd, &c, 1, 0);
if (nr == -1) /* Error. */
{
status = errno;
break;
}
else if (nr == 1)
{
*buf++ = c;
if (c == '\n') /* Newline is stored like fgets(). */
break;
}
else if (nr == 0)
{
if (n == 1) /* EOF, no data read. */
n = 0;
break; /* EOF, some data was read. */
}
}
*buf = '\0';
if (br)
*br = (n == buf_size) ? n - 1: n;
return status;
}
static int
_tcp_write (stream_t stream, const char *buf, size_t buf_size, size_t *bw)
{
struct _tcp_instance *tcp = (struct _tcp_instance *)stream;
int bytes;
if (bw == NULL)
return MU_ERROR_INVALID_PARAMETER;
*bw = 0;
bytes = send (tcp->fd, buf, buf_size, 0);
if (bytes == -1)
{
*bw = 0;
return errno;
}
*bw = bytes;
return 0;
}
static int
_tcp_seek (stream_t stream, off_t off, enum stream_whence whence)
{
(void)stream; (void)off; (void)whence;
return MU_ERROR_NOT_SUPPORTED;
}
static int
_tcp_tell (stream_t stream, off_t *off)
{
(void)stream; (void)off;
return MU_ERROR_NOT_SUPPORTED;
}
static int
_tcp_get_size (stream_t stream, off_t *off)
{
(void)stream; (void)off;
return MU_ERROR_NOT_SUPPORTED;
}
static int
_tcp_truncate (stream_t stream, off_t off)
{
(void)stream; (void)off;
return MU_ERROR_NOT_SUPPORTED;
}
static int
_tcp_flush (stream_t stream)
{
(void)stream;
return MU_ERROR_NOT_SUPPORTED;
}
static int
_tcp_get_flags (stream_t stream, int *flags)
{
struct _tcp_instance *tcp = (struct _tcp_instance *)stream;
*flags = tcp->flags;
return 0;
}
static int
_tcp_get_state (stream_t stream, enum stream_state *state)
{
struct _tcp_instance *tcp = (struct _tcp_instance *)stream;
*state = tcp->state;
return 0;
}
static struct _stream_vtable _tcp_vtable =
{
_tcp_add_ref,
_tcp_release,
_tcp_destroy,
_tcp_open,
_tcp_close,
_tcp_read,
_tcp_readline,
_tcp_write,
_tcp_seek,
_tcp_tell,
_tcp_get_size,
_tcp_truncate,
_tcp_flush,
_tcp_get_fd,
_tcp_get_flags,
_tcp_get_state,
};
int
stream_tcp_create (stream_t *pstream)
{
struct _tcp_instance *tcp;
tcp = calloc (1, sizeof *tcp);
if (tcp == NULL)
return MU_ERROR_NO_MEMORY;
tcp->base.vtable = &_tcp_vtable;
tcp->ref = 1;
tcp->fd = -1;
tcp->host = NULL;
tcp->port = -1;
tcp->state = TCP_STATE_INIT;
*pstream = &tcp->base;
return 0;
}