Commit d22b2199 d22b2199ab813bf994afc2dbe8e033ffcc01d045 by Sergey Poznyakoff

Minor change in stream API. Improve POP3 client interface.

* include/mailutils/sys/stream.h (_MU_STR_EVENT_SET)
(_MU_STR_EVENT_CLR): New defines.
(_mu_stream) <event_cb, event_mask>: New members.
* mailbox/stream.c (_stream_setflag, _stream_clrflag): New static
functions.
All functions use these instead of setting/clearing flags directly.
(_mu_stream_cleareof, _mu_stream_seteof): New extern functions.
(_stream_cleareof): Remove define, use _mu_stream_cleareof instead.
(_stream_fill_buffer): Set EOF marker when end of stream is reached.

* mailbox/fltstream.c (filter_read): Call _mu_stream_seteof to set
EOF flag.

* include/mailutils/pop3.h: Get rid of the superfluous "extern" in
front of function prototypes.
Add new prototypes.
Remove extra whitespace.

* libproto/pop/pop3_capatst.c: New file.
* libproto/pop/pop3_list_cmd.c: New file.
* libproto/pop/pop3_listas.c: New file.
* libproto/pop/pop3_rdlist.c: New file.
* libproto/pop/pop3_uidl_cmd.c: New file.
* libproto/pop/pop3_uidlas.c: New file.
* libproto/pop/Makefile.am: Add new files.
* libproto/pop/pop3_capa.c (_mu_pop3_fill_list): Remove.
Use mu_pop3_read_list instead.
(capa_comp): New comparator for capa lists.
* libproto/pop/pop3_list.c (mu_pop3_list): Fix format specifier.
* libproto/pop/pop3_lista.c (mu_pop3_list_all): Rewrite.
* libproto/pop/pop3_retr.c (mu_pop3_retr) <MU_POP3_RETR_RX>: do not
reset state, this is done by the EOF event callback.
* libproto/pop/pop3_top.c (mu_pop3_top) <MU_POP3_TOP_RX>: Likewise.
* libproto/pop/pop3_stream.c (pop3_decode_state): New state pds_char.
Change semantics of pds_init.
(newstate, _pop3_decoder): Handle .\r\n in the initial state.
(_pop3_event_cb): New event callback.
(mu_pop3_filter_create): Set event callback on the filter stream.
* libproto/pop/pop3_uidla.c (mu_pop3_uidl_all): Rewrite.

* examples/Makefile.am (pop3client_CPPFLAGS): Add MU_APP_COMMON_INCLUDES.
* examples/pop3client.c: Rewrite command parser.
1 parent b94a6d3c
......@@ -111,6 +111,7 @@ sfrom_LDADD =\
@MU_AUTHLIBS@\
${MU_LIB_MAILUTILS}
pop3client_CPPFLAGS = @MU_APP_COMMON_INCLUDES@
pop3client_LDADD = \
../lib/libmuaux.la\
${MU_LIB_POP}\
......
......@@ -34,6 +34,7 @@
#include <stdlib.h>
#include <termios.h>
#include <signal.h>
#include <xalloc.h>
#ifdef WITH_READLINE
# include <readline/readline.h>
......@@ -56,64 +57,81 @@
typedef struct
{
const char *name; /* User printable name of the function. */
int (*func) (char *); /* Function to call to do the job. */
int argmin;
int argmax;
int (*func) (int, char **); /* Function to call to do the job. */
const char *doc; /* Documentation for this function. */
}
COMMAND;
/* The names of functions that actually do the manipulation. */
int com_apop (char *);
int com_capa (char *);
int com_disconnect (char *);
int com_dele (char *);
int com_exit (char *);
int com_help (char *);
int com_list (char *);
int com_noop (char *);
int com_connect (char *);
int com_pass (char *);
int com_quit (char *);
int com_retr (char *);
int com_rset (char *);
int com_stat (char *);
int com_top (char *);
int com_uidl (char *);
int com_user (char *);
int com_verbose (char *);
int com_prompt (char *);
int com_stls (char *);
void initialize_readline (void);
COMMAND *find_command (char *);
char *dupstr (const char *);
int execute_line (char *);
int valid_argument (const char *, char *);
int com_apop (int, char **);
int com_capa (int, char **);
int com_disconnect (int, char **);
int com_dele (int, char **);
int com_exit (int, char **);
int com_help (int, char **);
int com_list (int, char **);
int com_noop (int, char **);
int com_connect (int, char **);
int com_pass (int, char **);
int com_quit (int, char **);
int com_retr (int, char **);
int com_rset (int, char **);
int com_stat (int, char **);
int com_top (int, char **);
int com_uidl (int, char **);
int com_user (int, char **);
int com_verbose (int, char **);
int com_prompt (int, char **);
int com_stls (int, char **);
void sig_int (int);
COMMAND *find_command (char *);
COMMAND commands[] = {
{ "apop", com_apop, "Authenticate with APOP: APOP user secret" },
{ "capa", com_capa, "List capabilities: capa" },
{ "disconnect", com_disconnect, "Close connection: disconnect" },
{ "dele", com_dele, "Mark message: DELE msgno" },
{ "exit", com_exit, "exit program" },
{ "help", com_help, "Display this text" },
{ "?", com_help, "Synonym for `help'" },
{ "list", com_list, "List messages: LIST [msgno]" },
{ "noop", com_noop, "Send no operation: NOOP" },
{ "pass", com_pass, "Send passwd: PASS [passwd]" },
{ "prompt", com_prompt, "Set command prompt" },
{ "connect", com_connect, "Open connection: connect hostname [port]" },
{ "quit", com_quit, "Go to Update state : QUIT" },
{ "retr", com_retr, "Dowload message: RETR msgno" },
{ "rset", com_rset, "Unmark all messages: RSET" },
{ "stat", com_stat, "Get the size and count of mailbox : STAT [msgno]" },
{ "stls", com_stls, "Start TLS negotiation" },
{ "top", com_top, "Get the header of message: TOP msgno [lines]" },
{ "uidl", com_uidl, "Get the unique id of message: UIDL [msgno]" },
{ "user", com_user, "send login: USER user" },
{ "verbose", com_verbose, "Enable Protocol tracing: verbose [on|off]" },
{ NULL, NULL, NULL }
{ "apop", 3, 3, com_apop,
"Authenticate with APOP: APOP user secret" },
{ "capa", 1, -1, com_capa,
"List capabilities: capa [-reread] [names...]" },
{ "disconnect", 1, 1,
com_disconnect, "Close connection: disconnect" },
{ "dele", 2, 2, com_dele,
"Mark message: DELE msgno" },
{ "exit", 1, 1, com_exit,
"exit program" },
{ "help", 1, 1, com_help,
"Display this text" },
{ "?", 1, 1, com_help,
"Synonym for `help'" },
{ "list", 1, 2, com_list,
"List messages: LIST [msgno]" },
{ "noop", 1, 1, com_noop,
"Send no operation: NOOP" },
{ "pass", 1, 2, com_pass,
"Send passwd: PASS [passwd]" },
{ "prompt", -1, -1, com_prompt,
"Set command prompt" },
{ "connect", 1, 4, com_connect,
"Open connection: connect [-tls] hostname port" },
{ "quit", 1, 1, com_quit,
"Go to Update state : QUIT" },
{ "retr", 2, 2, com_retr,
"Dowload message: RETR msgno" },
{ "rset", 1, 1, com_rset,
"Unmark all messages: RSET" },
{ "stat", 1, 1, com_stat,
"Get the size and count of mailbox : STAT" },
{ "stls", 1, 1, com_stls,
"Start TLS negotiation" },
{ "top", 2, 3, com_top,
"Get the header of message: TOP msgno [lines]" },
{ "uidl", 1, 2, com_uidl,
"Get the unique id of message: UIDL [msgno]" },
{ "user", 2, 2, com_user,
"send login: USER user" },
{ "verbose", 1, 2, com_verbose,
"Enable Protocol tracing: verbose [on|off]" },
{ NULL }
};
/* Global handle for pop3. */
......@@ -189,20 +207,6 @@ expand_prompt ()
return str;
}
char *
dupstr (const char *s)
{
char *r;
r = malloc (strlen (s) + 1);
if (!r)
{
mu_error ("Memory exhausted");
exit (1);
}
strcpy (r, s);
return r;
}
#ifdef WITH_READLINE
......@@ -269,7 +273,7 @@ command_generator (const char *text, int state)
list_index++;
if (strncmp (name, text, len) == 0)
return (dupstr (name));
return xstrdup (name);
}
/* If no names matched, then return NULL. */
......@@ -304,73 +308,103 @@ add_history (const char *s MU_ARG_UNUSED)
}
#endif
int
get_bool (const char *str, int *pb)
{
if (mu_c_strcasecmp (str, "yes") == 0
|| mu_c_strcasecmp (str, "on") == 0
|| mu_c_strcasecmp (str, "true") == 0)
*pb = 1;
else if (mu_c_strcasecmp (str, "no") == 0
|| mu_c_strcasecmp (str, "off") == 0
|| mu_c_strcasecmp (str, "false") == 0)
*pb = 0;
else
{
mu_error ("not a boolean: %s", str);
return 1;
}
return 0;
}
int
main (int argc MU_ARG_UNUSED, char **argv)
get_port (const char *port_str, int *pn)
{
char *line, *s;
short port_num;
long num;
char *p;
mu_set_program_name (argv[0]);
prompt = strdup (DEFAULT_PROMPT);
initialize_readline (); /* Bind our completer. */
#ifdef WITH_TLS
mu_init_tls_libs ();
#endif
/* Loop reading and executing lines until the user quits. */
while (!done)
num = port_num = strtol (port_str, &p, 0);
if (*p == 0)
{
char *p = expand_prompt ();
line = readline (p);
free (p);
if (!line)
break;
/* Remove leading and trailing whitespace from the line.
Then, if there is anything left, add it to the history list
and execute it. */
s = mu_str_stripws (line);
if (*s)
if (num != port_num)
{
int status;
add_history (s);
status = execute_line (s);
if (status != 0)
mu_error ("Error: %s", mu_strerror (status));
mu_error ("bad port number: %s", port_str);
return 1;
}
free (line);
}
exit (0);
else
{
struct servent *sp = getservbyname (port_str, "tcp");
if (!sp)
{
mu_error ("unknown port name");
return 1;
}
port_num = ntohs (sp->s_port);
}
*pn = port_num;
return 0;
}
/* Parse and execute a command line. */
int
execute_line (char *line)
{
COMMAND *command;
char *word, *arg;
int argc;
char **argv;
int status = 0;
/* Isolate the command word. */
word = mu_str_skip_class (line, MU_CTYPE_SPACE);
arg = mu_str_skip_class_comp (word, MU_CTYPE_SPACE);
if (*arg)
if (mu_argcv_get (line, NULL, "#", &argc, &argv))
{
*arg++ = 0;
arg = mu_str_skip_class (arg, MU_CTYPE_SPACE);
mu_error("cannot parse input line");
return 0;
}
command = find_command (word);
if (argc >= 0)
{
COMMAND *command = find_command (argv[0]);
if (!command)
mu_error ("%s: no such command.", argv[0]);
else if (command->argmin > 0 && argc < command->argmin)
mu_error ("%s: too few arguments", argv[0]);
else if (command->argmax > 0 && argc > command->argmax)
mu_error ("%s: too many arguments", argv[0]);
else
{
mu_error ("%s: No such command.", word);
return 0;
if (command->argmin <= 0 && argc != 2)
{
char *word = mu_str_skip_class (line, MU_CTYPE_SPACE);
char *arg = mu_str_skip_class_comp (word, MU_CTYPE_SPACE);
if (*arg)
{
*arg++ = 0;
arg = mu_str_skip_class (arg, MU_CTYPE_SPACE);
}
/* Call the function. */
return ((*(command->func)) (arg));
mu_argcv_free (argc, argv);
argc = 2;
argv = xcalloc (argc + 1, sizeof (argv[0]));
argv[0] = xstrdup (word);
argv[1] = xstrdup (arg);
argv[2] = NULL;
}
status = command->func (argc, argv);
}
}
mu_argcv_free (argc, argv);
return status;
}
/* Look up NAME as the name of a command, and return a pointer to that
......@@ -378,23 +412,32 @@ execute_line (char *line)
COMMAND *
find_command (char *name)
{
register int i;
COMMAND *cp;
for (i = 0; commands[i].name; i++)
if (strcmp (name, commands[i].name) == 0)
return (&commands[i]);
for (cp = commands; cp->name; cp++)
if (strcmp (cp->name, name) == 0)
return cp;
return ((COMMAND *) NULL);
return NULL;
}
int
com_verbose (char *arg)
com_verbose (int argc, char **argv)
{
int status = 0;
if (!valid_argument ("verbose", arg))
return EINVAL;
if (argc == 1)
{
if (verbose)
printf ("verbose is on\n");
else
printf ("verbose is off\n");
}
else
{
int bv;
verbose = (strcmp (arg, "on") == 0);
if (get_bool (argv[1], &bv) == 0)
{
verbose = bv;
if (pop3 != NULL)
{
if (verbose == 1)
......@@ -402,61 +445,84 @@ com_verbose (char *arg)
else
mu_pop3_trace (pop3, MU_POP3_TRACE_CLR);
}
return status;
}
}
return 0;
}
int
com_user (char *arg)
com_user (int argc, char **argv)
{
int status;
if (!valid_argument ("user", arg))
return EINVAL;
status = mu_pop3_user (pop3, arg);
status = mu_pop3_user (pop3, argv[1]);
if (status == 0)
username = strdup (arg);
username = strdup (argv[1]);
return status;
}
int
com_apop (char *arg)
com_apop (int argc, char **argv)
{
int status;
char *user, *digest;
if (!valid_argument ("apop", arg))
return EINVAL;
user = strtok (arg, " ");
digest = strtok (NULL, " ");
if (!valid_argument ("apop", user) || !valid_argument ("apop", digest))
return EINVAL;
status = mu_pop3_apop (pop3, user, digest);
status = mu_pop3_apop (pop3, argv[1], argv[2]);
if (status == 0)
{
username = strdup (user);
username = strdup (argv[1]);
pop_session_status = pop_session_logged_in;
}
return status;
}
int
com_capa (char *arg)
com_capa (int argc, char **argv)
{
mu_iterator_t iterator = NULL;
int status;
int status = 0;
int reread = 0;
int i = 1;
if (arg && *arg)
for (i = 1; i < argc; i++)
{
if (strcmp (arg, "reread") == 0)
if (strcmp (argv[i], "-reread") == 0)
reread = 1;
else
{
mu_error ("%s: unknown argument", "capa");
return 0;
break;
}
if (i < argc)
{
if (reread)
{
status = mu_pop3_capa (pop3, 1, NULL);
if (status)
return status;
}
for (; i < argc; i++)
{
const char *elt;
int rc = pop3_capa_test (pop3, argv[i], &elt);
switch (rc)
{
case 0:
if (*elt)
printf ("%s: %s\n", argv[i], elt);
else
printf ("%s is set\n", argv[i]);
break;
case MU_ERR_NOENT:
printf ("%s is not set\n", argv[i]);
break;
default:
return rc;
}
}
}
else
{
status = mu_pop3_capa (pop3, reread, &iterator);
if (status == 0)
......@@ -466,18 +532,19 @@ com_capa (char *arg)
{
char *capa = NULL;
mu_iterator_current (iterator, (void **) &capa);
printf ("Capa: %s\n", (capa) ? capa : "");
printf ("CAPA: %s\n", capa ? capa : "");
}
mu_iterator_destroy (&iterator);
}
}
return status;
}
int
com_uidl (char *arg)
com_uidl (int argc, char **argv)
{
int status = 0;
if (arg == NULL || *arg == '\0')
if (argc == 1)
{
mu_iterator_t uidl_iterator = NULL;
status = mu_pop3_uidl_all (pop3, &uidl_iterator);
......@@ -489,7 +556,7 @@ com_uidl (char *arg)
{
char *uidl = NULL;
mu_iterator_current (uidl_iterator, (void **) &uidl);
printf ("UIDL: %s\n", (uidl) ? uidl : "");
printf ("UIDL: %s\n", uidl ? uidl : "");
}
mu_iterator_destroy (&uidl_iterator);
}
......@@ -497,20 +564,20 @@ com_uidl (char *arg)
else
{
char *uidl = NULL;
unsigned int msgno = strtoul (arg, NULL, 10);
unsigned int msgno = strtoul (argv[1], NULL, 10);
status = mu_pop3_uidl (pop3, msgno, &uidl);
if (status == 0)
printf ("Msg: %d UIDL: %s\n", msgno, (uidl) ? uidl : "");
printf ("Msg: %d UIDL: %s\n", msgno, uidl ? uidl : "");
free (uidl);
}
return status;
}
int
com_list (char *arg)
com_list (int argc, char **argv)
{
int status = 0;
if (arg == NULL || *arg == '\0')
if (argc == 1)
{
mu_iterator_t list_iterator;
status = mu_pop3_list_all (pop3, &list_iterator);
......@@ -530,7 +597,7 @@ com_list (char *arg)
else
{
size_t size = 0;
unsigned int msgno = strtoul (arg, NULL, 10);
unsigned int msgno = strtoul (argv[1], NULL, 10);
status = mu_pop3_list (pop3, msgno, &size);
if (status == 0)
printf ("Msg: %u Size: %lu\n", msgno, (unsigned long) size);
......@@ -539,7 +606,7 @@ com_list (char *arg)
}
int
com_noop (char *arg MU_ARG_UNUSED)
com_noop (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
{
return mu_pop3_noop (pop3);
}
......@@ -561,33 +628,31 @@ echo_on (struct termios *stored_settings)
}
int
com_prompt (char *arg)
com_prompt (int argc, char **argv)
{
int quote;
size_t size;
if (!valid_argument ("prompt", arg))
return EINVAL;
free (prompt);
size = mu_argcv_quoted_length (arg, &quote);
size = mu_argcv_quoted_length (argv[1], &quote);
prompt = malloc (size + 1);
if (!prompt)
{
mu_error ("Memory exhausted");
exit (1);
}
mu_argcv_unquote_copy (prompt, arg, size);
mu_argcv_unquote_copy (prompt, argv[1], size);
return 0;
}
int
com_pass (char *arg)
com_pass (int argc, char **argv)
{
int status;
char pass[256];
char *pwd;
if (!arg || *arg == '\0')
if (argc == 1)
{
struct termios stored_settings;
......@@ -599,16 +664,18 @@ com_pass (char *arg)
putchar ('\n');
fflush (stdout);
pass[strlen (pass) - 1] = '\0'; /* nuke the trailing line. */
arg = pass;
pwd = pass;
}
status = mu_pop3_pass (pop3, arg);
else
pwd = argv[1];
status = mu_pop3_pass (pop3, pwd);
if (status == 0)
pop_session_status = pop_session_logged_in;
return status;
}
int
com_stat (char *arg MU_ARG_UNUSED)
com_stat (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
{
unsigned count = 0;
size_t size = 0;
......@@ -621,32 +688,31 @@ com_stat (char *arg MU_ARG_UNUSED)
}
int
com_stls (char *arg MU_ARG_UNUSED)
com_stls (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
{
return mu_pop3_stls (pop3);
}
int
com_dele (char *arg)
com_dele (int argc, char **argv)
{
unsigned msgno;
if (!valid_argument ("dele", arg))
return EINVAL;
msgno = strtoul (arg, NULL, 10);
msgno = strtoul (argv[1], NULL, 10);
return mu_pop3_dele (pop3, msgno);
}
/* Print out help for ARG, or for all of the commands if ARG is
not present. */
int
com_help (char *arg)
com_help (int argc, char **argv)
{
int i;
int printed = 0;
char *name = argv[1];
for (i = 0; commands[i].name; i++)
{
if (!*arg || (strcmp (arg, commands[i].name) == 0))
if (!name || (strcmp (name, commands[i].name) == 0))
{
printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc);
printed++;
......@@ -655,7 +721,7 @@ com_help (char *arg)
if (!printed)
{
printf ("No commands match `%s'. Possibilties are:\n", arg);
printf ("No commands match `%s'. Possibilties are:\n", name);
for (i = 0; commands[i].name; i++)
{
......@@ -677,32 +743,24 @@ com_help (char *arg)
}
int
com_rset (char *arg MU_ARG_UNUSED)
com_rset (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
{
return mu_pop3_rset (pop3);
}
int
com_top (char *arg)
com_top (int argc, char **argv)
{
mu_stream_t stream;
unsigned int msgno;
unsigned int lines;
char *space;
int status;
if (!valid_argument ("top", arg))
return EINVAL;
space = strchr (arg, ' ');
if (space)
{
*space++ = '\0';
lines = strtoul (space, NULL, 10);
}
msgno = strtoul (argv[1], NULL, 10);
if (argc == 3)
lines = strtoul (argv[2], NULL, 10);
else
lines = 0;
msgno = strtoul (arg, NULL, 10);
lines = 5;
status = mu_pop3_top (pop3, msgno, lines, &stream);
......@@ -718,16 +776,13 @@ com_top (char *arg)
}
int
com_retr (char *arg)
com_retr (int argc, char **argv)
{
mu_stream_t stream;
unsigned int msgno;
int status;
if (!valid_argument ("retr", arg))
return EINVAL;
msgno = strtoul (arg, NULL, 10);
msgno = strtoul (argv[1], NULL, 10);
status = mu_pop3_retr (pop3, msgno, &stream);
if (status == 0)
......@@ -742,73 +797,44 @@ com_retr (char *arg)
}
int
get_port (const char *port_str, int *pn)
com_connect (int argc, char **argv)
{
short port_num;
long num;
char *p;
int status;
int n = 0;
int tls = 0;
int i = 1;
num = port_num = strtol (port_str, &p, 0);
if (*p == 0)
for (i = 1; i < argc; i++)
{
if (num != port_num)
if (strcmp (argv[i], "-tls") == 0)
{
mu_error ("bad port number: %s", port_str);
return 1;
}
}
if (WITH_TLS)
tls = 1;
else
{
struct servent *sp = getservbyname (port_str, "tcp");
if (!sp)
{
mu_error ("unknown port name");
return 1;
}
port_num = ntohs (sp->s_port);
}
*pn = port_num;
return 0;
}
int
com_connect (char *arg)
{
int status;
int n = 110;
int argc;
char **argv;
if (!valid_argument ("connect", arg))
return 1;
if (mu_argcv_get (arg, NULL, NULL, &argc, &argv))
{
mu_error ("Cannot parse arguments");
mu_error ("TLS not supported");
return 0;
}
if (!valid_argument ("connect", argv[0]))
{
mu_argcv_free (argc, argv);
return EINVAL;
}
if (argc > 2)
{
mu_error ("Too many arguments");
mu_argcv_free (argc, argv);
return 0;
else
break;
}
if (argc == 2 && get_port (argv[1], &n))
argc -= i;
argv += i;
if (argc >= 2)
{
mu_argcv_free (argc, argv);
if (get_port (argv[1], &n))
return 0;
}
else if (tls)
n = MU_POP3_DEFAULT_SSL_PORT;
else
n = MU_POP3_DEFAULT_PORT;
if (pop_session_status != pop_session_disconnected)
com_disconnect (NULL);
com_disconnect (0, NULL);
status = mu_pop3_create (&pop3);
if (status == 0)
......@@ -816,10 +842,35 @@ com_connect (char *arg)
mu_stream_t tcp;
if (verbose)
com_verbose ("on");
mu_pop3_trace (pop3, MU_POP3_TRACE_SET);
status = mu_tcp_stream_create (&tcp, argv[0], n, MU_STREAM_READ);
if (status == 0)
{
#ifdef WITH_TLS
if (tls)
{
mu_stream_t tlsstream;
status = mu_stream_open (tcp);
if (status)
{
mu_error ("cannot open connection: %s",
mu_stream_strerror (tcp, status));
mu_stream_destroy (&tcp);
return 0;
}
status = mu_tls_client_stream_create (&tlsstream, tcp, tcp, 0);
mu_stream_unref (tcp);
if (status)
{
mu_error ("cannot create TLS stream: %s",
mu_strerror (status));
return 0;
}
tcp = tlsstream;
}
#endif
mu_pop3_set_carrier (pop3, tcp);
status = mu_pop3_connect (pop3);
}
......@@ -831,14 +882,14 @@ com_connect (char *arg)
}
if (status)
{
mu_error ("Failed to create pop3: %s", mu_strerror (status));
mu_argcv_free (argc, argv);
}
else
{
connect_argc = argc;
connect_argv = argv;
connect_argv = xcalloc (argc, sizeof (*connect_argv));
for (i = 0; i < argc; i++)
connect_argv[i] = xstrdup (argv[i]);
connect_argv[i] = NULL;
port = n;
pop_session_status = pop_session_connected;
}
......@@ -847,7 +898,7 @@ com_connect (char *arg)
}
int
com_disconnect (char *arg MU_ARG_UNUSED)
com_disconnect (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
{
if (pop3)
{
......@@ -864,14 +915,14 @@ com_disconnect (char *arg MU_ARG_UNUSED)
}
int
com_quit (char *arg MU_ARG_UNUSED)
com_quit (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
{
int status = 0;
if (pop3)
{
if (mu_pop3_quit (pop3) == 0)
{
status = com_disconnect (arg);
status = com_disconnect (0, NULL);
}
else
{
......@@ -884,7 +935,7 @@ com_quit (char *arg MU_ARG_UNUSED)
}
int
com_exit (char *arg MU_ARG_UNUSED)
com_exit (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
{
if (pop3)
{
......@@ -895,16 +946,44 @@ com_exit (char *arg MU_ARG_UNUSED)
return 0;
}
/* Return non-zero if ARG is a valid argument for CALLER, else print
an error message and return zero. */
int
valid_argument (const char *caller, char *arg)
main (int argc MU_ARG_UNUSED, char **argv)
{
if (!arg || !*arg)
char *line, *s;
mu_set_program_name (argv[0]);
prompt = strdup (DEFAULT_PROMPT);
initialize_readline (); /* Bind our completer. */
#ifdef WITH_TLS
mu_init_tls_libs ();
#endif
/* Loop reading and executing lines until the user quits. */
while (!done)
{
mu_error ("%s: Argument required", caller);
return 0;
char *p = expand_prompt ();
line = readline (p);
free (p);
if (!line)
break;
/* Remove leading and trailing whitespace from the line.
Then, if there is anything left, add it to the history list
and execute it. */
s = mu_str_stripws (line);
if (*s)
{
int status;
add_history (s);
status = execute_line (s);
if (status != 0)
mu_error ("Error: %s", mu_strerror (status));
}
return 1;
free (line);
}
exit (0);
}
......
......@@ -32,87 +32,99 @@ struct _mu_pop3;
typedef struct _mu_pop3 *mu_pop3_t;
#define MU_POP3_DEFAULT_PORT 110
#define MU_POP3_DEFAULT_SSL_PORT 995
extern int mu_pop3_create (mu_pop3_t *pop3);
extern void mu_pop3_destroy (mu_pop3_t *pop3);
int mu_pop3_create (mu_pop3_t *pop3);
void mu_pop3_destroy (mu_pop3_t *pop3);
extern int mu_pop3_set_carrier (mu_pop3_t pop3, mu_stream_t carrier);
extern int mu_pop3_get_carrier (mu_pop3_t pop3, mu_stream_t *pcarrier);
int mu_pop3_set_carrier (mu_pop3_t pop3, mu_stream_t carrier);
int mu_pop3_get_carrier (mu_pop3_t pop3, mu_stream_t *pcarrier);
extern int mu_pop3_connect (mu_pop3_t pop3);
extern int mu_pop3_disconnect (mu_pop3_t pop3);
int mu_pop3_connect (mu_pop3_t pop3);
int mu_pop3_disconnect (mu_pop3_t pop3);
extern int mu_pop3_set_timeout (mu_pop3_t pop3, int timeout);
extern int mu_pop3_get_timeout (mu_pop3_t pop3, int *timeout);
int mu_pop3_set_timeout (mu_pop3_t pop3, int timeout);
int mu_pop3_get_timeout (mu_pop3_t pop3, int *timeout);
#define MU_POP3_TRACE_CLR 0
#define MU_POP3_TRACE_SET 1
#define MU_POP3_TRACE_QRY 2
extern int mu_pop3_trace (mu_pop3_t pop3, int op);
int mu_pop3_trace (mu_pop3_t pop3, int op);
extern int mu_pop3_apop (mu_pop3_t pop3, const char *name, const char *digest);
int mu_pop3_apop (mu_pop3_t pop3, const char *name, const char *digest);
extern int mu_pop3_stls (mu_pop3_t pop3);
int mu_pop3_stls (mu_pop3_t pop3);
/* It is the responsability of the caller to call mu_iterator_destroy() when
done with the iterator. The items returned by the iterator are of type
"const char *", no processing is done on the item except the removal of
the trailing newline. */
extern int mu_pop3_capa (mu_pop3_t pop3, int reread,
mu_iterator_t *piter);
int mu_pop3_capa (mu_pop3_t pop3, int reread, mu_iterator_t *piter);
int pop3_capa_test (mu_pop3_t pop3, const char *name, const char **pret);
extern int mu_pop3_dele (mu_pop3_t pop3, unsigned int mesgno);
int mu_pop3_dele (mu_pop3_t pop3, unsigned int mesgno);
extern int mu_pop3_list (mu_pop3_t pop3, unsigned int mesgno, size_t *mesg_octet);
int mu_pop3_list (mu_pop3_t pop3, unsigned int mesgno, size_t *mesg_octet);
/* An iterator is return with the multi-line answer. It is the responsability
of the caller to call mu_iterator_destroy() to dispose of the iterator. */
extern int mu_pop3_list_all (mu_pop3_t pop3, mu_iterator_t *piterator);
/* Send the LIST command and prepare pop3 for receiving a multiline answer.
The caller is expected to obtain a stream via mu_pop3_stream_create,
or an iterator via mu_pop3_iterator_create and read data from them.
extern int mu_pop3_noop (mu_pop3_t pop3);
This function is not intended for use by a casual user, better use
mu_pop3_list_all or mu_pop3_list_all_stream. */
int mu_pop3_list_cmd (mu_pop3_t pop3);
int mu_pop3_list_all (mu_pop3_t pop3, mu_iterator_t *pitr);
int mu_pop3_list_all_stream (mu_pop3_t pop3, mu_stream_t *pstream);
extern int mu_pop3_pass (mu_pop3_t pop3, const char *pass);
int mu_pop3_noop (mu_pop3_t pop3);
extern int mu_pop3_quit (mu_pop3_t pop3);
int mu_pop3_pass (mu_pop3_t pop3, const char *pass);
int mu_pop3_quit (mu_pop3_t pop3);
/* A stream is returned with the multi-line answer. It is the responsability
of the caller to call mu_stream_destroy() to dipose of the stream. */
extern int mu_pop3_retr (mu_pop3_t pop3, unsigned int mesgno,
int mu_pop3_retr (mu_pop3_t pop3, unsigned int mesgno,
mu_stream_t *pstream);
extern int mu_pop3_rset (mu_pop3_t pop3);
int mu_pop3_rset (mu_pop3_t pop3);
extern int mu_pop3_stat (mu_pop3_t pop3, unsigned int *count,
size_t *octets);
int mu_pop3_stat (mu_pop3_t pop3, unsigned int *count, size_t *octets);
/* A stream is returned with the multi-line answer. It is the responsability
of the caller to call mu_stream_destroy() to dipose of the stream. */
extern int mu_pop3_top (mu_pop3_t pop3, unsigned int mesgno,
int mu_pop3_top (mu_pop3_t pop3, unsigned int mesgno,
unsigned int lines, mu_stream_t *pstream);
/* The uidl is malloc'ed and returned in puidl; it is the responsability of
the caller to free() the uild when done. */
extern int mu_pop3_uidl (mu_pop3_t pop3, unsigned int mesgno,
char **puidl);
/* An iterator is returned with the multi-line answer. It is the
responsability of the caller to call mu_iterator_destroy() to dispose of
the iterator. */
extern int mu_pop3_uidl_all (mu_pop3_t pop3, mu_iterator_t *piterator);
int mu_pop3_uidl (mu_pop3_t pop3, unsigned int mesgno, char **puidl);
extern int mu_pop3_user (mu_pop3_t pop3, const char *user);
/* Send the UIDL command and prepare pop3 for receiving a multiline answer.
The caller is expected to obtain a stream via mu_pop3_stream_create,
or an iterator via mu_pop3_iterator_create and read data from them.
This function is not intended for use by a casual user, better use
mu_pop3_uidl_all or mu_pop3_uidl_all_stream. */
int mu_pop3_uidl_all_cmd (mu_pop3_t pop3);
int mu_pop3_uidl_all (mu_pop3_t pop3, mu_iterator_t *piterator);
int mu_pop3_uidl_all_stream (mu_pop3_t pop3, mu_stream_t *pstream);
int mu_pop3_user (mu_pop3_t pop3, const char *user);
/* Returns the last command acknowledge. If the server supports RESP-CODE,
the message could be retrieved, but it is up to the caller to do the
parsing. */
extern int mu_pop3_response (mu_pop3_t pop3, size_t *nread);
int mu_pop3_response (mu_pop3_t pop3, size_t *nread);
extern int mu_pop3_writeline (mu_pop3_t pop3, const char *format, ...)
int mu_pop3_writeline (mu_pop3_t pop3, const char *format, ...)
MU_PRINTFLIKE(2,3);
extern int mu_pop3_sendline (mu_pop3_t pop3, const char *line);
extern int mu_pop3_getline (mu_pop3_t pop3);
int mu_pop3_sendline (mu_pop3_t pop3, const char *line);
int mu_pop3_getline (mu_pop3_t pop3);
int mu_pop3_read_list (mu_pop3_t pop3, mu_list_t list);
int mu_pop3_stream_to_list (mu_pop3_t pop3, mu_stream_t stream,
mu_list_t list);
#ifdef __cplusplus
}
......
......@@ -24,6 +24,9 @@
#define _MU_STR_INTERN_MASK 0xf000
#define _MU_STR_EVENT_SET 1
#define _MU_STR_EVENT_CLR 2
struct _mu_stream
{
int ref_count;
......@@ -54,6 +57,9 @@ struct _mu_stream
int (*truncate) (struct _mu_stream *, mu_off_t);
int (*shutdown) (struct _mu_stream *, int);
void (*event_cb) (struct _mu_stream *, int, int);
int event_mask;
const char *(*error_string) (struct _mu_stream *, int);
};
......@@ -65,6 +71,9 @@ int mu_stream_write_unbuffered (mu_stream_t stream,
const void *buf, size_t size,
int full_write, size_t *pnwritten);
void _mu_stream_cleareof (mu_stream_t str);
void _mu_stream_seteof (mu_stream_t str);
#define _MU_SWAP_FIRST_ONLY 0x01
#define _MU_SWAP_IOCTL_MUST_SUCCEED 0x02
......
......@@ -25,12 +25,13 @@ libmu_pop_la_LDFLAGS=-version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@
libmu_pop_la_LIBADD = ${MU_LIB_AUTH} ${MU_LIB_MAILUTILS} @INTLLIBS@
# folder.c\
# mbox.c\
# url.c
# url.c\
# mbox.c
libmu_pop_la_SOURCES = \
\
pop3_apop.c \
pop3_capa.c \
pop3_capatst.c \
pop3_carrier.c \
pop3_connect.c \
pop3_create.c \
......@@ -39,10 +40,13 @@ libmu_pop_la_SOURCES = \
pop3_disconnect.c \
pop3_iterator.c \
pop3_lista.c \
pop3_listas.c \
pop3_list.c \
pop3_list_cmd.c \
pop3_noop.c \
pop3_pass.c \
pop3_quit.c \
pop3_rdlist.c \
pop3_readline.c \
pop3_response.c \
pop3_retr.c \
......@@ -54,7 +58,9 @@ libmu_pop_la_SOURCES = \
pop3_timeout.c \
pop3_top.c \
pop3_trace.c \
pop3_uidl_cmd.c \
pop3_uidla.c \
pop3_uidlas.c \
pop3_uidl.c \
pop3_user.c
......
......@@ -33,36 +33,18 @@
#include <mailutils/sys/pop3.h>
static int
string_comp (const void *item, const void *value)
capa_comp (const void *item, const void *value)
{
return strcmp (item, value);
}
int
_mu_pop3_fill_list (mu_pop3_t pop3, mu_list_t list)
{
mu_stream_t stream;
size_t n;
int status = mu_pop3_stream_create (pop3, &stream);
if (status)
return status;
while (mu_stream_getline (stream, &pop3->rdbuf, &pop3->rdsize, &n) == 0
&& n > 0)
const char *capa = item;
const char *needle = value;
for (; *needle; capa++, needle++)
{
char *np = strdup (pop3->rdbuf);
if (!np)
{
status = ENOMEM;
break;
}
mu_rtrim_class (np, MU_CTYPE_SPACE);
status = mu_list_append (list, np);
if (status)
break;
if (!*capa)
return 1;
if (mu_tolower (*capa) != mu_tolower (*needle))
return 1;
}
mu_stream_destroy (&stream);
return status;
return !(*capa == 0 || mu_isspace (*capa));
}
/*
......@@ -91,7 +73,7 @@ mu_pop3_capa (mu_pop3_t pop3, int reread, mu_iterator_t *piter)
status = mu_list_create (&pop3->capa);
if (status)
return status;
mu_list_set_comparator (pop3->capa, string_comp);
mu_list_set_comparator (pop3->capa, capa_comp);
mu_list_set_destroy_item (pop3->capa, mu_list_free_item);
switch (pop3->state)
......@@ -109,7 +91,7 @@ mu_pop3_capa (mu_pop3_t pop3, int reread, mu_iterator_t *piter)
pop3->state = MU_POP3_CAPA_RX;
case MU_POP3_CAPA_RX:
status = _mu_pop3_fill_list (pop3, pop3->capa);
status = mu_pop3_read_list (pop3, pop3->capa);
MU_POP3_CHECK_ERROR (pop3, status);
if (piter)
status = mu_list_get_iterator (pop3->capa, piter);
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2003, 2004, 2005, 2007, 2010 Free Software Foundation,
Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <mailutils/list.h>
#include <mailutils/sys/pop3.h>
int
pop3_capa_test (mu_pop3_t pop3, const char *name, const char **pret)
{
int rc;
rc = mu_pop3_capa (pop3, 0, NULL);
if (rc)
return rc;
return mu_list_locate (pop3->capa, (void*) name, (void**)pret);
}
......@@ -40,7 +40,7 @@ mu_pop3_list (mu_pop3_t pop3, unsigned int msgno, size_t *psize)
switch (pop3->state)
{
case MU_POP3_NO_STATE:
status = mu_pop3_writeline (pop3, "LIST %d\r\n", msgno);
status = mu_pop3_writeline (pop3, "LIST %u\r\n", msgno);
MU_POP3_CHECK_ERROR (pop3, status);
MU_POP3_FCLR (pop3, MU_POP3_ACK);
pop3->state = MU_POP3_LIST;
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2004, 2007, 2010 Free Software
Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_list_cmd (mu_pop3_t pop3)
{
int status = 0;
if (pop3 == NULL)
return EINVAL;
switch (pop3->state)
{
case MU_POP3_NO_STATE:
status = mu_pop3_writeline (pop3, "LIST\r\n");
MU_POP3_CHECK_ERROR (pop3, status);
MU_POP3_FCLR (pop3, MU_POP3_ACK);
pop3->state = MU_POP3_LIST;
case MU_POP3_LIST:
status = mu_pop3_response (pop3, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
MU_POP3_CHECK_OK (pop3);
pop3->state = MU_POP3_LIST_RX;
case MU_POP3_LIST_RX:
/* The mu_iterator_t will read the stream and set the state to
MU_POP3_NO_STATE when done. */
break;
/* They must deal with the error first by reopening. */
case MU_POP3_ERROR:
status = ECANCELED;
break;
default:
status = EINPROGRESS;
}
return status;
}
......@@ -21,51 +21,19 @@
# include <config.h>
#endif
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_list_all (mu_pop3_t pop3, mu_iterator_t *piterator)
{
int status = 0;
int status = mu_pop3_list_cmd (pop3);
if (pop3 == NULL)
return EINVAL;
if (piterator == NULL)
return MU_ERR_OUT_PTR_NULL;
switch (pop3->state)
{
case MU_POP3_NO_STATE:
status = mu_pop3_writeline (pop3, "LIST\r\n");
MU_POP3_CHECK_ERROR (pop3, status);
MU_POP3_FCLR (pop3, MU_POP3_ACK);
pop3->state = MU_POP3_LIST;
if (status)
return status;
case MU_POP3_LIST:
status = mu_pop3_response (pop3, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
MU_POP3_CHECK_OK (pop3);
status = mu_pop3_iterator_create (pop3, piterator);
MU_POP3_CHECK_ERROR (pop3, status);
pop3->state = MU_POP3_LIST_RX;
case MU_POP3_LIST_RX:
/* The mu_iterator_t will read the stream and set the state to
MU_POP3_NO_STATE when done. */
break;
/* They must deal with the error first by reopening. */
case MU_POP3_ERROR:
status = ECANCELED;
break;
default:
status = EINPROGRESS;
}
return status;
}
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2004, 2007, 2010 Free Software
Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <mailutils/sys/pop3.h>
int
mu_pop3_list_all_stream (mu_pop3_t pop3, mu_stream_t *pstream)
{
int status = mu_pop3_list_cmd (pop3);
if (status)
return status;
status = mu_pop3_stream_create (pop3, pstream);
MU_POP3_CHECK_ERROR (pop3, status);
pop3->state = MU_POP3_LIST_RX;
return status;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2003, 2004, 2005, 2007, 2010 Free Software Foundation,
Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <mailutils/stream.h>
#include <mailutils/list.h>
#include <mailutils/cctype.h>
#include <mailutils/cstr.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_stream_to_list (mu_pop3_t pop3, mu_stream_t stream, mu_list_t list)
{
int status;
size_t n;
while (mu_stream_getline (stream, &pop3->rdbuf, &pop3->rdsize, &n) == 0
&& n > 0)
{
char *np = strdup (pop3->rdbuf);
if (!np)
{
status = ENOMEM;
break;
}
mu_rtrim_class (np, MU_CTYPE_SPACE);
status = mu_list_append (list, np);
if (status)
break;
}
return status;
}
int
mu_pop3_read_list (mu_pop3_t pop3, mu_list_t list)
{
mu_stream_t stream;
int status = mu_pop3_stream_create (pop3, &stream);
if (status)
return status;
status = mu_pop3_stream_to_list (pop3, stream, list);
mu_stream_destroy (&stream);
return status;
}
......@@ -48,12 +48,11 @@ mu_pop3_retr (mu_pop3_t pop3, unsigned int msgno, mu_stream_t *pstream)
status = mu_pop3_response (pop3, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
MU_POP3_CHECK_OK (pop3);
status = mu_pop3_stream_create (pop3, pstream);
MU_POP3_CHECK_ERROR (pop3, status);
pop3->state = MU_POP3_RETR_RX;
case MU_POP3_RETR_RX:
status = mu_pop3_stream_create (pop3, pstream);
MU_POP3_CHECK_ERROR (pop3, status);
pop3->state = MU_POP3_NO_STATE;
break;
/* They must deal with the error first by reopening. */
......
......@@ -39,6 +39,7 @@ struct mu_pop3_stream
enum pop3_decode_state
{
pds_init, /* initial state */
pds_char, /* Any character excepting [\r\n.] */
pds_cr, /* prev. char was \r */
pds_crlf, /* 2 prev. char were \r\n */
pds_dot, /* 3 prev. chars were \r\n. */
......@@ -56,6 +57,16 @@ newstate (int state, int c)
{
case '\r':
return pds_cr;
case '.':
return pds_dot;
}
break;
case pds_char:
switch (c)
{
case '\r':
return pds_cr;
}
break;
......@@ -93,7 +104,7 @@ newstate (int state, int c)
return pds_end;
}
}
return pds_init;
return pds_char;
}
/* Move min(isize,osize) bytes from iptr to optr, replacing each \r\n
......@@ -140,7 +151,7 @@ _pop3_decoder (void *xd,
if (*iptr == '\n')
continue;
}
else if (c == '.' && *pstate == pds_crlf)
else if (c == '.' && (*pstate == pds_init || *pstate == pds_crlf))
{
/* Make sure we have two more characters in the buffer */
if (i + 2 == isize)
......@@ -164,16 +175,39 @@ _pop3_decoder (void *xd,
return mu_filter_ok;
}
static void
_pop3_event_cb (mu_stream_t str, int ev, int flags)
{
if (ev == _MU_STR_EVENT_SET)
{
mu_transport_t trans[2];
if (mu_stream_ioctl (str, MU_IOCTL_GET_TRANSPORT, trans) == 0)
{
struct mu_pop3_stream *sp = (struct mu_pop3_stream *) trans[0];
sp->pop3->state = MU_POP3_NO_STATE;
}
}
}
static int
mu_pop3_filter_create (mu_stream_t *pstream, mu_stream_t stream)
{
int rc;
int *state = malloc (sizeof (*state));
if (!state)
return ENOMEM;
return mu_filter_stream_create (pstream, stream,
rc = mu_filter_stream_create (pstream, stream,
MU_FILTER_DECODE,
_pop3_decoder, state,
MU_STREAM_READ);
if (rc == 0)
{
mu_stream_t str = *pstream;
str->event_cb = _pop3_event_cb;
str->event_mask = _MU_STR_EOF;
}
return rc;
}
......@@ -257,6 +291,7 @@ mu_pop3_stream_create (mu_pop3_t pop3, mu_stream_t *pstream)
sp->stream.readdelim = _mu_pop3_readdelim;
sp->stream.flush = _mu_pop3_flush;
sp->stream.wait = _mu_pop3_wait;
sp->pop3 = pop3;
sp->done = 0;
str = (mu_stream_t) sp;
......
......@@ -48,12 +48,11 @@ mu_pop3_top (mu_pop3_t pop3, unsigned msgno, unsigned int lines,
status = mu_pop3_response (pop3, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
MU_POP3_CHECK_OK (pop3);
status = mu_pop3_stream_create (pop3, pstream);
MU_POP3_CHECK_ERROR (pop3, status);
pop3->state = MU_POP3_TOP_RX;
case MU_POP3_TOP_RX:
status = mu_pop3_stream_create (pop3, pstream);
MU_POP3_CHECK_ERROR (pop3, status);
pop3->state = MU_POP3_NO_STATE;
break;
/* They must deal with the error first by reopening. */
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2003, 2004, 2007, 2010 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_uidl_all_cmd (mu_pop3_t pop3)
{
int status = 0;
if (pop3 == NULL)
return EINVAL;
switch (pop3->state)
{
case MU_POP3_NO_STATE:
status = mu_pop3_writeline (pop3, "UIDL\r\n");
MU_POP3_CHECK_ERROR (pop3, status);
MU_POP3_FCLR (pop3, MU_POP3_ACK);
pop3->state = MU_POP3_UIDL;
case MU_POP3_UIDL:
status = mu_pop3_response (pop3, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
MU_POP3_CHECK_OK (pop3);
pop3->state = MU_POP3_UIDL_RX;
case MU_POP3_UIDL_RX:
break;
/* They must deal with the error first by reopening. */
case MU_POP3_ERROR:
status = ECANCELED;
break;
default:
status = EINPROGRESS;
}
return status;
}
......@@ -20,50 +20,17 @@
# include <config.h>
#endif
#include <string.h>
# include <errno.h>
#include <stdlib.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_uidl_all (mu_pop3_t pop3, mu_iterator_t *piterator)
{
int status = 0;
if (pop3 == NULL)
return EINVAL;
if (piterator == NULL)
return MU_ERR_OUT_PTR_NULL;
switch (pop3->state)
{
case MU_POP3_NO_STATE:
status = mu_pop3_writeline (pop3, "UIDL\r\n");
MU_POP3_CHECK_ERROR (pop3, status);
MU_POP3_FCLR (pop3, MU_POP3_ACK);
pop3->state = MU_POP3_UIDL;
case MU_POP3_UIDL:
status = mu_pop3_response (pop3, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
MU_POP3_CHECK_OK (pop3);
int status = mu_pop3_uidl_all_cmd (pop3);
if (status)
return status;
status = mu_pop3_iterator_create (pop3, piterator);
MU_POP3_CHECK_ERROR (pop3, status);
pop3->state = MU_POP3_UIDL_RX;
case MU_POP3_UIDL_RX:
/* The mu_iterator_t will read the stream and set the state to
MU_POP3_NO_STATE when done. */
break;
/* They must deal with the error first by reopening. */
case MU_POP3_ERROR:
status = ECANCELED;
break;
default:
status = EINPROGRESS;
}
return status;
}
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2003, 2004, 2007, 2010 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <mailutils/sys/pop3.h>
int
mu_pop3_uidl_all_stream (mu_pop3_t pop3, mu_stream_t *pstream)
{
int status = mu_pop3_uidl_all_cmd (pop3);
if (status)
return status;
status = mu_pop3_stream_create (pop3, pstream);
MU_POP3_CHECK_ERROR (pop3, status);
pop3->state = MU_POP3_UIDL_RX;
return status;
}
......@@ -164,7 +164,7 @@ filter_read (mu_stream_t stream, char *buf, size_t size, size_t *pret)
return MU_ERR_FAILURE; /* FIXME: special error code? */
if (iobuf.eof)
{
stream->flags |= _MU_STR_EOF;
_mu_stream_seteof (stream);
stop = 1;
}
break;
......
......@@ -32,6 +32,22 @@
#include <mailutils/stream.h>
#include <mailutils/sys/stream.h>
static void
_stream_setflag (struct _mu_stream *stream, int flag)
{
if (stream->event_cb && (stream->event_mask & flag))
stream->event_cb (stream, _MU_STR_EVENT_SET, flag);
stream->flags |= flag;
}
static void
_stream_clrflag (struct _mu_stream *stream, int flag)
{
if (stream->event_cb && (stream->event_mask & flag))
stream->event_cb (stream, _MU_STR_EVENT_CLR, flag);
stream->flags &= ~flag;
}
int
mu_stream_seterr (struct _mu_stream *stream, int code, int perm)
{
......@@ -45,12 +61,23 @@ mu_stream_seterr (struct _mu_stream *stream, int code, int perm)
default:
if (perm)
stream->flags |= _MU_STR_ERR;
_stream_setflag (stream, _MU_STR_ERR);
}
return code;
}
#define _stream_cleareof(s) ((s)->flags &= ~_MU_STR_EOF)
void
_mu_stream_cleareof (mu_stream_t str)
{
_stream_clrflag (str, _MU_STR_EOF);
}
void
_mu_stream_seteof (mu_stream_t str)
{
_stream_setflag (str, _MU_STR_EOF);
}
#define _stream_advance_buffer(s,n) ((s)->cur += n, (s)->level -= n)
#define _stream_buffer_offset(s) ((s)->cur - (s)->buffer)
#define _stream_orig_level(s) ((s)->level + _stream_buffer_offset (s))
......@@ -82,9 +109,13 @@ _stream_fill_buffer (struct _mu_stream *stream)
for (n = 0;
n < stream->bufsize
&& (rc = mu_stream_read_unbuffered (stream,
&c, 1, 0, &rdn)) == 0
&& rdn; )
&c, 1, 0, &rdn)) == 0;)
{
if (rdn == 0)
{
_stream_setflag (stream, _MU_STR_EOF);
break;
}
stream->buffer[n++] = c;
if (c == '\n')
break;
......@@ -175,7 +206,7 @@ _stream_flush_buffer (struct _mu_stream *stream, int all)
}
else
{
stream->flags &= ~_MU_STR_DIRTY;
_stream_clrflag (stream, _MU_STR_DIRTY);
stream->level = 0;
}
stream->cur = stream->buffer;
......@@ -269,7 +300,7 @@ void
mu_stream_clearerr (mu_stream_t stream)
{
stream->last_err = 0;
stream->flags &= ~_MU_STR_ERR;
_stream_clrflag (stream, _MU_STR_ERR);
}
int
......@@ -327,7 +358,7 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence,
return rc;
if (rc)
return mu_stream_seterr (stream, rc, 1);
_stream_cleareof (stream);
_mu_stream_cleareof (stream);
}
if (pres)
......@@ -469,7 +500,7 @@ mu_stream_read_unbuffered (mu_stream_t stream, void *buf, size_t size,
{
if (rdbytes == 0)
{
stream->flags |= _MU_STR_EOF;
_stream_setflag (stream, _MU_STR_EOF);
break;
}
buf += rdbytes;
......@@ -487,7 +518,7 @@ mu_stream_read_unbuffered (mu_stream_t stream, void *buf, size_t size,
if (rc == 0)
{
if (nread == 0)
stream->flags |= _MU_STR_EOF;
_stream_setflag (stream, _MU_STR_EOF);
stream->bytes_in += nread;
}
mu_stream_seterr (stream, rc, rc != 0);
......@@ -551,7 +582,7 @@ mu_stream_write_unbuffered (mu_stream_t stream,
if (rc == 0)
stream->bytes_out += nwritten;
}
stream->flags |= _MU_STR_WRT;
_stream_setflag (stream, _MU_STR_WRT);
stream->offset += nwritten;
if (pnwritten)
*pnwritten = nwritten;
......@@ -806,7 +837,7 @@ mu_stream_write (mu_stream_t stream, const void *buf, size_t size,
nbytes += n;
bufp += n;
size -= n;
stream->flags |= _MU_STR_DIRTY;
_stream_setflag (stream, _MU_STR_DIRTY);
}
if (pnwritten)
*pnwritten = nbytes;
......@@ -835,7 +866,7 @@ mu_stream_flush (mu_stream_t stream)
return rc;
if ((stream->flags & _MU_STR_WRT) && stream->flush)
return stream->flush (stream);
stream->flags &= ~_MU_STR_WRT;
_stream_clrflag (stream, _MU_STR_WRT);
return 0;
}
......