Commit 4ec2ac41 4ec2ac41eaa6dc77165820d3335aeb859da644d6 by Alain Magloire

* mailbox2/pop3/*: Pop3 functions are thread-safe and cancel-safe.

	The problem is monitor.h, we will probably end up doing a monitor.h.in
	and set at compile time if threading is enable or not.
1 parent 1fadf5f9
2001-07-01 Alain Magloire
* mailbox2/pop3/*: Pop3 functions are thread-safe and cancel-safe.
The problem is monitor.h, we will probably end up doing a monitor.h.in
and set a compile time if threading was enable or not.
2001-07-01 Alain Magloire
* mail/util.c (util_expand_msglist): Cleanup the expand by pattern
by moving some code in util_strupper(), the comparison must be
case insensitive.
......
/* 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_MONITOR_H
#define _MAILUTILS_MONITOR_H
#include <unistd.h>
#ifdef _POSIX_THREADS
# include <pthread.h>
#endif
#ifdef _POSIX_THREADS
# define monitor_t pthread_mutex_t
# define MU_MONITOR_INITIALIZER PTHREAD_MUTEX_INITIALIZER
# define monitor_create(m) pthread_mutex_init (m, NULL)
# define monitor_destroy(m) pthread_mutex_destroy (&m)
# define monitor_cleanup_push(routine, arg) pthread_cleanup_push (routine, arg)
# define monitor_cleanup_pop(execute) pthread_cleanup_pop (execute)
# define monitor_lock(m) pthread_mutex_lock (&m)
# define monitor_unlock(m) pthread_mutex_unlock (&m)
#else
# define monitor_t int
# define MU_MONITOR_INITIALIZER 0
# define monitor_create(m) (*m = 0)
# define monitor_destroy(m) (m = 0)
# define monitor_cleanup_push(routine, arg) {
# define monitor_cleanup_pop(execute) }
# define monitor_rdlock(m) (m = 1)
# define monitor_unlock(m) (m = 0)
#endif
#endif /* _MAILUTILS_MONITOR_H */
......@@ -22,20 +22,17 @@
#include <stdio.h>
#include <string.h>
#include <mailutils/sys/pop3.h>
#include <mailutils/md5-rsa.h>
#include <mailutils/sys/pop3.h>
/*
APOP name digest
a string identifying a mailbox and a MD5 digest string (both required)
*/
int
pop3_apop (pop3_t pop3, const char *user, const char *secret)
static int
pop3_apop0 (pop3_t pop3, const char *user, const char *secret)
{
int status = 0;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
int status;
/* The server did not offer a time stamp in the greeting, bailout early. */
if (pop3->timestamp == NULL)
......@@ -93,3 +90,19 @@ pop3_apop (pop3_t pop3, const char *user, const char *secret)
return status;
}
int
pop3_apop (pop3_t pop3, const char *user, const char *secret)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_apop0 (pop3, user, secret);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -24,13 +24,10 @@
#include <stddef.h>
#include <mailutils/sys/pop3.h>
int
pop3_capa (pop3_t pop3, iterator_t *piterator)
static int
pop3_capa0 (pop3_t pop3, iterator_t *piterator)
{
int status = 0;
if (pop3 == NULL || piterator == NULL)
return MU_ERROR_INVALID_PARAMETER;
int status;
switch (pop3->state)
{
......@@ -67,3 +64,19 @@ pop3_capa (pop3_t pop3, iterator_t *piterator)
return status;
}
int
pop3_capa (pop3_t pop3, iterator_t *piterator)
{
int status;
if (pop3 == NULL || piterator == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_capa0 (pop3, piterator);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
/* GNU mailutils - a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Library Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <string.h>
#include <mailutils/sys/pop3.h>
#include <mailutils/md5-rsa.h>
#include <mailutils/monitor.h>
void
pop3_cleanup (void *arg)
{
pop3_t pop3 = (pop3_t)arg;
monitor_unlock (pop3->lock);
pop3->state = POP3_ERROR;
}
......@@ -22,22 +22,21 @@
#include <sys/time.h>
#include <unistd.h>
#include <stdlib.h>
#ifdef HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif
#include <mailutils/sys/pop3.h>
static int pop3_sleep (int seconds);
/* Open the connection to the server. The server sends an affirmative greeting
that may contain a timestamp for APOP. */
int
pop3_connect (pop3_t pop3, const char *host, unsigned int port)
static int
pop3_connect0 (pop3_t pop3, const char *host, unsigned int port)
{
int status = 0;
/* Sanity checks. */
if (pop3 == NULL || host == NULL)
return MU_ERROR_INVALID_PARAMETER;
int status;
/* Default is 110. */
if (!port)
......@@ -131,3 +130,21 @@ pop3_sleep (int seconds)
tval.tv_usec = 0;
return select (1, NULL, NULL, NULL, &tval);
}
int
pop3_connect (pop3_t pop3, const char *host, unsigned int port)
{
int status;
/* Sanity checks. */
if (pop3 == NULL || host == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_connect0 (pop3, host, port);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -60,6 +60,8 @@ pop3_create (pop3_t *ppop3)
pop3->timeout = 10 * 60; /* The default Timeout is 10 minutes. */
pop3->acknowledge = 0; /* No Ack received. */
monitor_create (&(pop3->lock));
*ppop3 = pop3;
return 0; /* Okdoke. */
}
......
......@@ -26,13 +26,10 @@
#include <mailutils/sys/pop3.h>
int
pop3_dele (pop3_t pop3, unsigned msgno)
static int
pop3_dele0 (pop3_t pop3, unsigned msgno)
{
int status = 0;
if (pop3 == NULL || msgno == 0)
return MU_ERROR_INVALID_PARAMETER;
int status;
switch (pop3->state)
{
......@@ -64,3 +61,19 @@ pop3_dele (pop3_t pop3, unsigned msgno)
}
return status;
}
int
pop3_dele (pop3_t pop3, unsigned msgno)
{
int status;
if (pop3 == NULL || msgno == 0)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_dele0 (pop3, msgno);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -37,6 +37,8 @@ pop3_destroy (pop3_t pop3)
if (pop3->timestamp)
free (pop3->timestamp);
monitor_destroy (pop3->lock);
free (pop3);
}
}
......
......@@ -24,13 +24,9 @@
#include <string.h>
/* Sudden death. */
int
pop3_disconnect (pop3_t pop3)
static int
pop3_disconnect0 (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;
......@@ -48,3 +44,20 @@ pop3_disconnect (pop3_t pop3)
return stream_close (pop3->stream);
return 0;
}
int
pop3_disconnect (pop3_t pop3)
{
int status;
/* Sanity checks. */
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_disconnect0 (pop3);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -25,7 +25,6 @@
#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));
......@@ -62,6 +61,7 @@ pop3_iterator_create (pop3_t pop3, iterator_t *piterator)
p_iterator->item = NULL;
p_iterator->done = 0;
p_iterator->pop3= pop3;
monitor_create (&p_iterator->lock);
*piterator = &p_iterator->base;
return 0;
}
......@@ -69,38 +69,57 @@ pop3_iterator_create (pop3_t pop3, iterator_t *piterator)
static int
p_add_ref (iterator_t iterator)
{
int status = 0;
struct p_iterator *p_iterator = (struct p_iterator *)iterator;
return ++p_iterator->ref;
if (p_iterator)
{
monitor_lock (p_iterator->lock);
status = ++p_iterator->ref;
monitor_unlock (p_iterator->lock);
}
return status;
}
static int
p_release (iterator_t iterator)
{
int status = 0;
struct p_iterator *p_iterator = (struct p_iterator *)iterator;
if (--p_iterator->ref == 0)
if (p_iterator)
{
p_destroy (iterator);
return 0;
monitor_lock (p_iterator->lock);
status = --p_iterator->ref;
if (status <= 0)
{
monitor_unlock (p_iterator->lock);
p_destroy (iterator);
return 0;
}
monitor_unlock (p_iterator->lock);
}
return p_iterator->ref;
return status;
}
static int
p_destroy (iterator_t iterator)
{
struct p_iterator *p_iterator = (struct p_iterator *)iterator;
if (!p_iterator->done)
if (p_iterator)
{
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->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;
monitor_destroy (p_iterator->lock);
free (p_iterator);
}
if (p_iterator->item)
free (p_iterator->item);
p_iterator->pop3->state = POP3_NO_STATE;
free (iterator);
return 0;
}
......@@ -116,131 +135,174 @@ 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;
int status = 0;
if (n == 0)
if (p_iterator)
{
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 pop3_uidl_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 pop3_uidl_item *)(p_iterator->item))->msgno = msgno;
((struct pop3_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 pop3_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 pop3_list_item *)(p_iterator->item))->msgno = msgno;
((struct pop3_list_item *)(p_iterator->item))->size = size;
free (buf);
}
break;
default:
monitor_lock (p_iterator->lock);
if (!p_iterator->done)
{
/* The first readline will not consume the buffer, we just need to
know how much to read. */
status = pop3_readline (p_iterator->pop3, NULL, 0, &n);
if (status == 0)
{
if (n)
{
switch (p_iterator->pop3->state)
{
case POP3_CAPA_RX:
{
char *buf;
buf = calloc (n + 1, 1);
if (buf)
{
/* Consume. */
pop3_readline (p_iterator->pop3, buf, n + 1, NULL);
if (buf[n - 1] == '\n')
buf[n - 1] = '\0';
if (p_iterator->item)
free (p_iterator->item);
p_iterator->item = buf;
}
else
status = MU_ERROR_NO_MEMORY;
break;
}
case POP3_UIDL_RX:
{
struct pop3_uidl_item *pitem;
char *buf = calloc (n + 1, 1);
if (buf)
{
if (p_iterator->item)
{
pitem = p_iterator->item;
if (pitem->uidl)
free (pitem->uidl);
free (pitem);
}
p_iterator->item = calloc (1, sizeof *pitem);
pitem = p_iterator->item;
if (pitem)
{
unsigned msgno;
char *space;
/* Consume. */
pop3_readline (p_iterator->pop3, buf,
n + 1, NULL);
msgno = 0;
/* The format is:
msgno uidlsttring */
space = strchr (buf, ' ');
if (space)
{
*space++ = '\0';
msgno = strtoul (buf, NULL, 10);
}
if (space && space[strlen (space) - 1] == '\n')
space[strlen (space) - 1] = '\0';
if (space == NULL)
space = (char *)"";
pitem->msgno = msgno;
pitem->uidl = strdup (space);
}
else
status = MU_ERROR_NO_MEMORY;
free (buf);
}
else
status = MU_ERROR_NO_MEMORY;
break;
}
case POP3_LIST_RX:
{
struct pop3_list_item *pitem;
char *buf = calloc (n + 1, 1);
if (buf)
{
if (p_iterator->item)
free (p_iterator->item);
pitem = calloc (1, sizeof *pitem);
p_iterator->item = pitem;
if (pitem)
{
unsigned msgno;
size_t size;
/* Consume. */
pop3_readline (p_iterator->pop3, buf,
n + 1, NULL);
size = msgno = 0;
sscanf (buf, "%d %d", &msgno, &size);
pitem->msgno = msgno;
pitem->size = size;
}
else
status = MU_ERROR_NO_MEMORY;
free (buf);
}
else
status = MU_ERROR_NO_MEMORY;
break;
}
default:
}
}
else
{
p_iterator->done = 1;
p_iterator->pop3->state = POP3_NO_STATE;
}
}
}
monitor_unlock (p_iterator->lock);
}
return 0;
return status;
}
static int
p_is_done (iterator_t iterator)
{
struct p_iterator *p_iterator = (struct p_iterator *)iterator;
return p_iterator->done;
int status = 1;
if (p_iterator)
{
monitor_lock (p_iterator->lock);
status = p_iterator->done;
monitor_unlock (p_iterator->lock);
}
return status;
}
static int
p_current (iterator_t iterator, void *item)
{
struct p_iterator *p_iterator = (struct p_iterator *)iterator;
if (item)
if (p_iterator)
{
switch (p_iterator->pop3->state)
monitor_lock (p_iterator->lock);
if (item)
{
case POP3_CAPA_RX:
case POP3_UIDL_RX:
*((char **)item) = p_iterator->item;
break;
case POP3_LIST_RX:
*((struct pop3_list_item **)item) = p_iterator->item;
break;
default:
switch (p_iterator->pop3->state)
{
case POP3_CAPA_RX:
case POP3_UIDL_RX:
*((char **)item) = p_iterator->item;
break;
case POP3_LIST_RX:
*((struct pop3_list_item **)item) = p_iterator->item;
break;
default:
}
}
p_iterator->item = NULL;
monitor_unlock (p_iterator->lock);
}
p_iterator->item = NULL;
return 0;
}
......
......@@ -19,22 +19,19 @@
# include <config.h>
#endif
#include <string.h>
#ifdef HAVE_STRINGS_H
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
#include <stdio.h>
#include <mailutils/sys/pop3.h>
int
pop3_list (pop3_t pop3, unsigned msgno, size_t *psize)
static int
pop3_list0 (pop3_t pop3, unsigned msgno, size_t *psize)
{
int status = 0;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
int status;
switch (pop3->state)
{
......@@ -73,3 +70,18 @@ pop3_list (pop3_t pop3, unsigned msgno, size_t *psize)
return status;
}
int
pop3_list (pop3_t pop3, unsigned msgno, size_t *psize)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_list0 (pop3, msgno, psize);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -19,21 +19,19 @@
# include <config.h>
#endif
#include <string.h>
#ifdef HAVE_STRINGS_H
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
#include <stdlib.h>
#include <mailutils/sys/pop3.h>
int
pop3_list_all (pop3_t pop3, iterator_t *piterator)
static int
pop3_list_all0 (pop3_t pop3, iterator_t *piterator)
{
int status = 0;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
int status;
switch (pop3->state)
{
......@@ -72,3 +70,19 @@ pop3_list_all (pop3_t pop3, iterator_t *piterator)
return status;
}
int
pop3_list_all (pop3_t pop3, iterator_t *piterator)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_list_all0 (pop3, piterator);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -19,20 +19,18 @@
# include <config.h>
#endif
#include <string.h>
#ifdef HAVE_STRINGS_H
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
#include <mailutils/sys/pop3.h>
int
pop3_noop (pop3_t pop3)
static int
pop3_noop0 (pop3_t pop3)
{
int status = 0;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
int status;
switch (pop3->state)
{
......@@ -65,3 +63,20 @@ pop3_noop (pop3_t pop3)
return status;
}
int
pop3_noop (pop3_t pop3)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_noop0 (pop3);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -19,20 +19,18 @@
# include <config.h>
#endif
#include <string.h>
#ifdef HAVE_STRINGS_H
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
#include <mailutils/sys/pop3.h>
int
pop3_pass (pop3_t pop3, const char *passwd)
static int
pop3_pass0 (pop3_t pop3, const char *passwd)
{
int status = 0;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
int status;
switch (pop3->state)
{
......@@ -67,3 +65,19 @@ pop3_pass (pop3_t pop3, const char *passwd)
return status;
}
int
pop3_pass (pop3_t pop3, const char *passwd)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_pass0 (pop3, passwd);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -19,20 +19,18 @@
# include <config.h>
#endif
#include <string.h>
#ifdef HAVE_STRINGS_H
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
#include <mailutils/sys/pop3.h>
int
pop3_quit (pop3_t pop3)
static int
pop3_quit0 (pop3_t pop3)
{
int status = 0;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
int status;
switch (pop3->state)
{
......@@ -60,3 +58,19 @@ pop3_quit (pop3_t pop3)
return status;
}
int
pop3_quit (pop3_t pop3)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_quit0 (pop3);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -38,13 +38,20 @@ pop3_response (pop3_t pop3, char *buffer, size_t buflen, size_t *pnread)
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;
len = pop3->ack.ptr - pop3->ack.buf;
if (len && pop3->ack.buf[len - 1] == '\n')
pop3->ack.buf[len - 1] = '\0';
pop3->acknowledge = 1; /* Flag that we have the ack. */
pop3->ack.ptr = pop3->ack.buf;
if (status == 0)
{
len = pop3->ack.ptr - pop3->ack.buf;
if (len && pop3->ack.buf[len - 1] == '\n')
pop3->ack.buf[len - 1] = '\0';
pop3->acknowledge = 1; /* Flag that we have the ack. */
pop3->ack.ptr = pop3->ack.buf;
}
else
{
const char *econ = "-ERR POP3 Failed";
n = strlen (econ);
strcpy (pop3->ack.buf, econ);
}
}
else
n = strlen (pop3->ack.buf);
......
......@@ -27,13 +27,10 @@
#include <mailutils/sys/pop3.h>
int
pop3_retr (pop3_t pop3, unsigned msgno, stream_t *pstream)
static int
pop3_retr0 (pop3_t pop3, unsigned msgno, stream_t *pstream)
{
int status = 0;
if (pop3 == NULL || pstream == NULL)
return MU_ERROR_INVALID_PARAMETER;
int status;
switch (pop3->state)
{
......@@ -70,3 +67,19 @@ pop3_retr (pop3_t pop3, unsigned msgno, stream_t *pstream)
return status;
}
int
pop3_retr (pop3_t pop3, unsigned msgno, stream_t *pstream)
{
int status;
if (pop3 == NULL || pstream == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_retr0 (pop3, msgno, pstream);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -19,20 +19,18 @@
# include <config.h>
#endif
#include <string.h>
#ifdef HAVE_STRINGS_H
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
#include <mailutils/sys/pop3.h>
int
pop3_rset (pop3_t pop3)
static int
pop3_rset0 (pop3_t pop3)
{
int status = 0;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
int status;
switch (pop3->state)
{
......@@ -65,3 +63,19 @@ pop3_rset (pop3_t pop3)
return status;
}
int
pop3_rset (pop3_t pop3)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_rset0 (pop3);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -20,20 +20,18 @@
#endif
#include <stdio.h>
#include <string.h>
#ifdef HAVE_STRINGS_H
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
#include <mailutils/sys/pop3.h>
int
pop3_stat (pop3_t pop3, unsigned *msg_count, size_t *size)
static int
pop3_stat0 (pop3_t pop3, unsigned *msg_count, size_t *size)
{
int status = 0;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
int status;
switch (pop3->state)
{
......@@ -73,3 +71,19 @@ pop3_stat (pop3_t pop3, unsigned *msg_count, size_t *size)
return status;
}
int
pop3_stat (pop3_t pop3, unsigned *msg_count, size_t *size)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_stat0 (pop3, msg_count, size);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -119,6 +119,7 @@ pop3_stream_create (pop3_t pop3, stream_t *pstream)
p_stream->ref = 1;
p_stream->done = 0;
p_stream->pop3 = pop3;
monitor_create (&p_stream->lock);
*pstream = &p_stream->base;
return 0;
}
......@@ -127,35 +128,50 @@ static int
p_add_ref (stream_t stream)
{
struct p_stream *p_stream = (struct p_stream *)stream;
return ++p_stream->ref;
int status = 0;
if (p_stream)
{
monitor_lock (p_stream->lock);
status = ++p_stream->ref;
monitor_unlock (p_stream->lock);
}
return status;
}
static int
p_release (stream_t stream)
{
struct p_stream *p_stream = (struct p_stream *)stream;
if (--p_stream->ref == 0)
int status = 0;
if (p_stream)
{
p_destroy (stream);
return 0;
monitor_lock (p_stream->lock);
status = --p_stream->ref;
if (status <= 0)
p_destroy (stream);
monitor_unlock (p_stream->lock);
}
return p_stream->ref;
return status;
}
static int
p_destroy (stream_t stream)
{
struct p_stream *p_stream = (struct p_stream *)stream;
if (!p_stream->done)
if (p_stream)
{
char buf[128];
size_t n = 0;
while (pop3_readline (p_stream->pop3, buf, sizeof buf, &n) > 0
&& n > 0)
n = 0;
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;
monitor_destroy (p_stream->lock);
free (p_stream);
}
p_stream->pop3->state = POP3_NO_STATE;
free (stream);
return 0;
}
......@@ -180,40 +196,45 @@ 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)
if (p_stream)
{
do
monitor_lock (p_stream->lock);
if (!p_stream->done)
{
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)
do
{
char buffer[2];
*buffer = '\0';
status = pop3_readline (p_stream->pop3, buffer, 2, &nread);
*buf = *buffer;
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;
}
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);
}
while (buflen > 0);
monitor_unlock (p_stream->lock);
}
if (pn)
*pn = n;
......@@ -226,14 +247,19 @@ 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)
if (p_stream)
{
status = pop3_readline (p_stream->pop3, buf, buflen, &n);
if (n == 0)
monitor_lock (p_stream->lock);
if (!p_stream->done)
{
p_stream->pop3->state = POP3_NO_STATE;
p_stream->done = 1;
status = pop3_readline (p_stream->pop3, buf, buflen, &n);
if (n == 0)
{
p_stream->pop3->state = POP3_NO_STATE;
p_stream->done = 1;
}
}
monitor_unlock (p_stream->lock);
}
if (pn)
*pn = n;
......
......@@ -19,20 +19,18 @@
# include <config.h>
#endif
#include <string.h>
#ifdef HAVE_STRINGS_H
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
#include <mailutils/sys/pop3.h>
int
pop3_top (pop3_t pop3, unsigned msgno, size_t lines, stream_t *pstream)
static int
pop3_top0 (pop3_t pop3, unsigned msgno, size_t lines, stream_t *pstream)
{
int status = 0;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
int status;
switch (pop3->state)
{
......@@ -71,3 +69,19 @@ pop3_top (pop3_t pop3, unsigned msgno, size_t lines, stream_t *pstream)
return status;
}
int
pop3_top (pop3_t pop3, unsigned msgno, size_t lines, stream_t *pstream)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_top0 (pop3, msgno, lines, pstream);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -19,21 +19,19 @@
# include <config.h>
#endif
#include <string.h>
#ifdef HAVE_STRINGS_H
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
#include <stdlib.h>
#include <mailutils/sys/pop3.h>
int
pop3_uidl (pop3_t pop3, unsigned msgno, char **uidl)
static int
pop3_uidl0 (pop3_t pop3, unsigned msgno, char **uidl)
{
int status = 0;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
int status;
switch (pop3->state)
{
......@@ -100,3 +98,19 @@ pop3_uidl (pop3_t pop3, unsigned msgno, char **uidl)
return status;
}
int
pop3_uidl (pop3_t pop3, unsigned msgno, char **uidl)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_uidl0 (pop3, msgno, uidl);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -19,21 +19,19 @@
# include <config.h>
#endif
#include <string.h>
#ifdef HAVE_STRINGS_H
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
#include <stdlib.h>
#include <mailutils/sys/pop3.h>
int
pop3_uidl_all (pop3_t pop3, iterator_t *piterator)
static int
pop3_uidl_all0 (pop3_t pop3, iterator_t *piterator)
{
int status = 0;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
int status;
switch (pop3->state)
{
......@@ -72,3 +70,19 @@ pop3_uidl_all (pop3_t pop3, iterator_t *piterator)
return status;
}
int
pop3_uidl_all (pop3_t pop3, iterator_t *piterator)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_uidl_all0 (pop3, piterator);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -19,20 +19,18 @@
# include <config.h>
#endif
#include <string.h>
#ifdef HAVE_STRINGS_H
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
#include <mailutils/sys/pop3.h>
int
pop3_user (pop3_t pop3, const char *user)
static int
pop3_user0 (pop3_t pop3, const char *user)
{
int status = 0;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
int status;
switch (pop3->state)
{
......@@ -67,3 +65,19 @@ pop3_user (pop3_t pop3, const char *user)
return status;
}
int
pop3_user (pop3_t pop3, const char *user)
{
int status;
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
monitor_lock (pop3->lock);
monitor_cleanup_push (pop3_cleanup, pop3);
status = pop3_user0 (pop3, user);
monitor_unlock (pop3->lock);
monitor_cleanup_pop (0);
return status;
}
......
......@@ -14,6 +14,7 @@
#include <strings.h>
#include <stdlib.h>
#include <termios.h>
#include <signal.h>
#include <readline/readline.h>
#include <readline/history.h>
......@@ -56,6 +57,8 @@ char *dupstr (const char *);
int execute_line (char *);
int valid_argument (const char *, char *);
void sig_int (int);
COMMAND commands[] = {
{ "apop", com_apop, "Authenticate with APOP: APOP user secret" },
{ "disconnect", com_disconnect, "Close connection: disconnect" },
......@@ -121,6 +124,7 @@ main (int argc, char **argv)
/* Loop reading and executing lines until the user quits. */
for ( ; done == 0; )
{
line = readline ("pop3> ");
if (!line)
......@@ -354,9 +358,10 @@ com_uidl (char *arg)
{
char *uidl = NULL;
unsigned int msgno = strtoul (arg, NULL, 10);
pop3_uidl (pop3, msgno, &uidl);
print_response ();
printf ("Msg: %d UIDL: %s\n", msgno, (uidl) ? uidl : "");
if (pop3_uidl (pop3, msgno, &uidl) == 0)
printf ("Msg: %d UIDL: %s\n", msgno, (uidl) ? uidl : "");
else
print_response ();
}
return 0;
}
......@@ -387,9 +392,10 @@ com_list (char *arg)
{
size_t size = 0;
unsigned int msgno = strtoul (arg, NULL, 10);
pop3_list (pop3, msgno, &size);
print_response ();
printf ("Msg: %d Size: %d\n", msgno, size);
if (pop3_list (pop3, msgno, &size) == 0)
printf ("Msg: %d Size: %d\n", msgno, size);
else
print_response ();
}
return 0;
}
......@@ -619,10 +625,19 @@ com_quit (char *arg)
(void)arg;
if (pop3)
{
pop3_quit (pop3);
pop3_disconnect (pop3);
print_response ();
if (pop3_quit (pop3) == 0)
{
print_response ();
pop3_disconnect (pop3);
}
else
{
print_response ();
fprintf (stdout, "Try 'exit' to leave %s\n", progname);
}
}
else
fprintf (stdout, "Try 'exit' to leave %s\n", progname);
return 0;
}
......