Commit 78d43b05 78d43b05bf6dfd37b5f251715211f48f3f22fb58 by Sergey Poznyakoff

Begin imap client implementation.

* include/mailutils/imap.h: New file.
* include/mailutils/Makefile.am (pkginclude_HEADERS): Add imap.h

* libproto/imap/capability.c: New file.
* libproto/imap/capatst.c: New file.
* libproto/imap/carrier.c: New file.
* libproto/imap/connect.c: New file.
* libproto/imap/create.c: New file.
* libproto/imap/destroy.c: New file.
* libproto/imap/disconnect.c: New file.
* libproto/imap/err.c: New file.
* libproto/imap/fake-folder.c: New file.
* libproto/imap/logout.c: New file.
* libproto/imap/response.c: New file.
* libproto/imap/state.c: New file.
* libproto/imap/tag.c: New file.
* libproto/imap/trace.c: New file.
* libproto/imap/Makefile.am (libmu_imap_la_SOURCES): Temporarly
remove folder.c, mbox.c and url.c. Add new files.

* mu/getarg.c: New file.
* mu/imap.c: New file.
* mu/verbose.c: New file.
* mu/Makefile.am (IDLE_MODULES): New variable.
(IMAP_C): New variable.
(MODULES): Add $(IMAP_C).
(mu_SOURCES): Add getarg.c and verbose.c
(mu-setup.h, mu-setup.c): Add IDLE_MODULES both to the dependencies
and to the mu-setup.awk command line.
* mu/mu-setup.awk: New keyword mu-cond.
* mu/pop.c: Add mu-cond keyword.

* include/mailutils/sys/imap.h: Rewrite.
* include/mailutils/sys/pop3.h (MU_POP3_CHECK_EAGAIN): Take into
account MU_ERR_REPLY and MU_ERR_BADREPLY, which are recoverable errors.

* libmailutils/base/list.c (mu_list_clear): Return immediately if
list is NULL.
* libmu_auth/sql.c (sql_escape_string): Remove unused variable.

* libproto/pop/pop3_carrier.c (mu_pop3_get_carrier): Increase refcount
on the returned stream.
* libproto/pop/pop3_response.c (mu_pop3_response): Check POP3 reply code.
1 parent 966a860c
......@@ -52,6 +52,7 @@ pkginclude_HEADERS = \
gsasl.h\
guile.h\
header.h\
imap.h\
io.h\
iterator.h\
kwd.h\
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 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, see
<http://www.gnu.org/licenses/>. */
#ifndef _MAILUTILS_IMAP_H
#define _MAILUTILS_IMAP_H
#include <mailutils/iterator.h>
#include <mailutils/debug.h>
#include <mailutils/stream.h>
#ifdef __cplusplus
extern "C" {
#endif
#define MU_IMAP_DEFAULT_PORT 143
#define MU_IMAP_DEFAULT_SSL_PORT 993
typedef struct _mu_imap *mu_imap_t;
enum mu_imap_state
{
MU_IMAP_STATE_INIT, /* Initial state */
MU_IMAP_STATE_NONAUTH, /* Non-Authenticated State */
MU_IMAP_STATE_AUTH, /* Authenticated State */
MU_IMAP_STATE_SELECTED, /* Selected State */
MU_IMAP_STATE_LOGOUT /* Logout State */
};
int mu_imap_create (mu_imap_t *pimap);
void mu_imap_destroy (mu_imap_t *pimap);
int mu_imap_connect (mu_imap_t imap);
int mu_imap_disconnect (mu_imap_t imap);
int mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t *piter);
int mu_imap_capability_test (mu_imap_t imap, const char *name,
const char **pret);
int mu_imap_logout (mu_imap_t imap);
int mu_imap_set_carrier (mu_imap_t imap, mu_stream_t carrier);
int mu_imap_get_carrier (mu_imap_t imap, mu_stream_t *pcarrier);
#define MU_IMAP_TRACE_CLR 0
#define MU_IMAP_TRACE_SET 1
#define MU_IMAP_TRACE_QRY 2
int mu_imap_trace (mu_imap_t imap, int op);
int mu_imap_trace_mask (mu_imap_t imap, int op, int lev);
int mu_imap_strerror (mu_imap_t imap, const char **pstr);
int mu_imap_state (mu_imap_t imap, int *pstate);
int mu_imap_state_str (int state, const char **pstr);
int mu_imap_tag (mu_imap_t imap, const char **pseq);
#ifdef __cplusplus
}
#endif
#endif /* _MAILUTILS_IMAP_H */
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2005, 2007, 2009, 2010 Free Software
Foundation, Inc.
Copyright (C) 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
......@@ -13,7 +12,7 @@
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, see
Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#ifndef _MAILUTILS_SYS_IMAP_H
......@@ -23,211 +22,120 @@
# include <mailutils/sys/mailbox.h>
# include <mailutils/sys/registrar.h>
# include <mailutils/sys/auth.h>
# include <mailutils/imap.h>
# ifdef __cplusplus
extern "C" {
# endif
# define CLEAR_STATE(f_imap) \
f_imap->selected = NULL, f_imap->state = IMAP_NO_STATE
/* Clear the state and close the stream. */
# define CHECK_ERROR_CLOSE(folder, f_imap, status) \
do \
{ \
if (status != 0) \
{ \
mu_stream_close (folder->stream); \
CLEAR_STATE (f_imap); \
return status; \
} \
} \
while (0)
#define MU_IMAP_RESP 0x01
#define MU_IMAP_TRACE 0x02
#define MU_IMAP_XSCRIPT_MASK(n) (1<<((n)+1))
enum mu_imap_client_state
{
MU_IMAP_NO_STATE,
MU_IMAP_ERROR,
MU_IMAP_CONNECT,
MU_IMAP_GREETINGS,
MU_IMAP_CONNECTED,
MU_IMAP_CAPABILITY_RX,
MU_IMAP_LOGOUT_RX,
};
enum mu_imap_response
{
MU_IMAP_OK,
MU_IMAP_NO,
MU_IMAP_BAD
};
struct _mu_imap
{
int flags;
/* Holds the tagged response to the last command */
char *tagbuf;
size_t tagsize;
enum mu_imap_response resp_code;
/* Untagged responses */
mu_list_t untagged_resp;
/* Error string (if any) */
char *errstr;
size_t errsize;
/* Input line buffer */
char *rdbuf;
size_t rdsize;
enum mu_imap_state state;
enum mu_imap_state imap_state;
/* Tag */
size_t tag_len; /* Length of the command tag */
int *tag_buf; /* Tag number (BCD) */
char *tag_str; /* String representation (tag_len + 1 bytes, asciiz) */
mu_list_t capa;
mu_stream_t carrier;
};
#define MU_IMAP_FSET(p,f) ((p)->flags |= (f))
#define MU_IMAP_FISSET(p,f) ((p)->flags & (f))
#define MU_IMAP_FCLR(p,f) ((p)->flags &= ~(f))
/* Clear the state. */
# define CHECK_ERROR(f_imap, status) \
int _mu_imap_init (mu_imap_t imap);
int _mu_imap_trace_enable (mu_imap_t imap);
int _mu_imap_trace_disable (mu_imap_t imap);
int _mu_imap_xscript_level (mu_imap_t imap, int xlev);
/* If status indicates an error, return.
*/
#define MU_IMAP_CHECK_ERROR(imap, status) \
do \
{ \
if (status != 0) \
{ \
CLEAR_STATE (f_imap); \
imap->state = MU_IMAP_ERROR; \
return status; \
} \
} \
while (0)
while (0)
/* Clear the state for non recoverable error. */
# define CHECK_EAGAIN(f_imap, status) \
/* Check if status indicates an error.
If the error is recoverable just return the status.
Otherwise, set the error state and return the status
*/
#define MU_IMAP_CHECK_EAGAIN(imap, status) \
do \
{ \
if (status != 0) \
{ \
if (status != EAGAIN && status != EINPROGRESS && status != EINTR) \
{ \
CLEAR_STATE (f_imap); \
} \
return status; \
} \
} \
switch (status) \
{ \
case 0: \
break; \
case EAGAIN: \
case EINPROGRESS: \
case EINTR: \
case MU_ERR_REPLY: \
case MU_ERR_BADREPLY: \
return status; \
default: \
imap->state = MU_IMAP_ERROR; \
return status; \
} \
} \
while (0)
struct _f_imap;
struct _m_imap;
struct _msg_imap;
typedef struct _f_imap *f_imap_t;
typedef struct _m_imap *m_imap_t;
typedef struct _msg_imap *msg_imap_t;
enum imap_state
{
IMAP_NO_STATE=0,
IMAP_AUTH, IMAP_AUTH_DONE,
IMAP_APPEND, IMAP_APPEND_CONT, IMAP_APPEND_SEND, IMAP_APPEND_ACK,
IMAP_BODY,
IMAP_CLOSE, IMAP_CLOSE_ACK,
IMAP_COPY, IMAP_COPY_ACK,
IMAP_CREATE, IMAP_CREATE_ACK,
IMAP_DELETE, IMAP_DELETE_ACK,
IMAP_EXPUNGE, IMAP_EXPUNGE_ACK,
IMAP_FETCH, IMAP_FETCH_ACK,
IMAP_GREETINGS,
IMAP_HEADER,
IMAP_HEADER_FIELD,
IMAP_LIST, IMAP_LIST_PARSE, IMAP_LIST_ACK,
IMAP_LOGIN, IMAP_LOGIN_ACK,
IMAP_LOGOUT, IMAP_LOGOUT_ACK,
IMAP_LSUB, IMAP_LSUB_ACK,
IMAP_MESSAGE,
IMAP_NOOP, IMAP_NOOP_ACK,
IMAP_OPEN_CONNECTION,
IMAP_RENAME, IMAP_RENAME_ACK,
IMAP_SCAN, IMAP_SCAN_ACK,
IMAP_SELECT, IMAP_SELECT_ACK,
IMAP_STORE, IMAP_STORE_ACK,
IMAP_SUBSCRIBE, IMAP_SUBSCRIBE_ACK,
IMAP_UNSUBSCRIBE, IMAP_UNSUBSCRIBE_ACK
};
int _mu_imap_seterrstr (mu_imap_t imap, const char *str, size_t len);
void _mu_imap_clrerrstr (mu_imap_t imap);
enum imap_auth_state
{
/* ANONYMOUS */
IMAP_AUTH_ANON_REQ_WRITE,
IMAP_AUTH_ANON_REQ_SEND,
IMAP_AUTH_ANON_WAIT_CONT,
IMAP_AUTH_ANON_MSG,
IMAP_AUTH_ANON_MSG_SEND,
IMAP_AUTH_ANON_WAIT_RESP
};
struct literal_string
{
char *buffer;
size_t buflen;
size_t total;
msg_imap_t msg_imap;
enum imap_state type;
size_t nleft; /* nleft to read in the literal. */
};
struct _f_imap
{
/* Back pointer. */
mu_folder_t folder;
m_imap_t selected;
int _mu_imap_tag_next (mu_imap_t imap);
int _mu_imap_tag_clr (mu_imap_t imap);
enum imap_state state;
int imaps; /* IMAPS or IMAP? */
size_t seq; /* Sequence number to build a tag. */
char **capav; /* Cabilities of the server. */
int capac; /* Number of capabilities in the above array */
int flags;
/* IO use to hold the literal and quoted strings send by
the IMAP server. */
struct
{
mu_stream_t stream;
mu_off_t offset;
size_t nleft; /* nleft to read in the literal. */
msg_imap_t msg_imap;
enum imap_state type;
} string;
/* Use for LIST and LSUB. */
mu_list_t flist;
mu_folder_enumerate_fp enum_fun;
void *enum_data;
int enum_stop;
int _mu_imap_response (mu_imap_t imap);
int isopen;
/* Server channel buffer I/O */
size_t buflen;
char *buffer;
char *ptr;
char *nl;
mu_off_t offset; /* Dummy, this is used because of the stream buffering.
The mu_stream_t maintains and offset and the offset we
use must be in sync. */
/* Login */
char *user;
mu_secret_t secret;
/* AUTHENTICATE states */
enum imap_auth_state auth_state;
};
struct _m_imap
{
/* Back pointers. */
mu_mailbox_t mailbox;
f_imap_t f_imap;
size_t messages_count;
size_t imessages_count;
msg_imap_t *imessages;
size_t recent;
size_t unseen;
unsigned long uidvalidity;
size_t uidnext;
char *name;
enum imap_state state;
/* mailbox operations can be sequences of folder operations, and
thus need to keep meta-state, mailbox_imap_open(), for example. */
};
struct _msg_imap
{
/* Back pointers. */
mu_message_t message;
m_imap_t m_imap;
size_t num;
size_t part;
size_t num_parts;
msg_imap_t *parts;
msg_imap_t parent;
int flags;
size_t uid;
mu_header_t fheader;
char *internal_date;
size_t mu_message_size;
size_t mu_message_lines;
size_t body_size;
size_t body_lines;
size_t header_size;
size_t header_lines;
};
int imap_writeline (f_imap_t, const char *format, ...) MU_PRINTFLIKE(2,3);
int imap_write (f_imap_t);
int imap_send (f_imap_t);
int imap_parse (f_imap_t);
int imap_readline (f_imap_t);
char *section_name (msg_imap_t);
# ifdef __cplusplus
}
# endif
......
......@@ -93,28 +93,31 @@ int _mu_pop3_trace_disable (mu_pop3_t pop3);
int _mu_pop3_init (mu_pop3_t pop3);
/* Check for non recoverable error.
The error is consider not recoverable if not part of the signal set:
EAGAIN, EINPROGRESS, EINTR.
For unrecoverable error we reset, by moving the working ptr
to the begining of the buffer and setting the state to error.
/* Check if status indicates an error.
If the error is recoverable just return the status.
Otherwise, set the error state and return the status
*/
#define MU_POP3_CHECK_EAGAIN(pop3, status) \
do \
{ \
if (status != 0) \
{ \
if (status != EAGAIN && status != EINPROGRESS && status != EINTR) \
{ \
pop3->state = MU_POP3_ERROR; \
} \
return status; \
} \
} \
switch (status) \
{ \
case 0: \
break; \
case EAGAIN: \
case EINPROGRESS: \
case EINTR: \
case MU_ERR_REPLY: \
case MU_ERR_BADREPLY: \
return status; \
default: \
pop3->state = MU_POP3_ERROR; \
return status; \
} \
} \
while (0)
/* If error return.
Check status an reset(see MU_POP2_CHECK_EAGAIN) the buffer.
/* If status indicates an error, return.
*/
#define MU_POP3_CHECK_ERROR(pop3, status) \
do \
......
......@@ -64,7 +64,9 @@ mu_list_clear (mu_list_t list)
{
struct list_data *current;
struct list_data *previous;
if (!list)
return;
mu_monitor_wrlock (list->monitor);
for (current = list->head.next; current != &list->head;)
{
......
......@@ -88,7 +88,6 @@ sql_escape_string (const char *ustr)
char *
mu_sql_expand_query (const char *query, const char *ustr)
{
int rc;
char *res;
char *esc_ustr;
struct mu_wordsplit ws;
......
......@@ -13,7 +13,7 @@
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
## along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
INCLUDES = @MU_LIB_COMMON_INCLUDES@
......@@ -21,8 +21,24 @@ lib_LTLIBRARIES = libmu_imap.la
libmu_imap_la_LDFLAGS=-version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@
libmu_imap_la_LIBADD = ${MU_LIB_AUTH} ${MU_LIB_MAILUTILS} @INTLLIBS@
# FIXME: Put these back when ready
# folder.c\
# mbox.c\
# url.c
libmu_imap_la_SOURCES = \
folder.c\
mbox.c\
url.c
fake-folder.c\
capability.c\
capatst.c\
carrier.c\
connect.c\
create.c\
destroy.c\
disconnect.c\
err.c\
logout.c\
response.c\
state.c\
tag.c\
trace.c
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 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, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <mailutils/types.h>
#include <mailutils/cctype.h>
#include <mailutils/cstr.h>
#include <mailutils/errno.h>
#include <mailutils/stream.h>
#include <mailutils/list.h>
#include <mailutils/wordsplit.h>
#include <mailutils/sys/imap.h>
static int
capa_comp (const void *item, const void *value)
{
const char *capa = item;
const char *needle = value;
for (; *needle; capa++, needle++)
{
if (!*capa)
return 1;
if (mu_tolower (*capa) != mu_tolower (*needle))
return 1;
}
return !(*capa == 0 || *capa == '=');
}
int
mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t *piter)
{
int status;
if (imap == NULL)
return EINVAL;
if (!imap->carrier)
return MU_ERR_NO_TRANSPORT;
if (imap->state != MU_IMAP_CONNECTED)
return MU_ERR_SEQ;
if (imap->capa)
{
if (!reread)
{
if (!piter)
return 0;
return mu_list_get_iterator (imap->capa, piter);
}
mu_list_clear (imap->capa);
}
else
{
status = mu_list_create (&imap->capa);
MU_IMAP_CHECK_ERROR (imap, status);
mu_list_set_comparator (imap->capa, capa_comp);
mu_list_set_destroy_item (imap->capa, mu_list_free_item);
}
switch (imap->state)
{
case MU_IMAP_CONNECTED:
status = _mu_imap_tag_next (imap);
MU_IMAP_CHECK_EAGAIN (imap, status);
status = mu_stream_printf (imap->carrier, "%s CAPABILITY\r\n",
imap->tag_str);
MU_IMAP_CHECK_EAGAIN (imap, status);
imap->state = MU_IMAP_CAPABILITY_RX;
case MU_IMAP_CAPABILITY_RX:
status = _mu_imap_response (imap);
MU_IMAP_CHECK_EAGAIN (imap, status);
if (imap->resp_code != MU_IMAP_OK)
return MU_ERR_REPLY;
else
{
size_t count;
char *str;
imap->state = MU_IMAP_CONNECTED;
mu_list_count (imap->untagged_resp, &count);
if (mu_list_get (imap->untagged_resp, 0, (void*)&str) == 0)
{
size_t i;
struct mu_wordsplit ws;
if (mu_wordsplit (str, &ws,
MU_WRDSF_NOVAR | MU_WRDSF_NOCMD |
MU_WRDSF_SQUEEZE_DELIMS))
{
int ec = errno;
mu_error ("mu_imap_capability: cannot split line: %s",
mu_wordsplit_strerror (&ws));
return ec;
}
if (ws.ws_wordc > 1 &&
mu_c_strcasecmp (ws.ws_wordv[0], "CAPABILITY") == 0)
{
for (i = 1; i < ws.ws_wordc; i++)
{
mu_list_append (imap->capa, ws.ws_wordv[i]);
ws.ws_wordv[i] = NULL;
}
}
mu_wordsplit_free (&ws);
}
if (piter)
status = mu_list_get_iterator (imap->capa, piter);
else
status = 0;
}
break;
case MU_IMAP_ERROR:
status = ECANCELED;
break;
default:
status = EINPROGRESS;
}
return status;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 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, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <mailutils/types.h>
#include <mailutils/list.h>
#include <mailutils/sys/imap.h>
int
mu_imap_capability_test (mu_imap_t imap, const char *name, const char **pret)
{
int rc;
rc = mu_imap_capability (imap, 0, NULL);
if (rc)
return rc;
return mu_list_locate (imap->capa, (void*) name, (void**)pret);
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 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, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <mailutils/errno.h>
#include <mailutils/sys/imap.h>
int
mu_imap_set_carrier (mu_imap_t imap, mu_stream_t carrier)
{
/* Sanity checks. */
if (imap == NULL)
return EINVAL;
if (imap->carrier)
{
/* Close any old carrier. */
mu_imap_disconnect (imap);
mu_stream_destroy (&imap->carrier);
}
mu_stream_ref (carrier);
imap->carrier = carrier;
if (MU_IMAP_FISSET (imap, MU_IMAP_TRACE))
_mu_imap_trace_enable (imap);
imap->state = MU_IMAP_CONNECT;
return 0;
}
int
mu_imap_get_carrier (mu_imap_t imap, mu_stream_t *pcarrier)
{
/* Sanity checks. */
if (imap == NULL)
return EINVAL;
if (pcarrier == NULL)
return MU_ERR_OUT_PTR_NULL;
mu_stream_ref (imap->carrier);
*pcarrier = imap->carrier;
return 0;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 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, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <mailutils/errno.h>
#include <mailutils/wordsplit.h>
#include <mailutils/sys/imap.h>
int
mu_imap_connect (mu_imap_t imap)
{
int status;
if (imap == NULL)
return EINVAL;
if (imap->carrier == NULL)
return EINVAL;
switch (imap->state)
{
default:
case MU_IMAP_NO_STATE:
status = mu_imap_disconnect (imap);
if (status != 0)
{
/* Sleep for 2 seconds (FIXME: Must be configurable) */
struct timeval tval;
tval.tv_sec = 2;
tval.tv_usec = 0;
select (0, NULL, NULL, NULL, &tval);
}
imap->state = MU_IMAP_CONNECT;
case MU_IMAP_CONNECT:
/* Establish the connection. */
if (!mu_stream_is_open (imap->carrier))
{
status = mu_stream_open (imap->carrier);
MU_IMAP_CHECK_EAGAIN (imap, status);
MU_IMAP_FCLR (imap, MU_IMAP_RESP);
}
imap->state = MU_IMAP_GREETINGS;
case MU_IMAP_GREETINGS:
status = mu_stream_getline (imap->carrier, &imap->rdbuf,
&imap->rdsize, NULL);
MU_IMAP_CHECK_EAGAIN (imap, status);
if (imap->rdsize < 2 ||
!(imap->rdbuf[0] == '*' && imap->rdbuf[1] == ' '))
{
mu_error ("mu_imap_connect: invalid server response: %s",
imap->rdbuf);
imap->state = MU_IMAP_ERROR;
return MU_ERR_BADREPLY;
}
else
{
struct mu_wordsplit ws;
if (mu_wordsplit (imap->rdbuf, &ws,
MU_WRDSF_NOVAR | MU_WRDSF_NOCMD |
MU_WRDSF_SQUEEZE_DELIMS))
{
int ec = errno;
mu_error ("mu_imap_connect: cannot split line: %s",
mu_wordsplit_strerror (&ws));
imap->state = MU_IMAP_ERROR;
return ec;
}
if (ws.ws_wordc < 2)
status = MU_ERR_BADREPLY;
else if (strcmp (ws.ws_wordv[1], "BYE") == 0)
{
status = EACCES;
_mu_imap_seterrstr (imap, imap->rdbuf + 2,
strlen (imap->rdbuf + 2));
}
else if (strcmp (ws.ws_wordv[1], "PREAUTH") == 0)
{
status = 0;
imap->state = MU_IMAP_CONNECTED;
imap->imap_state = MU_IMAP_STATE_AUTH;
}
else if (strcmp (ws.ws_wordv[1], "OK") == 0)
{
status = 0;
imap->state = MU_IMAP_CONNECTED;
imap->imap_state = MU_IMAP_STATE_NONAUTH;
}
else
{
status = MU_ERR_BADREPLY;
imap->state = MU_IMAP_ERROR;
}
mu_wordsplit_free (&ws);
}
}
return status;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 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, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <errno.h>
#include <mailutils/errno.h>
#include <mailutils/sys/imap.h>
#include <mailutils/list.h>
int
mu_imap_create (mu_imap_t *pimap)
{
mu_imap_t imap;
/* Sanity check. */
if (pimap == NULL)
return EINVAL;
imap = calloc (1, sizeof *imap);
if (imap == NULL)
return ENOMEM;
_mu_imap_init (imap);
*pimap = imap;
return 0;
}
int
_mu_imap_init (mu_imap_t imap)
{
if (imap == NULL)
return EINVAL;
if (imap->carrier == 0)
{
int rc;
if (imap->untagged_resp)
mu_list_clear (imap->untagged_resp);
mu_list_destroy (&imap->capa);
_mu_imap_clrerrstr (imap);
rc = _mu_imap_tag_clr (imap);
imap->flags = 0;
if (rc)
return rc;
}
imap->state = MU_IMAP_NO_STATE; /* Init with no state. */
return 0;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 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, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <mailutils/errno.h>
#include <mailutils/sys/imap.h>
#include <mailutils/list.h>
void
mu_imap_destroy (mu_imap_t *pimap)
{
if (pimap && *pimap)
{
mu_imap_t imap = *pimap;
/* Free the response buffer. */
if (imap->tagbuf)
free (imap->tagbuf);
/* Free the read buffer. */
if (imap->rdbuf)
free (imap->rdbuf);
if (imap->errstr)
free (imap->errstr);
if (imap->tag_str)
free (imap->tag_str);
if (imap->tag_buf)
free (imap->tag_buf);
mu_list_destroy (&imap->untagged_resp);
mu_list_destroy (&imap->capa);
mu_stream_destroy (&imap->carrier);
free (imap);
*pimap = NULL;
}
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 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, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <mailutils/sys/imap.h>
int
mu_imap_disconnect (mu_imap_t imap)
{
/* Sanity checks. */
if (imap == NULL)
return EINVAL;
imap->state = MU_IMAP_NO_STATE;
MU_IMAP_FCLR (imap, MU_IMAP_RESP);
if (imap->rdbuf)
imap->rdbuf[0] = 0;
mu_list_clear (imap->untagged_resp);
mu_list_clear (imap->capa);
/* Close the stream. */
if (mu_stream_is_open (imap->carrier))
return mu_stream_close (imap->carrier);
return 0;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 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, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <mailutils/errno.h>
#include <mailutils/sys/imap.h>
int
_mu_imap_seterrstr (mu_imap_t imap, const char *str, size_t len)
{
if (len + 1 > imap->errsize)
{
char *p = realloc (imap->errstr, len + 1);
if (!p)
return ENOMEM;
imap->errsize = len + 1;
}
memcpy (imap->errstr, str, len);
imap->errstr[len] = 0;
return 0;
}
void
_mu_imap_clrerrstr (mu_imap_t imap)
{
if (imap->errstr)
imap->errstr[0] = 0;
}
int
mu_imap_strerror (mu_imap_t imap, const char **pstr)
{
if (imap->errstr)
{
*pstr = imap->errstr;
return 0;
}
*pstr = "(no error)";
return MU_ERR_NOENT;
}
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <mailutils/mailutils.h>
mu_record_t mu_imap_record = NULL;
mu_record_t mu_imaps_record = NULL;
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 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, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <mailutils/errno.h>
#include <mailutils/stream.h>
#include <mailutils/sys/imap.h>
int
mu_imap_logout (mu_imap_t imap)
{
int status;
if (imap == NULL)
return EINVAL;
if (!imap->carrier)
return MU_ERR_NO_TRANSPORT;
if (imap->state != MU_IMAP_CONNECTED)
return MU_ERR_SEQ;
switch (imap->state)
{
case MU_IMAP_CONNECTED:
status = _mu_imap_tag_next (imap);
MU_IMAP_CHECK_EAGAIN (imap, status);
status = mu_stream_printf (imap->carrier, "%s LOGOUT\r\n",
imap->tag_str);
MU_IMAP_CHECK_EAGAIN (imap, status);
imap->state = MU_IMAP_LOGOUT_RX;
case MU_IMAP_LOGOUT_RX:
status = _mu_imap_response (imap);
MU_IMAP_CHECK_EAGAIN (imap, status);
imap->state = MU_IMAP_NO_STATE;
imap->imap_state = MU_IMAP_STATE_LOGOUT;
break;
default:
status = EINPROGRESS;
}
return status;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 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, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <mailutils/cctype.h>
#include <mailutils/cstr.h>
#include <mailutils/stream.h>
#include <mailutils/errno.h>
#include <mailutils/sys/imap.h>
#define IS_PREFIX(s, len, pfx) \
((len) >= sizeof (pfx) - 1 && \
memcmp ((s), (pfx), sizeof (pfx) - 1) == 0 && \
s[sizeof (pfx) - 1] == ' ')
int
_mu_imap_response (mu_imap_t imap)
{
size_t n = 0;
int status = 0;
if (imap == NULL)
return EINVAL;
if (MU_IMAP_FISSET (imap, MU_IMAP_RESP))
return 0;
_mu_imap_clrerrstr (imap);
if (imap->untagged_resp)
mu_list_clear (imap->untagged_resp);
else
{
status = mu_list_create (&imap->untagged_resp);
MU_IMAP_CHECK_ERROR (imap, status);
mu_list_set_destroy_item (imap->untagged_resp, mu_list_free_item);
}
while (1)
{
status = mu_stream_getline (imap->carrier, &imap->rdbuf,
&imap->rdsize, NULL);
if (status == 0)
{
n = mu_rtrim_class (imap->rdbuf, MU_CTYPE_SPACE);
if (imap->rdbuf[0] == '*' && imap->rdbuf[1] == ' ')
{
char *p = mu_str_skip_cset (imap->rdbuf + 2, " ");
mu_list_append (imap->untagged_resp, strdup (p));
}
else if (n > imap->tag_len + 3 &&
memcmp (imap->rdbuf, imap->tag_str, imap->tag_len) == 0
&& imap->rdbuf[imap->tag_len] == ' ')
{
char *p = mu_str_skip_cset (imap->rdbuf + imap->tag_len, " ");
size_t len = strlen (p);
if (len >= imap->tagsize)
{
char *np = realloc (imap->tagbuf, len + 1);
if (!np)
{
imap->state = MU_IMAP_ERROR;
return ENOMEM;
}
imap->tagsize = len + 1;
imap->tagbuf = np;
}
strcpy (imap->tagbuf, p);
if (IS_PREFIX(p, len, "OK"))
imap->resp_code = MU_IMAP_OK;
else if (IS_PREFIX(p, len, "NO"))
imap->resp_code = MU_IMAP_NO;
else if (IS_PREFIX(p, len, "BAD"))
imap->resp_code = MU_IMAP_BAD;
else
status = MU_ERR_BADREPLY;
MU_IMAP_FSET (imap, MU_IMAP_RESP);
break;
}
else
{
imap->state = MU_IMAP_ERROR;
return MU_ERR_BADREPLY;
}
}
else
{
imap->state = MU_IMAP_ERROR;
return status;
}
}
return status;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 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, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <errno.h>
#include <mailutils/nls.h>
#include <mailutils/sys/imap.h>
const char *_mu_imap_state_name[] = {
N_("initial"),
N_("non-authenticated"),
N_("authenticated"),
N_("selected"),
N_("logout")
};
int _mu_imap_state_count = MU_ARRAY_SIZE (_mu_imap_state_name);
int
mu_imap_state (mu_imap_t imap, int *pstate)
{
if (imap == NULL || pstate == NULL)
return EINVAL;
*pstate = imap->imap_state;
return 0;
}
int
mu_imap_state_str (int state, const char **pstr)
{
if (state < 0 || state >= _mu_imap_state_count)
return EINVAL;
*pstr = gettext (_mu_imap_state_name[state]);
return 0;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 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, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <errno.h>
#include <mailutils/sys/imap.h>
static int
_mu_imap_tag_incr (mu_imap_t imap)
{
int i = 0;
while (1)
{
if (++imap->tag_buf[i] <= 9)
break;
imap->tag_buf[i] = 0;
if (++i == imap->tag_len)
{
char *sp;
int *np = realloc (imap->tag_buf, imap->tag_len + 1);
if (!np)
return ENOMEM;
imap->tag_buf = np;
sp = realloc (imap->tag_str, imap->tag_len + 2);
if (!sp)
return ENOMEM;
imap->tag_str = sp;
imap->tag_len++;
}
}
return 0;
}
static void
_mu_imap_tag_print (mu_imap_t imap)
{
int i;
for (i = 0; i < imap->tag_len; i++)
imap->tag_str[imap->tag_len-i-1] = imap->tag_buf[i] + '0';
imap->tag_str[i] = 0;
}
int
_mu_imap_tag_clr (mu_imap_t imap)
{
int i;
if (imap->tag_len == 0)
{
imap->tag_len = 2;
imap->tag_buf = calloc (imap->tag_len, sizeof (imap->tag_buf[0]));
if (!imap->tag_buf)
return ENOMEM;
imap->tag_str = calloc (imap->tag_len + 1, sizeof (imap->tag_str[0]));
if (!imap->tag_str)
{
free (imap->tag_buf);
return ENOMEM;
}
}
for (i = 0; i < imap->tag_len; i++)
imap->tag_buf[i] = 0;
_mu_imap_tag_print (imap);
return 0;
}
int
_mu_imap_tag_next (mu_imap_t imap)
{
int status;
status = _mu_imap_tag_incr (imap);
if (status == 0)
_mu_imap_tag_print (imap);
return status;
}
int
mu_imap_tag (mu_imap_t imap, const char **ptag)
{
if (!imap)
return EINVAL;
*ptag = imap->tag_str;
return 0;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 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, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <mailutils/error.h>
#include <mailutils/errno.h>
#include <mailutils/nls.h>
#include <mailutils/stream.h>
#include <mailutils/sys/imap.h>
static const char *imap_prefix[] = {
"S: ", "C: "
};
int
_mu_imap_trace_enable (mu_imap_t imap)
{
int rc = 0;
mu_debug_t debug;
mu_stream_t dstr, xstr;
if (!imap->carrier)
{
MU_IMAP_FSET (imap, MU_IMAP_TRACE);
return 0;
}
mu_diag_get_debug (&debug);
rc = mu_dbgstream_create (&dstr, debug, MU_DIAG_DEBUG, 0);
if (rc)
mu_error (_("cannot create debug stream; transcript disabled: %s"),
mu_strerror (rc));
else
{
rc = mu_xscript_stream_create (&xstr, imap->carrier, dstr,
imap_prefix);
if (rc)
mu_error (_("cannot create transcript stream: %s"),
mu_strerror (rc));
else
{
mu_stream_unref (imap->carrier);
imap->carrier = xstr;
MU_IMAP_FSET (imap, MU_IMAP_TRACE);
}
}
return rc;
}
int
_mu_imap_trace_disable (mu_imap_t imap)
{
mu_stream_t xstr = imap->carrier;
mu_stream_t stream[2];
int rc;
if (!xstr)
return 0;
rc = mu_stream_ioctl (xstr, MU_IOCTL_GET_TRANSPORT, stream);
if (rc)
return rc;
imap->carrier = stream[0];
mu_stream_destroy (&xstr);
MU_IMAP_FCLR (imap, MU_IMAP_TRACE);
return 0;
}
int
mu_imap_trace (mu_imap_t imap, int op)
{
int trace_on = MU_IMAP_FISSET (imap, MU_IMAP_TRACE);
switch (op)
{
case MU_IMAP_TRACE_SET:
if (trace_on)
return MU_ERR_EXISTS;
return _mu_imap_trace_enable (imap);
case MU_IMAP_TRACE_CLR:
if (!trace_on)
return MU_ERR_NOENT;
return _mu_imap_trace_disable (imap);
case MU_IMAP_TRACE_QRY:
if (!trace_on)
return MU_ERR_NOENT;
return 0;
}
return EINVAL;
}
int
mu_imap_trace_mask (mu_imap_t imap, int op, int lev)
{
switch (op)
{
case MU_IMAP_TRACE_SET:
imap->flags |= MU_IMAP_XSCRIPT_MASK(lev);
break;
case MU_IMAP_TRACE_CLR:
imap->flags &= ~MU_IMAP_XSCRIPT_MASK(lev);
break;
case MU_IMAP_TRACE_QRY:
if (imap->flags & MU_IMAP_XSCRIPT_MASK(lev))
break;
return MU_ERR_NOENT;
default:
return EINVAL;
}
return 0;
}
int
_mu_imap_xscript_level (mu_imap_t imap, int xlev)
{
if (mu_stream_ioctl (imap->carrier, MU_IOCTL_LEVEL, &xlev) == 0)
return xlev;
return MU_XSCRIPT_NORMAL;
}
......@@ -13,7 +13,7 @@
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
## along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
INCLUDES = @MU_LIB_COMMON_INCLUDES@
......
......@@ -55,6 +55,7 @@ mu_pop3_get_carrier (mu_pop3_t pop3, mu_stream_t *pcarrier)
if (pcarrier == NULL)
return MU_ERR_OUT_PTR_NULL;
mu_stream_ref (pop3->carrier);
*pcarrier = pop3->carrier;
return 0;
}
......
......@@ -67,6 +67,13 @@ mu_pop3_response (mu_pop3_t pop3, size_t *pnread)
else if (pop3->ackbuf)
n = strlen (pop3->ackbuf);
if (n < 3)
status = MU_ERR_BADREPLY;
else if (strncmp (pop3->ackbuf, "-ERR", 4) == 0)
status = MU_ERR_REPLY;
else if (strncmp (pop3->ackbuf, "+OK", 3))
status = MU_ERR_BADREPLY;
if (pnread)
*pnread = n;
return status;
......
......@@ -18,16 +18,24 @@
bin_PROGRAMS = mu
dist_bin_SCRIPTS = mailutils-config
IDLE_MODULES=
if MU_COND_SUPPORT_POP
POP_C=pop.c
else
IDLE_MODULES+=pop.c
endif
EXTRA_DIST=pop.c mu-setup.h mu-setup.c mu-setup.awk
BUILT_SOURCES=mu-setup.h mu-setup.c
if MU_COND_SUPPORT_IMAP
IMAP_C=imap.c
else
IDLE_MODULES+=imap.c
endif
MODULES = \
acl.c\
cflags.c\
$(IMAP_C)\
filter.c\
flt2047.c\
help.c\
......@@ -39,9 +47,11 @@ MODULES = \
mu_SOURCES = \
dispatch.c\
getarg.c\
mu.h\
mu.c\
shell.c\
verbose.c\
$(MODULES)
mu_LDADD = \
......@@ -68,8 +78,10 @@ AM_CPPFLAGS = \
-DPYTHON_LIBS="\"$(PYTHON_LIBS)\"" \
-DI18NLIBS="\"$(LIBINTL)\""
mu-setup.h: Makefile.am $(MODULES)
$(AM_V_GEN)$(AWK) -f $(top_srcdir)/mu/mu-setup.awk -v mode=h $(MODULES) > mu-setup.h
mu-setup.h: Makefile.am $(MODULES) $(IDLE_MODULES)
$(AM_V_GEN)$(AWK) -f $(top_srcdir)/mu/mu-setup.awk -v mode=h \
$(MODULES) $(IDLE_MODULES) > mu-setup.h
mu-setup.c: Makefile.am $(MODULES)
$(AM_V_GEN)$(AWK) -f $(top_srcdir)/mu/mu-setup.awk -v mode=c $(MODULES) > mu-setup.c
$(AM_V_GEN)$(AWK) -f $(top_srcdir)/mu/mu-setup.awk -v mode=c \
$(MODULES) $(IDLE_MODULES) > mu-setup.c
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2010 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Mailutils 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 General Public License
along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
#if defined(HAVE_CONFIG_H)
# include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <mailutils/mailutils.h>
#include "mu.h"
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
return 1;
return 0;
}
int
get_port (const char *port_str, int *pn)
{
short port_num;
long num;
char *p;
num = port_num = strtol (port_str, &p, 0);
if (*p == 0)
{
if (num != port_num)
{
mu_error ("bad port number: %s", port_str);
return 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;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2010 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Mailutils 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 General Public License
along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
#if defined(HAVE_CONFIG_H)
# include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <netdb.h>
#include <mailutils/mailutils.h>
#include <mailutils/imap.h>
#include "mu.h"
#include "argp.h"
#include "xalloc.h"
static char imap_doc[] = N_("mu imap - IMAP4 client shell.");
char imap_docstring[] = N_("IMAP4 client shell");
static char imap_args_doc[] = "";
static struct argp_option imap_options[] = {
{ NULL }
};
static error_t
imap_parse_opt (int key, char *arg, struct argp_state *state)
{
switch (key)
{
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}
static struct argp imap_argp = {
imap_options,
imap_parse_opt,
imap_args_doc,
imap_doc,
NULL,
NULL,
NULL
};
static mu_imap_t imap;
static enum mu_imap_state
current_imap_state ()
{
int state;
if (imap == NULL)
state = MU_IMAP_STATE_INIT;
else
{
mu_imap_state (imap, &state);
if (state == MU_IMAP_STATE_LOGOUT)
state = MU_IMAP_STATE_INIT;
}
return state;
}
static void
imap_set_verbose ()
{
if (imap)
{
if (QRY_VERBOSE ())
mu_imap_trace (imap, MU_IMAP_TRACE_SET);
else
mu_imap_trace (imap, MU_IMAP_TRACE_CLR);
}
}
void
imap_set_verbose_mask ()
{
if (imap)
{
mu_imap_trace_mask (imap, QRY_VERBOSE_MASK (MU_XSCRIPT_SECURE)
? MU_IMAP_TRACE_SET : MU_IMAP_TRACE_CLR,
MU_XSCRIPT_SECURE);
mu_imap_trace_mask (imap, QRY_VERBOSE_MASK (MU_XSCRIPT_PAYLOAD)
? MU_IMAP_TRACE_SET : MU_IMAP_TRACE_CLR,
MU_XSCRIPT_PAYLOAD);
}
}
static int
com_verbose (int argc, char **argv)
{
return shell_verbose (argc, argv,
imap_set_verbose, imap_set_verbose_mask);
}
static int connect_argc;
static char **connect_argv;
#define host connect_argv[0]
static int port = MU_IMAP_DEFAULT_PORT;
static char *username;
static void
imap_prompt_env ()
{
enum mu_imap_state state = current_imap_state ();
if (!mutool_prompt_env)
mutool_prompt_env = xcalloc (2*7 + 1, sizeof(mutool_prompt_env[0]));
mutool_prompt_env[0] = "user";
mutool_prompt_env[1] = (state >= MU_IMAP_STATE_AUTH && username) ?
username : "[nouser]";
mutool_prompt_env[2] = "host";
mutool_prompt_env[3] = connect_argv ? host : "[nohost]";
mutool_prompt_env[4] = "program-name";
mutool_prompt_env[5] = (char*) mu_program_name;
mutool_prompt_env[6] = "canonical-program-name";
mutool_prompt_env[7] = "mu";
mutool_prompt_env[8] = "package";
mutool_prompt_env[9] = PACKAGE;
mutool_prompt_env[10] = "version";
mutool_prompt_env[11] = PACKAGE_VERSION;
mutool_prompt_env[12] = "status";
if (mu_imap_state_str (state, (const char **) &mutool_prompt_env[13]))
mutool_prompt_env[12] = NULL;
mutool_prompt_env[14] = NULL;
}
static int
com_disconnect (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
{
if (imap)
{
mu_imap_disconnect (imap);
mu_imap_destroy (&imap);
mu_argcv_free (connect_argc, connect_argv);
connect_argc = 0;
connect_argv = NULL;
imap_prompt_env ();
}
return 0;
}
static int
com_connect (int argc, char **argv)
{
int status;
int n = 0;
int tls = 0;
int i = 1;
enum mu_imap_state state;
for (i = 1; i < argc; i++)
{
if (strcmp (argv[i], "-tls") == 0)
{
if (WITH_TLS)
tls = 1;
else
{
mu_error ("TLS not supported");
return 0;
}
}
else
break;
}
argc -= i;
argv += i;
if (argc >= 2)
{
if (get_port (argv[1], &n))
return 0;
}
else if (tls)
n = MU_IMAP_DEFAULT_SSL_PORT;
else
n = MU_IMAP_DEFAULT_PORT;
state = current_imap_state ();
if (state != MU_IMAP_STATE_INIT)
com_disconnect (0, NULL);
status = mu_imap_create (&imap);
if (status == 0)
{
mu_stream_t tcp;
if (QRY_VERBOSE ())
{
imap_set_verbose ();
imap_set_verbose_mask ();
}
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_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_imap_set_carrier (imap, tcp);
status = mu_imap_connect (imap);
if (status)
{
const char *err;
mu_error ("Failed to connect: %s", mu_strerror (status));
if (mu_imap_strerror (imap, &err))
mu_error ("server response: %s", err);
mu_imap_destroy (&imap);
}
}
else
mu_imap_destroy (&imap);
}
else
mu_error ("Failed to create imap: %s", mu_strerror (status));
if (!status)
{
connect_argc = argc;
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;
imap_prompt_env ();
}
return status;
}
static int
com_logout (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
{
int status = 0;
if (imap)
{
if (mu_imap_logout (imap) == 0)
{
status = com_disconnect (0, NULL);
}
else
{
mu_stream_printf (mustrout, "Try 'exit' to leave %s\n",
mu_program_name);
}
}
else
mu_stream_printf (mustrout, "Try 'exit' to leave %s\n", mu_program_name);
return status;
}
static int
com_capability (int argc, char **argv)
{
mu_iterator_t iterator = NULL;
int status = 0;
int reread = 0;
int i = 1;
for (i = 1; i < argc; i++)
{
if (strcmp (argv[i], "-reread") == 0)
reread = 1;
else
break;
}
if (i < argc)
{
if (reread)
{
status = mu_imap_capability (imap, 1, NULL);
if (status)
return status;
}
for (; i < argc; i++)
{
const char *elt;
int rc = mu_imap_capability_test (imap, argv[i], &elt);
switch (rc)
{
case 0:
if (*elt)
mu_stream_printf (mustrout, "%s: %s\n", argv[i], elt);
else
mu_stream_printf (mustrout, "%s is set\n", argv[i]);
break;
case MU_ERR_NOENT:
mu_stream_printf (mustrout, "%s is not set\n", argv[i]);
break;
default:
return rc;
}
}
}
else
{
status = mu_imap_capability (imap, reread, &iterator);
if (status == 0)
{
for (mu_iterator_first (iterator);
!mu_iterator_is_done (iterator); mu_iterator_next (iterator))
{
char *capa = NULL;
mu_iterator_current (iterator, (void **) &capa);
mu_stream_printf (mustrout, "CAPA: %s\n", capa ? capa : "");
}
mu_iterator_destroy (&iterator);
}
}
return status;
}
struct mutool_command imap_comtab[] = {
{ "capability", 1, -1, com_capability,
/* TRANSLATORS: -reread is a keyword; do not translate. */
N_("[-reread] [NAME...]"),
N_("list server capabilities") },
{ "verbose", 1, 4, com_verbose,
"[on|off|mask|unmask] [secure [payload]]",
N_("control the protocol tracing") },
{ "connect", 1, 4, com_connect,
/* TRANSLATORS: --tls is a keyword. */
N_("[-tls] HOSTNAME [PORT]"),
N_("open connection") },
{ "disconnect", 1, 1,
com_disconnect,
NULL,
N_("close connection") },
{ "logout", 1, 1, com_logout,
NULL,
N_("quit imap session") },
{ "quit", 1, 1, com_logout,
NULL,
N_("same as `logout'") },
{ NULL }
};
int
mutool_imap (int argc, char **argv)
{
int index;
if (argp_parse (&imap_argp, argc, argv, ARGP_IN_ORDER, &index, NULL))
return 1;
argc -= index;
argv += index;
if (argc)
{
mu_error (_("too many arguments"));
return 1;
}
/* Command line prompt */
mutool_shell_prompt = xstrdup ("imap> ");
imap_prompt_env ();
mutool_shell ("imap", imap_comtab);
return 0;
}
/*
MU Setup: imap
mu-handler: mutool_imap
mu-docstring: imap_docstring
mu-cond: ENABLE_IMAP
End MU Setup:
*/
......@@ -55,7 +55,11 @@ END {
print "extern int", setup[name,"handler"], "(int argc, char **argv);"
print "extern char " setup[name,"docstring"] "[];"
} else {
if (setup[name,"cond"])
print "#ifdef", setup[name,"cond"]
print "{", "\"" name "\",", setup[name,"handler"] ",", setup[name,"docstring"], "},"
if (setup[name,"cond"])
print "#endif"
}
}
}
......
......@@ -40,3 +40,21 @@ mu_stream_t mutool_open_pager (void);
int mu_help (void);
mutool_action_t dispatch_find_action (const char *name);
char *dispatch_docstring (const char *text);
#define VERBOSE_MASK(n) (1<<((n)+1))
#define SET_VERBOSE_MASK(n) (shell_verbose_flags |= VERBOSE_MASK (n))
#define CLR_VERBOSE_MASK(n) (shell_verbose_flags &= ~VERBOSE_MASK (n))
#define QRY_VERBOSE_MASK(n) (shell_verbose_flags & VERBOSE_MASK (n))
#define HAS_VERBOSE_MASK(n) (shell_verbose_flags & ~1)
#define SET_VERBOSE() (shell_verbose_flags |= 1)
#define CLR_VERBOSE() (shell_verbose_flags &= ~1)
#define QRY_VERBOSE() (shell_verbose_flags & 1)
extern int shell_verbose_flags;
int shell_verbose (int argc, char **argv,
void (*set_verbose) (void), void (*set_mask) (void));
int get_bool (const char *str, int *pb);
int get_port (const char *port_str, int *pn);
......
......@@ -19,9 +19,7 @@
#endif
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <netdb.h>
#include <mailutils/mailutils.h>
#include "mu.h"
#include "argp.h"
......@@ -56,67 +54,8 @@ static struct argp pop_argp = {
NULL
};
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
return 1;
return 0;
}
int
get_port (const char *port_str, int *pn)
{
short port_num;
long num;
char *p;
num = port_num = strtol (port_str, &p, 0);
if (*p == 0)
{
if (num != port_num)
{
mu_error ("bad port number: %s", port_str);
return 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;
}
/* Global handle for pop3. */
mu_pop3_t pop3;
/* Flag if verbosity is needed. */
int verbose;
#define VERBOSE_MASK(n) (1<<((n)+1))
#define SET_VERBOSE_MASK(n) (verbose |= VERBOSE_MASK (n))
#define CLR_VERBOSE_MASK(n) (verbose &= VERBOSE_MASK (n))
#define QRY_VERBOSE_MASK(n) (verbose & VERBOSE_MASK (n))
#define HAS_VERBOSE_MASK(n) (verbose & ~1)
#define SET_VERBOSE() (verbose |= 1)
#define CLR_VERBOSE() (verbose &= ~1)
#define QRY_VERBOSE() (verbose & 1)
static mu_pop3_t pop3;
enum pop_session_status
{
......@@ -125,15 +64,15 @@ enum pop_session_status
pop_session_logged_in
};
enum pop_session_status pop_session_status;
static enum pop_session_status pop_session_status;
int connect_argc;
char **connect_argv;
static int connect_argc;
static char **connect_argv;
/* Host we are connected to. */
#define host connect_argv[0]
int port = 110;
char *username;
static int port = 110;
static char *username;
const char *
pop_session_str (enum pop_session_status stat)
......@@ -185,63 +124,27 @@ pop_prompt_env ()
}
static int
string_to_xlev (const char *name, int *pv)
{
if (strcmp (name, "secure") == 0)
*pv = MU_XSCRIPT_SECURE;
else if (strcmp (name, "payload") == 0)
*pv = MU_XSCRIPT_PAYLOAD;
else
return 1;
return 0;
}
static int
change_verbose_mask (int set, int argc, char **argv)
{
int i;
for (i = 0; i < argc; i++)
{
int lev;
if (string_to_xlev (argv[i], &lev))
{
mu_error ("unknown level: %s", argv[i]);
return 1;
}
if (set)
SET_VERBOSE_MASK (lev);
else
CLR_VERBOSE_MASK (lev);
}
return 0;
}
void
set_verbose (mu_pop3_t p)
static void
pop_set_verbose (void)
{
if (p)
if (pop3)
{
if (QRY_VERBOSE ())
{
mu_pop3_trace (p, MU_POP3_TRACE_SET);
}
mu_pop3_trace (pop3, MU_POP3_TRACE_SET);
else
mu_pop3_trace (p, MU_POP3_TRACE_CLR);
mu_pop3_trace (pop3, MU_POP3_TRACE_CLR);
}
}
void
set_verbose_mask (mu_pop3_t p)
static void
pop_set_verbose_mask (void)
{
if (p)
if (pop3)
{
mu_pop3_trace_mask (p, QRY_VERBOSE_MASK (MU_XSCRIPT_SECURE)
mu_pop3_trace_mask (pop3, QRY_VERBOSE_MASK (MU_XSCRIPT_SECURE)
? MU_POP3_TRACE_SET : MU_POP3_TRACE_CLR,
MU_XSCRIPT_SECURE);
mu_pop3_trace_mask (p, QRY_VERBOSE_MASK (MU_XSCRIPT_PAYLOAD)
mu_pop3_trace_mask (pop3, QRY_VERBOSE_MASK (MU_XSCRIPT_PAYLOAD)
? MU_POP3_TRACE_SET : MU_POP3_TRACE_CLR,
MU_XSCRIPT_PAYLOAD);
}
......@@ -250,50 +153,8 @@ set_verbose_mask (mu_pop3_t p)
static int
com_verbose (int argc, char **argv)
{
if (argc == 1)
{
if (QRY_VERBOSE ())
{
mu_stream_printf (mustrout, "verbose is on");
if (HAS_VERBOSE_MASK ())
{
char *delim = " (";
if (QRY_VERBOSE_MASK (MU_XSCRIPT_SECURE))
{
mu_stream_printf (mustrout, "%ssecure", delim);
delim = ", ";
}
if (QRY_VERBOSE_MASK (MU_XSCRIPT_PAYLOAD))
mu_stream_printf (mustrout, "%spayload", delim);
mu_stream_printf (mustrout, ")");
}
mu_stream_printf (mustrout, "\n");
}
else
mu_stream_printf (mustrout, "verbose is off\n");
}
else
{
int bv;
if (get_bool (argv[1], &bv) == 0)
{
verbose |= bv;
if (argc > 2)
change_verbose_mask (verbose, argc - 2, argv + 2);
set_verbose (pop3);
}
else if (strcmp (argv[1], "mask") == 0)
change_verbose_mask (1, argc - 2, argv + 2);
else if (strcmp (argv[1], "unmask") == 0)
change_verbose_mask (0, argc - 2, argv + 2);
else
mu_error ("unknown subcommand");
set_verbose_mask (pop3);
}
return 0;
return shell_verbose (argc, argv,
pop_set_verbose, pop_set_verbose_mask);
}
static int
......@@ -655,8 +516,8 @@ com_connect (int argc, char **argv)
if (QRY_VERBOSE ())
{
set_verbose (pop3);
set_verbose_mask (pop3);
pop_set_verbose ();
pop_set_verbose_mask ();
}
status = mu_tcp_stream_create (&tcp, argv[0], n, MU_STREAM_READ);
if (status == 0)
......@@ -779,7 +640,7 @@ struct mutool_command pop_comtab[] = {
N_("NAME"),
N_("send login") },
{ "verbose", 1, 4, com_verbose,
"[on|off|mask|unmask] [secret [payload]]",
"[on|off|mask|unmask] [secure [payload]]",
N_("control the protocol tracing") },
{ NULL }
};
......@@ -813,5 +674,6 @@ mutool_pop (int argc, char **argv)
MU Setup: pop
mu-handler: mutool_pop
mu-docstring: pop_docstring
mu-cond: ENABLE_POP
End MU Setup:
*/
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2010 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Mailutils 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 General Public License
along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
#if defined(HAVE_CONFIG_H)
# include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <mailutils/mailutils.h>
#include "mu.h"
/* Manipulations with verbosity flags, which are common for pop and imap. */
int shell_verbose_flags;
static int
string_to_xlev (const char *name, int *pv)
{
if (strcmp (name, "secure") == 0)
*pv = MU_XSCRIPT_SECURE;
else if (strcmp (name, "payload") == 0)
*pv = MU_XSCRIPT_PAYLOAD;
else
return 1;
return 0;
}
static int
change_verbose_mask (int set, int argc, char **argv)
{
int i;
for (i = 0; i < argc; i++)
{
int lev;
if (string_to_xlev (argv[i], &lev))
{
mu_error ("unknown level: %s", argv[i]);
return 1;
}
if (set)
SET_VERBOSE_MASK (lev);
else
CLR_VERBOSE_MASK (lev);
}
return 0;
}
int
shell_verbose (int argc, char **argv,
void (*set_verbose) (void), void (*set_mask) (void))
{
if (argc == 1)
{
if (QRY_VERBOSE ())
{
mu_stream_printf (mustrout, "verbose is on");
if (HAS_VERBOSE_MASK ())
{
char *delim = " (";
if (QRY_VERBOSE_MASK (MU_XSCRIPT_SECURE))
{
mu_stream_printf (mustrout, "%ssecure", delim);
delim = ", ";
}
if (QRY_VERBOSE_MASK (MU_XSCRIPT_PAYLOAD))
mu_stream_printf (mustrout, "%spayload", delim);
mu_stream_printf (mustrout, ")");
}
mu_stream_printf (mustrout, "\n");
}
else
mu_stream_printf (mustrout, "verbose is off\n");
}
else
{
int bv;
if (get_bool (argv[1], &bv) == 0)
{
if (bv)
SET_VERBOSE ();
else
CLR_VERBOSE ();
if (argc > 2)
change_verbose_mask (shell_verbose_flags, argc - 2, argv + 2);
set_verbose ();
}
else if (strcmp (argv[1], "mask") == 0)
change_verbose_mask (1, argc - 2, argv + 2);
else if (strcmp (argv[1], "unmask") == 0)
change_verbose_mask (0, argc - 2, argv + 2);
else
mu_error ("unknown subcommand");
set_mask ();
}
return 0;
}