Commit bd507cf1 bd507cf116ad3a56e979f406fabe3d0cef5e05a8 by Alain Magloire

header.c header.h header0.h mailbox.c mailbox.h mailbox0.h

 	mbx_imap.c mbx_mbox.c mbx_mdir.c mbx_mh.c mbx_mmdf.c mbx_pop.c
 	mbx_unix.c

cleaning and pruning.
1 parent 3f2a7da5
......@@ -25,299 +25,44 @@
#include <stdlib.h>
#include <errno.h>
static int rfc822_parse (header_t h, const char *blurb, size_t len);
static int rfc822_set_value (header_t h, const char *fn, const char *fb,
size_t n, int replace);
static int rfc822_get_value (header_t h, const char *fn,
char *fb, size_t len, size_t *n);
static int rfc822_get_mvalue (header_t h, const char *fn,
char **fb, size_t *n);
struct _hdr
{
char *fn;
char *fb;
};
typedef struct _hdr *hdr_t;
struct _rfc822_data
{
char *blurb;
struct _hdr unixfrom; /* stupid hack for unix from */
size_t hdr_count;
struct _hdr *hdr;
};
typedef struct _rfc822_data *rfc822_t;
int
header_init (header_t *ph, const char *blurb, size_t len, int flag)
{
header_t h;
if (flag != MU_HDR_RFC822)
{
if (flag != MU_HEADER_RFC822)
return ENOTSUP;
}
h = calloc (1, sizeof (*h));
if (h == NULL)
{
return ENOMEM;
}
h->_parse = rfc822_parse;
h->_get_value = rfc822_get_value;
h->_get_mvalue = rfc822_get_mvalue;
h->_set_value = rfc822_set_value;
h->_parse (h, blurb, len);
*ph = h;
return 0;
return rfc822_init (ph, blurb, len);
}
void
header_destroy (header_t *ph)
{
if (ph && *ph)
{
header_t h = *ph;
if (h->data)
{
rfc822_t rfc = (rfc822_t)h->data;
if (rfc->hdr)
free (rfc->hdr);
if (rfc->blurb)
free (rfc->blurb);
free (rfc);
}
free (h);
*ph = NULL;
}
}
int
header_gvalue (const char *blurb, size_t blurb_len, const char *fn, char *fb,
size_t len, size_t *n)
{
const char *header_end;
const char *header_start;
const char *colon;
size_t i = 0;
size_t j = 0;
size_t fn_len;
int status = EINVAL;
if (blurb == NULL || blurb_len < 5 || fn == NULL || len == 0)
{
return status;
}
*fb = '\0'; /* if we did find something, return empty */
for (fn_len = strlen (fn), header_start = blurb;;header_start = header_end)
{
header_end = memchr (header_start, '\n', blurb_len);
if (header_end == NULL)
{
break;
}
header_end++;
blurb_len -= header_end - header_start;
colon = memchr (header_start, ':', header_end - header_start);
if (colon == NULL)
{
continue;
}
/* check if is the header field name */
j = colon - header_start;
if (fn_len == j)
{
if (memcmp (fn, header_start, fn_len) == 0)
{
i = header_end - colon -1;
if (fb)
{
i = (len < i) ? len : i;
memcpy (fb, colon +1, i);
fb[i - 1] = '\0';
}
status = 0;
break;
}
}
}
if (n)
*n = i;
return status;
(*ph)->_destroy (ph);
}
/* stub functions */
int
header_gmvalue (const char *blurb, size_t blurb_ln, const char *fn,
char **fb, size_t *n)
header_set_value (header_t h, const char *fn, const char *fb, size_t n,
int replace)
{
size_t i;
if (blurb == NULL || blurb_ln == 0 || fn == NULL || fb == NULL
|| header_gvalue (blurb, blurb_ln, fn, NULL, 0, &i) != 0)
{
if (h == NULL)
return EINVAL;
}
*fb = calloc (1, ++i);
if (*fb == NULL)
return ENOMEM;
return header_gvalue (blurb, blurb_ln, fn, *fb, i, n);
return h->_set_value (h, fn, fb, n, replace);
}
static int
rfc822_parse (header_t h, const char *blurb, size_t len)
int
header_get_value (header_t h, const char *fn, char *fb,
size_t len, size_t *n)
{
rfc822_t rfc;
char *header_end;
char *header_start;
char *header_start2;
char *colon;
struct _hdr *hdr;
if (h == NULL || blurb == NULL || len == 0)
{
return EINVAL;
}
rfc = calloc (1, sizeof (*rfc));
if (rfc == NULL)
{
return ENOMEM;
}
rfc->blurb = calloc (1, len);
if (rfc->blurb == NULL)
{
free (rfc);
return ENOMEM;
}
memcpy (rfc->blurb, blurb, len);
for (header_start = rfc->blurb;; header_start = ++header_end)
{
/* get a header, a header is :
field-name ':' field-body1
[ ' ' '\t' field-body2 ] '\r' '\n'
*/
for (header_start2 = header_start;;header_start2 = ++header_end)
{
header_end = memchr (header_start2, '\n', len);
if (header_end == NULL)
{
break;
}
else
{
len -= (header_end - header_start2 + 1);
if (len == 0)
{
header_end = NULL;
break;
}
if (header_end[1] != ' '
&& header_end[1] != '\t')
{
break; /* new header break the inner for */
}
}
/* *header_end = ' '; smash LF */
}
if (header_end == NULL)
{
break; /* bail out */
}
*header_end = '\0'; /* smash LF */
/* Treats unix "From " specially */
if ((header_end - header_start >= 5)
&& strncmp (header_start, "From ", 5) == 0)
{
rfc->unixfrom.fn = "From ";
rfc->unixfrom.fb = header_start + 6;
}
else
{
colon = memchr (header_start, ':', header_end - header_start);
if (colon == NULL)
{
/* Houston we have a problem */
free (rfc->blurb);
if (rfc->hdr)
free (rfc->hdr);
free (rfc);
if (h == NULL)
return EINVAL;
}
hdr = realloc (rfc->hdr, (rfc->hdr_count + 1) * sizeof (*hdr));
if (hdr == NULL)
{
/* Houston we have another problem */
free (rfc->blurb);
if (rfc->hdr)
free (rfc->hdr);
free (rfc);
return ENOMEM;
}
rfc->hdr = hdr;
rfc->hdr_count++;
*colon = '\0'; /* smash colon */
rfc->hdr[rfc->hdr_count - 1].fn = header_start;
rfc->hdr[rfc->hdr_count - 1].fb = colon + 1;
}
}
h->data = rfc;
return 0;
return h->_get_value (h, fn, fb, len, n);
}
static int
rfc822_set_value (header_t h, const char *fn, const char *fb,
size_t n, int replace)
ssize_t
header_get_data (header_t h, char *data, size_t len, off_t off, int *err)
{
(void)h; (void)fn; (void)fb; (void)n; (void)replace;
return ENOSYS;
}
static int
rfc822_get_value (header_t h, const char *fn, char *fb, size_t len, size_t *n)
{
size_t i = 0;
size_t j = 0;
rfc822_t rfc = (rfc822_t)h->data;
if (fb)
{
*fb = '\0'; /* if empty */
}
for (i = 0; i < rfc->hdr_count; i++)
{
if (strcmp (rfc->hdr[i].fn, fn) == 0)
{
j = strlen (rfc->hdr[i].fb);
j = (len < j) ? len : j;
if (fb)
{
memcpy (fb, rfc->hdr[i].fb, j);
}
break;
}
}
if (n)
*n = j;
return 0;
}
static int
rfc822_get_mvalue (header_t h, const char *fn, char **fb, size_t *n)
{
size_t i;
if (h == NULL || fn == NULL || fb == NULL
|| h->_get_value (h, fn, NULL, 0, &i) != 0)
{
if (h == NULL)
return EINVAL;
}
*fb = calloc (1, ++i);
if (*fb == NULL)
return ENOMEM;
return h->_get_value (h, fn, *fb, i, n);
return h->_get_data (h, data, len, off, err);
}
......
......@@ -32,34 +32,34 @@
extern "C" {
#endif
#define MU_HDR_RFC822 0
#define MU_HDR_UNIX_FROM "From "
#define MU_HDR_RETURN_PATH "Return-Path"
#define MU_HDR_RECEIVED "Received"
#define MU_HDR_DATE "Date"
#define MU_HDR_FROM "From"
#define MU_HDR_RESENT_FROM "Resent-From"
#define MU_HDR_SUBJECT "Subject"
#define MU_HDR_SENDER "Sender"
#define MU_HDR_RESENT_SENDER "Resent-SENDER"
#define MU_HDR_TO "To"
#define MU_HDR_RESENT_TO "Resent-To"
#define MU_HDR_CC "Cc"
#define MU_HDR_RESENT_CC "Resent-Cc"
#define MU_HDR_BCC "Bcc"
#define MU_HDR_RESENT_BCC "Resent-Bcc"
#define MU_HDR_REPLY_TO "Reply-To"
#define MU_HDR_RESENT_REPLY_TO "Resent-Reply-To"
#define MU_HDR_MESSAGE_ID "Message-ID"
#define MU_HDR_RESENT_MESSAGE_ID "Resent-Message-ID"
#define MU_HDR_IN_REPLY_TO "In-Reply-To"
#define MU_HDR_ENCRYPTED "Encrypted"
#define MU_HDR_PRECEDENCE "Precedence"
#define MU_HDR_STATUS "Status"
#define MU_HDR_CONTENT_LENGTH "Content-Length"
#define MU_HDR_CONTENT_TYPE "Content-Type"
#define MU_HDR_MIME_VERSION "MIME-Version"
#define MU_HEADER_RFC822 0
#define MU_HEADER_UNIX_FROM "From "
#define MU_HEADER_RETURN_PATH "Return-Path"
#define MU_HEADER_RECEIVED "Received"
#define MU_HEADER_DATE "Date"
#define MU_HEADER_FROM "From"
#define MU_HEADER_RESENT_FROM "Resent-From"
#define MU_HEADER_SUBJECT "Subject"
#define MU_HEADER_SENDER "Sender"
#define MU_HEADER_RESENT_SENDER "Resent-SENDER"
#define MU_HEADER_TO "To"
#define MU_HEADER_RESENT_TO "Resent-To"
#define MU_HEADER_CC "Cc"
#define MU_HEADER_RESENT_CC "Resent-Cc"
#define MU_HEADER_BCC "Bcc"
#define MU_HEADER_RESENT_BCC "Resent-Bcc"
#define MU_HEADER_REPLY_TO "Reply-To"
#define MU_HEADER_RESENT_REPLY_TO "Resent-Reply-To"
#define MU_HEADER_MESSAGE_ID "Message-ID"
#define MU_HEADER_RESENT_MESSAGE_ID "Resent-Message-ID"
#define MU_HEADER_IN_REPLY_TO "In-Reply-To"
#define MU_HEADER_ENCRYPTED "Encrypted"
#define MU_HEADER_PRECEDENCE "Precedence"
#define MU_HEADER_STATUS "Status"
#define MU_HEADER_CONTENT_LENGTH "Content-Length"
#define MU_HEADER_CONTENT_TYPE "Content-Type"
#define MU_HEADER_MIME_VERSION "MIME-Version"
/* Mime support header attribute */
......@@ -71,26 +71,12 @@ extern int header_init __P ((header_t *, const char *blurb,
size_t ln, int flag));
extern void header_destroy __P ((header_t *));
extern int header_gvalue __P ((const char *blurb, size_t bl, const char *fn,
char *fv, size_t len, size_t *n));
extern int header_gmvalue __P ((const char *blurb, size_t bl, const char *fn,
char **fv, size_t *nv));
#undef INLINE
#ifdef __GNUC__
#define INLINE __inline__
#else
#define INLINE
#endif
extern INLINE int header_set_value __P ((header_t, const char *fn,
const char *fv, size_t n,
int replace));
extern INLINE int header_get_value __P ((header_t, const char *fn, char *fv,
extern int header_set_value __P ((header_t, const char *fn,
const char *fv, size_t n, int replace));
extern int header_get_value __P ((header_t, const char *fn, char *fv,
size_t len, size_t *n));
extern INLINE int header_get_mvalue __P ((header_t, const char *fn,
char **fv, size_t *n));
extern ssize_t header_get_data __P ((header_t h, char *data,
size_t len, off_t off, int *err));
#ifdef _cpluscplus
}
#endif
......
......@@ -33,26 +33,36 @@
extern "C" {
#endif
struct _hdr
{
char *fn;
char *fn_end;
char *fv;
char *fv_end;
};
typedef struct _hdr *hdr_t;
struct _header
{
/* Data */
void *data;
/* owner ? */
void *message;
/* Functions */
int (*_init) __P ((header_t *, const char *, size_t));
void (*_destroy) __P ((header_t *));
int (*_set_value) __P ((header_t, const char *fn, const char *fv,
size_t n, int replace));
int (*_get_value) __P ((header_t, const char *fn, char *fv,
size_t len, size_t *n));
int (*_get_mvalue) __P ((header_t, const char *fn, char **fv, size_t *n));
ssize_t (*_get_data) __P ((header_t h, char *data,
size_t len, off_t off, int *err));
int (*_parse) __P ((header_t, const char *blurb, size_t len));
} ;
#ifdef USE_MACROS
#define header_set_value(h, fn, fv, n, r) h->_set_value (h, fn, fv, n, r)
#define header_get_value(h, fn, fv, v, ln, n) h->_get_value (h, fn, fv, ln, n)
#define header_get_mvalue(h, fn, fv, v, n) h->_get_mvalue (h, fn, fv, n)
#endif
extern int rfc822_init __P ((header_t *ph, const char *blurb, size_t len));
extern void rfc822_destroy __P ((header_t *ph));
#ifdef _cpluscplus
}
#endif
......
......@@ -19,680 +19,236 @@
#include <config.h>
#endif
#include <mbx_mbox.h>
#include <mbx_unix.h>
#include <mbx_mdir.h>
#include <mbx_mmdf.h>
#include <mbx_pop.h>
#include <mbx_imap.h>
#include <mailbox0.h>
#include <message0.h>
#include <registrar.h>
#include <locker.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
/* forward prototypes */
static int mbx_open (mailbox_t, int flag);
static int mbx_close (mailbox_t);
/* name */
static int mbx_get_name (mailbox_t, int *id, char *name,
size_t len, size_t *n);
static int mbx_get_mname (mailbox_t mbox, int *id, char **name, size_t *n);
/* passwd */
static int mbx_get_passwd (mailbox_t, char *passwd, size_t, size_t *);
static int mbx_get_mpasswd (mailbox_t, char **passwd, size_t *len);
static int mbx_set_passwd (mailbox_t, const char *passwd, size_t len);
/* deleting */
static int mbx_delete (mailbox_t, size_t msgno);
static int mbx_undelete (mailbox_t, size_t msgno);
static int mbx_expunge (mailbox_t);
static int mbx_is_deleted (mailbox_t, size_t msgno);
/* appending */
static int mbx_new_msg (mailbox_t, size_t *msgno);
static int mbx_set_header (mailbox_t, size_t msgno, const char *h,
size_t n, int replace);
static int mbx_set_body (mailbox_t, size_t msgno, const char *b,
size_t n, int replace);
static int mbx_append (mailbox_t, size_t msgno);
static int mbx_destroy_msg (mailbox_t, size_t msgno);
/* reading */
static int mbx_get_body (mailbox_t, size_t msgno, off_t off,
char *b, size_t len, size_t *n);
static int mbx_get_mbody (mailbox_t, size_t msgno, off_t off,
char **b, size_t *n);
static int mbx_get_header (mailbox_t, size_t msgno, off_t off,
char *h, size_t len, size_t *n);
static int mbx_get_mheader (mailbox_t, size_t msgno, off_t off,
char **h, size_t *n);
/* locking */
static int mbx_lock (mailbox_t, int flag);
static int mbx_unlock (mailbox_t);
//static int mbx_ilock (mailbox_t, int flag);
//static int mbx_iunlock (mailbox_t);
/* owner and group */
static int mbx_set_owner (mailbox_t, uid_t uid);
static int mbx_get_owner (mailbox_t, uid_t *uid);
static int mbx_set_group (mailbox_t, uid_t gid);
static int mbx_get_group (mailbox_t, uid_t *gid);
/* misc */
static int mbx_scan (mailbox_t, size_t *msgs);
static int mbx_is_updated (mailbox_t);
static int mbx_get_timeout (mailbox_t, size_t *timeout);
static int mbx_set_timeout (mailbox_t, size_t timeout);
static int mbx_get_refresh (mailbox_t, size_t *refresh);
static int mbx_set_refresh (mailbox_t, size_t refresh);
static int mbx_get_size (mailbox_t, size_t msgno, size_t *sh, size_t *sb);
static int mbx_set_notification (mailbox_t,
int (*func) (mailbox_t, void *arg));
/* init all the functions to a default value */
static void mbx_check_struct (mailbox_t);
/*
Builtin mailbox types.
A circular list is use for the builtin.
Proper locking is not done when accessing the list.
FIXME: not thread-safe. */
static struct mailbox_builtin
{
struct mailbox_type *mtype;
int is_malloc;
struct mailbox_builtin * next;
} mailbox_builtin [] = {
{ NULL, 0, &mailbox_builtin[1] }, /* sentinel, head list */
{ &_mailbox_mbox_type, 0, &mailbox_builtin[2] },
{ &_mailbox_unix_type, 0, &mailbox_builtin[3] },
{ &_mailbox_maildir_type, 0, &mailbox_builtin[4] },
{ &_mailbox_mmdf_type, 0, &mailbox_builtin[5] },
{ &_mailbox_pop_type, 0, &mailbox_builtin[6] },
{ &_mailbox_imap_type, 0, &mailbox_builtin[0] },
};
* Point of entry.
* Simple, first check if they ask for something specific; with the ID.
* Then try to discover the type of mailbox with the url(name).
* Then we call the appropriate mailbox_*type*_init() function.
*/
int
mailbox_add_type (struct mailbox_type *mtype)
{
struct mailbox_builtin *current = malloc (sizeof (*current));
if (current == NULL)
return ENOMEM;
if (mtype->utype)
{
int status = url_add_type (mtype->utype);
if (status != 0)
{
free (current);
return status;
}
mtype->id = mtype->utype->id; /* same ID as the url_type */
}
else
{
mtype->id = (int)mtype; /* just need to be uniq */
}
current->mtype = mtype;
current->is_malloc = 1;
current->next = mailbox_builtin->next;
mailbox_builtin->next = current;
return 0;
}
int
mailbox_remove_type (struct mailbox_type *mtype)
{
struct mailbox_builtin *current, *previous;
for (previous = mailbox_builtin, current = mailbox_builtin->next;
current != mailbox_builtin;
previous = current, current = current->next)
{
if (current->mtype == mtype)
{
previous->next = current->next;
if (current->is_malloc)
free (current);
return 0;;
}
}
return EINVAL;
}
int
mailbox_list_type (struct mailbox_type *list, size_t len, size_t *n)
{
struct mailbox_builtin *current;
size_t i;
for (i = 0, current = mailbox_builtin->next; current != mailbox_builtin;
current = current->next, i++)
{
if (list)
if (i < len)
list[i] = *(current->mtype);
}
if (n)
*n = i;
return 0;
}
int
mailbox_list_mtype (struct mailbox_type **mlist, size_t *n)
{
struct mailbox_type *mtype;
size_t i = 0;
mailbox_list_type (NULL, 0, &i);
if (i == 0)
{
if (n)
{
*n = i;
}
return 0;
}
mtype = calloc (i, sizeof (*mtype));
if (mtype == NULL)
{
return ENOMEM;
}
*mlist = mtype;
return *n = mailbox_list_type (mtype, i, n);
}
int
mailbox_get_type (struct mailbox_type **mtype, int id)
{
struct mailbox_builtin *current;
for (current = mailbox_builtin->next; current != mailbox_builtin;
current = current->next)
{
if (current->mtype->id == id)
{
*mtype = current->mtype;
return 0;;
}
}
return EINVAL;
}
int
mailbox_init (mailbox_t *mbox, const char *name, int id)
mailbox_init (mailbox_t *pmbox, const char *name, int id)
{
int status = EINVAL;
struct mailbox_registrar *mreg;
url_t url = NULL;
url_init (&url, name);
/* 1st run: if they know what they want, shortcut */
/* 1st guest: if an ID is specify, shortcut */
if (id)
{
struct mailbox_type *mtype;
status = mailbox_get_type (&mtype, id);
status = registrar_get (id, NULL, &mreg);
if (status == 0)
{
status = mtype->_init (mbox, name);
if (status == 0)
mbx_check_struct (*mbox);
status = mreg->_init (pmbox, name);
}
}
/* 2nd run: try heuristic URL discovery */
if (status != 0)
{
url_t url;
status = url_init (&url, name);
if (status == 0)
/* 2nd fallback: Use the URL */
else if (url != NULL)
{
int id;
struct mailbox_type *mtype;
/* We've found a match get it */
if (url_get_id (url, &id) == 0
&& (status = mailbox_get_type (&mtype, id)) == 0)
{
status = mtype->_init (mbox, name);
url_get_id (url, &id);
status = registrar_get (id, NULL, &mreg);
if (status == 0)
mbx_check_struct (*mbox);
}
url_destroy (&url);
}
status = mreg->_init (pmbox, name);
}
/* 3nd run: nothing yet ?? try mbox directly as the last resort.
this should take care of the case where the filename is use */
if (status != 0 )
{
status = mailbox_mbox_init (mbox, name);
/* if things went ok set mreg for mailbox_destroy and the URL */
if (status == 0)
mbx_check_struct (*mbox);
{
(*pmbox)->url = url;
(*pmbox)->_init = mreg->_init;
(*pmbox)->_destroy = mreg->_destroy;
}
return status;
}
void
mailbox_destroy (mailbox_t *mbox)
mailbox_destroy (mailbox_t *pmbox)
{
struct mailbox_type *mtype = (*mbox)->mtype;
return mtype->_destroy (mbox);
if (pmbox && *pmbox)
(*pmbox)->_destroy (pmbox);
}
/* -------------- stub functions ------------------- */
static void
mbx_check_struct (mailbox_t mbox)
{
if (mbox->_open == NULL)
mbox->_open = mbx_open;
if (mbox->_close == NULL)
mbox->_close = mbx_close;
if (mbox->_get_name == NULL)
mbox->_get_name = mbx_get_name;
if (mbox->_get_mname == NULL)
mbox->_get_mname = mbx_get_mname;
if (mbox->_get_passwd == NULL)
mbox->_get_passwd = mbx_get_passwd;
if (mbox->_get_mpasswd == NULL)
mbox->_get_mpasswd = mbx_get_mpasswd;
if (mbox->_set_passwd == NULL)
mbox->_set_passwd = mbx_set_passwd;
if (mbox->_delete == NULL)
mbox->_delete = mbx_delete;
if (mbox->_undelete == NULL)
mbox->_undelete = mbx_undelete;
if (mbox->_expunge == NULL)
mbox->_expunge = mbx_expunge;
if (mbox->_is_deleted == NULL)
mbox->_is_deleted = mbx_is_deleted;
if (mbox->_new_msg == NULL)
mbox->_new_msg = mbx_new_msg;
if (mbox->_set_header == NULL)
mbox->_set_header = mbx_set_header;
if (mbox->_set_body == NULL)
mbox->_set_body = mbx_set_body;
if (mbox->_append == NULL)
mbox->_append = mbx_append;
if (mbox->_destroy_msg == NULL)
mbox->_destroy_msg = mbx_destroy_msg;
if (mbox->_get_body == NULL)
mbox->_get_body = mbx_get_body;
if (mbox->_get_mbody == NULL)
mbox->_get_mbody = mbx_get_mbody;
if (mbox->_get_header == NULL)
mbox->_get_header = mbx_get_header;
if (mbox->_get_mheader == NULL)
mbox->_get_mheader = mbx_get_mheader;
if (mbox->_lock == NULL)
mbox->_lock = mbx_lock;
if (mbox->_unlock == NULL)
mbox->_unlock = mbx_unlock;
if (mbox->_ilock == NULL)
mbox->_ilock = mbx_lock;
if (mbox->_iunlock == NULL)
mbox->_iunlock = mbx_unlock;
if (mbox->_scan == NULL)
mbox->_scan = mbx_scan;
if (mbox->_is_updated == NULL)
mbox->_is_updated = mbx_is_updated;
if (mbox->_set_owner == NULL)
mbox->_set_owner = mbx_set_owner;
if (mbox->_get_owner == NULL)
mbox->_get_owner = mbx_get_owner;
if (mbox->_set_group == NULL)
mbox->_set_group = mbx_set_group;
if (mbox->_get_group == NULL)
mbox->_get_group = mbx_get_group;
if (mbox->_get_timeout == NULL)
mbox->_get_timeout = mbx_get_timeout;
if (mbox->_set_timeout == NULL)
mbox->_set_timeout = mbx_set_timeout;
if (mbox->_get_refresh == NULL)
mbox->_get_refresh = mbx_get_refresh;
if (mbox->_set_refresh == NULL)
mbox->_set_refresh = mbx_set_refresh;
if (mbox->_get_size == NULL)
mbox->_get_size = mbx_get_size;
if (mbox->_set_notification == NULL)
mbox->_set_notification = mbx_set_notification;
}
static int
mbx_open (mailbox_t mbox, int flag)
int
mailbox_open (mailbox_t mbox, int flag)
{
(void)mbox; (void)flag;
if (mbox == NULL || mbox->_open == NULL)
return ENOSYS;
return mbox->_open (mbox, flag);
}
static int
mbx_close (mailbox_t mbox)
int
mailbox_close (mailbox_t mbox)
{
(void)mbox;
if (mbox == NULL || mbox->_close == NULL)
return ENOSYS;
return mbox->_close (mbox);
}
/* name */
static int
mbx_get_name (mailbox_t mbox, int *id, char *name, size_t len, size_t *n)
{
char *s;
size_t i;
if (mbox == NULL || mbox->mtype == NULL)
{
return EINVAL;
}
s = mbox->mtype->name;
i = strlen (s);
if (id)
{
*id = mbox->mtype->id;
}
if (name && len > 0)
{
i = (len < i) ? len : i;
strncpy (name, s, i - 1);
name [i - 1] = 0;
}
if (n)
{
*n = i;
}
return 0;
}
static int
mbx_get_mname (mailbox_t mbox, int *id, char **name, size_t *n)
/* messages */
int
mailbox_is_deleted (mailbox_t mbox, size_t msgno)
{
size_t i = 0;
mbox->_get_name (mbox, id, 0, 0, &i);
i++;
*name = calloc (i, sizeof (char));
if (*name == NULL)
{
return ENOMEM;
}
mbox->_get_name (mbox, id, *name, i, n);
if (mbox == NULL || mbox->_is_deleted == NULL)
return 0;
return mbox->_is_deleted (mbox, msgno);
}
/* passwd */
static int
mbx_get_passwd (mailbox_t mbox, char *passwd, size_t len, size_t *n)
int
mailbox_append_message (mailbox_t mbox, message_t msg)
{
(void)mbox; (void)passwd; (void)len; (void)n;
if (mbox == NULL || mbox->_append_message == NULL)
return ENOSYS;
return mbox->_append_message (mbox, msg);
}
static int
mbx_get_mpasswd (mailbox_t mbox, char **passwd, size_t *n)
int
mailbox_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg)
{
size_t i = 0;
mbox->_get_passwd (mbox, NULL, 0, &i);
i++;
*passwd = calloc (i, sizeof (char));
if (*passwd == NULL)
{
return ENOMEM;
}
mbox->_get_passwd (mbox, *passwd, i, n);
int status;
if (mbox == NULL || pmsg == NULL)
return EINVAL;
if (mailbox_is_deleted (mbox, msgno))
return EINVAL;
status = message_init (pmsg);
if (status != 0)
return status;
(*pmsg)->mailbox = mbox;
(*pmsg)->num = msgno;
return 0;
}
static int
mbx_set_passwd (mailbox_t mbox, const char *passwd, size_t len)
{
(void)mbox; (void)passwd; (void)len;
return ENOSYS;
}
/* deleting */
static int
mbx_delete (mailbox_t mbox, size_t msgno)
{
(void)mbox; (void)msgno;
return ENOSYS;
}
static int
mbx_undelete (mailbox_t mbox, size_t msgno)
{
(void)mbox; (void)msgno;
return ENOSYS;
}
static int
mbx_expunge (mailbox_t mbox)
{
(void)mbox;
return ENOSYS;
}
static int
mbx_is_deleted (mailbox_t mbox, size_t msgno)
{
(void)mbox; (void)msgno;
return ENOSYS;
}
/* appending */
static int
mbx_new_msg (mailbox_t mbox, size_t *msgno)
{
(void)mbox; (void)msgno;
return ENOSYS;
}
static int
mbx_set_header (mailbox_t mbox, size_t msgno, const char *h,
size_t len, int replace)
{
(void)mbox; (void)msgno; (void)h; (void)len; (void)replace;
return ENOSYS;
}
static int
mbx_set_body (mailbox_t mbox, size_t msgno, const char *b,
size_t len, int replace)
int
mailbox_messages_count (mailbox_t mbox, size_t *num)
{
(void)mbox; (void)msgno; (void)b; (void)len; (void)replace;
if (mbox == NULL || mbox->_messages_count == NULL)
return ENOSYS;
return mbox->_messages_count (mbox, num);
}
static int
mbx_append (mailbox_t mbox, size_t msgno)
int
mailbox_delete (mailbox_t mbox, size_t msgno)
{
(void)mbox; (void)msgno;
if (mbox == NULL || mbox->_delete == NULL)
return ENOSYS;
return mbox->_delete (mbox, msgno);
}
static int
mbx_destroy_msg (mailbox_t mbox, size_t msgno)
int
mailbox_undelete (mailbox_t mbox, size_t msgno)
{
(void)mbox; (void)msgno;
if (mbox == NULL || mbox->_undelete == NULL)
return ENOSYS;
return mbox->_undelete (mbox, msgno);
}
/* reading */
static int
mbx_get_body (mailbox_t mbox, size_t msgno, off_t off,
char *b, size_t len, size_t *n)
int
mailbox_expunge (mailbox_t mbox)
{
(void)mbox; (void)msgno; (void)off; (void)b; (void)len; (void)n;
if (mbox == NULL || mbox->_expunge == NULL)
return ENOSYS;
return mbox->_expunge (mbox);
}
static int
mbx_get_mbody (mailbox_t mbox, size_t msgno, off_t off,
char **body, size_t *n)
{
size_t i = 0;
mbox->_get_body (mbox, msgno, off, NULL, 0, &i);
i++;
*body = calloc (i, sizeof (char));
if (*body == NULL)
{
return ENOMEM;
}
mbox->_get_body (mbox, msgno, off, *body, i, n);
return 0;
}
static int
mbx_get_header (mailbox_t mbox, size_t msgno, off_t off,
char *h, size_t len, size_t *n)
int
mailbox_num_deleted (mailbox_t mbox, size_t *num)
{
(void)mbox; (void)msgno; (void)off; (void)h; (void)len; (void)n;
return ENOSYS;
if (mbox == NULL || mbox->_num_deleted == NULL)
return EINVAL;
return mbox->_num_deleted (mbox, num);
}
static int
mbx_get_mheader (mailbox_t mbox, size_t msgno, off_t off,
char **header, size_t *n)
/* hook to allow some sort of "progress bar" .. I don't like it
* but can not find any other way yet
*/
int
mailbox_progress (mailbox_t mbox, int (*progress) (int, void *arg), void *arg)
{
size_t i;
i = mbox->_get_header (mbox, msgno, off, NULL, 0, &i);
i++;
*header = calloc (i, sizeof (char));
if (*header == NULL)
{
return ENOMEM;
}
mbox->_get_header (mbox, msgno, off, *header, i, n);
if (mbox == NULL)
return EINVAL;
mbox->_progress = progress;
mbox->progress_arg = arg;
return 0;
}
/* locking */
static int
mbx_lock (mailbox_t mbox, int flag)
{
(void)mbox; (void)flag;
return ENOSYS;
}
static int
mbx_unlock (mailbox_t mbox)
{
(void)mbox;
return ENOSYS;
}
/* owner and group */
static int
mbx_set_owner (mailbox_t mbox, uid_t uid)
{
mbox->owner = uid;
return 0;
}
static int
mbx_get_owner (mailbox_t mbox, uid_t *uid)
int
mailbox_is_updated (mailbox_t mbox)
{
*uid = mbox->owner;
if (mbox == NULL || mbox->_is_updated == NULL)
return 0;
return mbox->_is_updated (mbox);
}
static int
mbx_set_group (mailbox_t mbox, uid_t gid)
{
mbox->group = gid;
return 0;
}
static int
mbx_get_group (mailbox_t mbox, uid_t *gid)
ssize_t
mailbox_get_size (mailbox_t mbox, size_t msgno, size_t *h, size_t *b)
{
*gid = mbox->group;
return 0;
if (mbox == NULL || mbox->_get_size == NULL)
return EINVAL;
return mbox->_get_size (mbox, msgno, h, b);
}
/* misc */
static int
mbx_scan (mailbox_t mbox, size_t *msgs)
ssize_t
mailbox_get_header (mailbox_t mbox, size_t msgno, char *h,
size_t len, off_t off, int *err)
{
(void)mbox; (void)msgs;
if (mbox == NULL || mbox->_get_header == NULL)
return ENOSYS;
return mbox->_get_header (mbox, msgno, h, len, off, err);
}
static int
mbx_is_updated (mailbox_t mbox)
ssize_t
mailbox_get_body (mailbox_t mbox, size_t msgno, char *b,
size_t len, off_t off, int *err)
{
(void)mbox;
if (mbox == NULL || mbox->_get_body == NULL)
return ENOSYS;
return mbox->_get_body (mbox, msgno, b, len, off, err);
}
static int
mbx_get_timeout (mailbox_t mbox, size_t *timeout)
/* locking */
int
mailbox_set_locker (mailbox_t mbox, locker_t locker)
{
*timeout = mbox->timeout;
if (mbox == NULL)
return EINVAL;
if (mbox->locker != NULL)
locker_destroy (&mbox->locker);
mbox->locker = locker;
return 0;
}
static int
mbx_set_timeout (mailbox_t mbox, size_t timeout)
int
mailbox_get_locker (mailbox_t mbox, locker_t *locker)
{
mbox->timeout = timeout;
if (mbox == NULL || locker == NULL)
return EINVAL;
*locker = mbox->locker;
return 0;
}
static int
mbx_get_refresh (mailbox_t mbox, size_t *refresh)
int
mailbox_set_auth (mailbox_t mbox, auth_t auth)
{
*refresh = mbox->refresh;
if (mbox == NULL)
return EINVAL;
mbox->auth = auth;
return 0;
}
static int
mbx_set_refresh (mailbox_t mbox, size_t refresh)
int
mailbox_get_auth (mailbox_t mbox, auth_t *auth)
{
mbox->refresh = refresh;
if (mbox == NULL || auth == NULL)
return EINVAL;
*auth = mbox->auth;
return 0;
}
static int
mbx_get_size (mailbox_t mbox, size_t msgno, size_t *sh, size_t *sb)
{
(void)mbox; (void)msgno; (void)sh; (void)sb;
return ENOSYS;
}
static int
mbx_set_notification (mailbox_t mbox, int (*func) (mailbox_t, void *arg))
{
mbox->notification = func;
return ENOSYS;
}
......
......@@ -18,10 +18,12 @@
#ifndef _MAILBOX_H
# define _MAILBOX_H
#include <url.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <url.h>
#include <message.h>
#include <auth.h>
#include <locker.h>
#ifdef __cplusplus
extern "C" {
......@@ -39,109 +41,44 @@ extern "C" {
struct _mailbox;
typedef struct _mailbox *mailbox_t;
struct mailbox_type
{
char *name;
int id;
struct url_type *utype;
int (*_init) __P ((mailbox_t *, const char *name));
void (*_destroy) __P ((mailbox_t *));
};
/* constructor/destructor and possible types */
extern int mailbox_init __P ((mailbox_t *, const char *name, int id));
extern int mailbox_init __P ((mailbox_t *, const char *, int id));
extern void mailbox_destroy __P ((mailbox_t *));
/* mailbox registration */
extern int mailbox_list_type __P ((struct mailbox_type mtype[],
size_t len, size_t *n));
extern int mailbox_list_mtype __P ((struct mailbox_type **mtype, size_t *n));
extern int mailbox_add_type __P ((struct mailbox_type *mtype));
extern int mailbox_remove_type __P ((struct mailbox_type *mtype));
extern int mailbox_get_type __P ((struct mailbox_type **mtype, int id));
#ifndef INLINE
# ifdef __GNUC__
# define INLINE __inline__
# else
# define INLINE
# endif
#endif
/* flags for mailbox_open () */
#define MU_MB_RDONLY ((int)1)
#define MU_MB_WRONLY (MU_MB_RDONLY << 1)
#define MU_MB_RDWR (MU_MB_WRONLY << 1)
#define MU_MB_APPEND (MU_MB_RDWR << 1)
#define MU_MB_CREAT (MU_MB_APPEND << 1)
extern INLINE int mailbox_open __P ((mailbox_t, int flag));
extern INLINE int mailbox_close __P ((mailbox_t));
/* type */
extern INLINE int mailbox_get_name __P ((mailbox_t, int *id, char *name,
size_t len, size_t *n));
extern INLINE int mailbox_get_mname __P ((mailbox_t, int *id, char **name,
size_t *n));
/* passwd */
extern INLINE int mailbox_get_passwd __P ((mailbox_t, char *passwd,
size_t len, size_t *n));
extern INLINE int mailbox_get_mpasswd __P ((mailbox_t, char **passwd,
size_t *n));
extern INLINE int mailbox_set_passwd __P ((mailbox_t, const char *passwd,
size_t len));
/* deleting */
extern INLINE int mailbox_delete __P ((mailbox_t, size_t msgno));
extern INLINE int mailbox_undelete __P ((mailbox_t, size_t msgno));
extern INLINE int mailbox_expunge __P ((mailbox_t));
extern INLINE int mailbox_is_deleted __P ((mailbox_t, size_t msgno));
/* appending */
extern INLINE int mailbox_new_msg __P ((mailbox_t, size_t * msgno));
extern INLINE int mailbox_set_header __P ((mailbox_t, size_t msgno,
const char *h, size_t len,
int replace));
extern INLINE int mailbox_set_body __P ((mailbox_t, size_t msgno,
const char *b, size_t len,
int replace));
extern INLINE int mailbox_append __P ((mailbox_t, size_t msgno));
extern INLINE int mailbox_destroy_msg __P ((mailbox_t, size_t msgno));
/* reading */
extern INLINE int mailbox_get_body __P ((mailbox_t, size_t msgno,
off_t off, char *b,
size_t len, size_t *n));
extern INLINE int mailbox_get_mbody __P ((mailbox_t, size_t msgno, off_t off,
char **b, size_t *n));
extern INLINE int mailbox_get_header __P ((mailbox_t, size_t msgno, off_t off,
char *h, size_t len, size_t *n));
extern INLINE int mailbox_get_mheader __P ((mailbox_t, size_t msgno, off_t off,
char **h, size_t *n));
#define MU_MAILBOX_RDONLY ((int)1)
#define MU_MAILBOX_WRONLY (MU_MAILBOX_RDONLY << 1)
#define MU_MAILBOX_RDWR (MU_MAILBOX_WRONLY << 1)
#define MU_MAILBOX_APPEND (MU_MAILBOX_RDWR << 1)
#define MU_MAILBOX_CREAT (MU_MAILBOX_APPEND << 1)
#define MU_MAILBOX_NONBLOCK (MU_MAILBOX_CREAT << 1)
extern int mailbox_open __P ((mailbox_t, int flag));
extern int mailbox_close __P ((mailbox_t));
/* messages */
extern int mailbox_get_message __P ((mailbox_t, size_t msgno, message_t *msg));
extern int mailbox_append_message __P ((mailbox_t, message_t msg));
extern int mailbox_messages_count __P ((mailbox_t, size_t *num));
extern int mailbox_expunge __P ((mailbox_t));
/* Lock settings */
typedef enum { MB_RDLOCK, MB_WRLOCK } mailbox_lock_t;
extern INLINE int mailbox_lock __P ((mailbox_t, int flag));
extern INLINE int mailbox_unlock __P ((mailbox_t));
/* owner and group */
extern INLINE int mailbox_set_owner __P ((mailbox_t, uid_t uid));
extern INLINE int mailbox_set_group __P ((mailbox_t, gid_t gid));
/* miscellany */
extern INLINE int mailbox_scan __P ((mailbox_t, size_t *msgs));
extern INLINE int mailbox_is_updated __P ((mailbox_t));
extern INLINE int mailbox_get_timeout __P ((mailbox_t, size_t *timeout));
extern INLINE int mailbox_set_timeout __P ((mailbox_t, size_t timeout));
extern INLINE int mailbox_get_refresh __P ((mailbox_t, size_t *refresh));
extern INLINE int mailbox_set_refresh __P ((mailbox_t, size_t refresh));
extern INLINE int mailbox_get_size __P ((mailbox_t, size_t msgno,
size_t *header, size_t *body));
extern INLINE int mailbox_set_notification __P ((mailbox_t,
int (*notification)
__P ((mailbox_t, void *))));
extern int mailbox_get_locker __P ((mailbox_t, locker_t *locker));
extern int mailbox_set_locker __P ((mailbox_t, locker_t locker));
/* Authentication */
extern int mailbox_get_auth __P ((mailbox_t, auth_t *auth));
extern int mailbox_set_auth __P ((mailbox_t, auth_t auth));
/* update and scanning*/
extern int mailbox_progress __P ((mailbox_t, int (*progress)
__P ((int, void *)), void *arg));
extern int mailbox_is_updated __P ((mailbox_t));
/* mailbox size ? */
extern int mailbox_size __P ((mailbox_t, off_t size));
extern int mailbox_get_url __P ((mailbox_t, url_t *));
#ifdef __cplusplus
}
......
......@@ -16,13 +16,12 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef _MAILBOX0_H
# define _MAILBOX0_H
#define _MAILBOX0_H
#include <url.h>
#include <mailbox.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
......@@ -36,176 +35,78 @@ extern "C" {
# endif
#endif /*__P */
/* forward declaration */
//struct _mailbox;
//typedef struct _mailbox *mailbox_t;
/* Lock settings */
//typedef enum { MB_ULOCK, MB_RLOCK, MB_WLOCK } mailbox_lock_t;
/*
struct mailbox_type
{
char *name;
int id;
struct url_type *utype;
int (*_init) __P ((mailbox_t *, const char *name));
void (*_destroy) __P ((mailbox_t *));
};
*/
struct _mailbox
{
/* Data */
char *name;
uid_t owner;
gid_t group;
size_t messages;
size_t num_deleted;
FILE *file;
message_t *messages;
size_t messages_num;
off_t size;
int lock;
size_t timeout;
size_t refresh;
int (*notification) __P ((mailbox_t, void *arg));
struct mailbox_type *mtype;
/* back pointer to the specific mailbox */
auth_t auth;
locker_t locker;
url_t url;
int (*_progress) __P ((int, void *arg));
void *progress_arg;
/* Back pointer to the specific mailbox */
void *data;
/* Functions */
/* Public methods */
#define MU_MB_RDONLY ((int)1)
#define MU_MB_WRONLY (MU_MB_RDONLY << 1)
#define MU_MB_RDWR (MU_MB_WRONLY << 1)
#define MU_MB_APPEND (MU_MB_RDWR << 1)
#define MU_MB_CREAT (MU_MB_APPEND << 1)
int (*_init) __P ((mailbox_t *, const char *));
void (*_destroy) __P ((mailbox_t *));
int (*_open) __P ((mailbox_t, int flag));
int (*_close) __P ((mailbox_t));
/* type */
int (*_get_name) __P ((mailbox_t, int *id, char *name,
size_t len, size_t *n));
int (*_get_mname) __P ((mailbox_t, int *id, char **name, size_t *n));
/* passwd if needed */
int (*_get_passwd) __P ((mailbox_t, char *passwd,
size_t len, size_t *n));
int (*_get_mpasswd) __P ((mailbox_t, char **passwd, size_t *n));
int (*_set_passwd) __P ((mailbox_t, const char *passwd, size_t len));
/* deleting mesgs */
int (*_is_deleted) __P ((mailbox_t, size_t msgno));
int (*_delete) __P ((mailbox_t, size_t msgno));
int (*_undelete) __P ((mailbox_t, size_t msgno));
/* messages */
int (*_get_message) __P ((mailbox_t, size_t msgno, message_t *msg));
int (*_append_message) __P ((mailbox_t, message_t msg));
int (*_messages_count) __P ((mailbox_t, size_t *num));
int (*_expunge) __P ((mailbox_t));
int (*_is_updated) __P ((mailbox_t));
int (*_scan) __P ((mailbox_t, size_t *msgs));
/* appending messages */
int (*_new_msg) __P ((mailbox_t, size_t *msgno));
int (*_set_header) __P ((mailbox_t, size_t msgno, const char *h,
size_t len, int replace));
int (*_set_body) __P ((mailbox_t, size_t msgno, const char *b,
size_t len, int replace));
int (*_append) __P ((mailbox_t, size_t msgno));
int (*_destroy_msg) __P ((mailbox_t, size_t msgno));
#define MU_MB_RDLOCK 0
#define MU_MB_WRLOCK 1
/* locking */
int (*_lock) __P ((mailbox_t, int flag));
int (*_unlock) __P ((mailbox_t));
int (*_ilock) __P ((mailbox_t, int flag));
int (*_iunlock) __P ((mailbox_t));
/* reading mesgs */
int (*_get_body) __P ((mailbox_t, size_t msgno, off_t off,
char *b, size_t len, size_t *n));
int (*_get_mbody) __P ((mailbox_t, size_t msgno, off_t off,
char **b, size_t *n));
int (*_get_header) __P ((mailbox_t, size_t msgno, off_t off,
char *h, size_t len, size_t *n));
int (*_get_mheader) __P ((mailbox_t, size_t msgno, off_t off,
char **h, size_t *n));
int (*_get_size) __P ((mailbox_t, size_t msgno,
size_t *h, size_t *b));
/* setting flags */
int (*_is_read) __P ((mailbox_t, size_t msgno));
int (*_set_read) __P ((mailbox_t, size_t msgno));
int (*_is_seen) __P ((mailbox_t, size_t msgno));
int (*_set_seen) __P ((mailbox_t, size_t msgno));
int (*_size) __P ((mailbox_t, off_t *size));
/* owner and group */
int (*_set_owner) __P ((mailbox_t, uid_t uid));
int (*_get_owner) __P ((mailbox_t, uid_t *uid));
int (*_set_group) __P ((mailbox_t, gid_t gid));
int (*_get_group) __P ((mailbox_t, gid_t *gid));
/* private */
int (*_delete) __P ((mailbox_t, size_t msgno));
int (*_undelete) __P ((mailbox_t, size_t msgno));
int (*_is_deleted) __P ((mailbox_t, size_t msgno));
int (*_num_deleted) __P ((mailbox_t, size_t *));
int (*_get_size) __P ((mailbox_t, size_t msgno,
size_t *h, size_t *b));
/* miscellany */
int (*_size) __P ((mailbox_t, off_t *size));
int (*_get_timeout) __P ((mailbox_t, size_t *timeout));
int (*_set_timeout) __P ((mailbox_t, size_t timeout));
int (*_get_refresh) __P ((mailbox_t, size_t *refresh));
int (*_set_refresh) __P ((mailbox_t, size_t refresh));
int (*_set_notification) __P ((mailbox_t,
int (*func) __P ((mailbox_t, void * arg))));
ssize_t (*_get_header) __P ((mailbox_t, size_t msgno, char *h,
size_t len, off_t off, int *err));
ssize_t (*_get_body) __P ((mailbox_t, size_t msgno, char *b,
size_t len, off_t off, int *err));
};
/* private */
extern int mailbox_delete __P ((mailbox_t, size_t msgno));
extern int mailbox_undelete __P ((mailbox_t, size_t msgno));
extern int mailbox_is_deleted __P ((mailbox_t, size_t msgno));
extern int mailbox_num_deleted __P ((mailbox_t, size_t *));
extern int mailbox_get_size __P ((mailbox_t, size_t msgno,
size_t *h, size_t *b));
extern ssize_t mailbox_get_header __P ((mailbox_t, size_t msgno, char *h,
size_t len, off_t off, int *err));
extern ssize_t mailbox_get_body __P ((mailbox_t, size_t msgno, char *b,
size_t len, off_t off, int *err));
extern int mailbox_get_auth __P ((mailbox_t mbox, auth_t *auth));
extern int mailbox_set_auth __P ((mailbox_t mbox, auth_t auth));
extern int mailbox_get_locker __P ((mailbox_t mbox, locker_t *locker));
extern int mailbox_set_locker __P ((mailbox_t mbox, locker_t locker));
extern int mailbox_progress __P ((mailbox_t mbox,
int (*progress) (int, void *arg),
void *arg));
#ifdef MU_USE_MACROS
#define mailbox_open(m, f) m->_open (m, f)
#define mailbox_close(m) m->_close (m)
/* type */
#define mailbox_get_name(m, t, d, l, n) m->_get_name (m, t, d, l, n)
#define mailbox_get_mtype(m, t, d, n) m->_get_mtype (m, t, d, n)
/* passwd */
#define mailbox_get_passwd(m, p, l, n) m->_get_passwd (m, p, l, n)
#define mailbox_get_mpasswd(m, p, n) m->_get_mpasswd (m, p, n)
#define mailbox_set_passwd(m, p, l) m->_set_passwd (m, p, l)
/* deleting */
#define mailbox_delete(m, mid) m->_delete (m, mid)
#define mailbox_undelete(m, mid) m->_undelete (m, mid)
#define mailbox_is_deleted(m, mid) m->_is_deleted (m, mid)
#define mailbox_expunge(m) m->_expunge (m)
/* appending */
#define mailbox_new_msg(m, mid) m->_new_msg (m, mid)
#define mailbox_set_header(m, mid, h, l, r) m->_set_header(m, mid, h, n, r)
#define mailbox_set_body(m, mid, b, l r) m->_set_body (m, mid, b, l, r)
#define mailbox_append(m, mid) m->_append (m, mid)
#define mailbox_destroy_msg(m, mid) m->_destroy_msg (m, mid)
/* locking */
#define mailbox_lock(m, f) m->_lock (m, f)
#define mailbox_unlock(m) m->_unlock (m)
/* reading */
#define mailbox_get_header(m, mid, h, l, n) m->_get_header (m, mid, h, o, n)
#define mailbox_get_mheader(m, mid, h, l) m->_get_header (m, mid, h, l)
#define mailbox_get_body(m, mid, b, l, n) m->_get_body (m, mid, b, l, n)
#define mailbox_get_mbody(m, mid, b, n) m->_get_body (m, mid, b, n)
/* owner and group */
#define mailbox_set_owner(m, uid) m->_set_owner(m, uid)
#define mailbox_get_owner(m, uid) m->_set_owner(m, uid)
#define mailbox_set_group(m, gid) m->_set_group(m, gid)
#define mailbox_get_group(m, gid) m->_set_group(m, gid)
/* miscellany */
#define mailbox_scan(m, t) m->_scan (m, t)
#define mailbox_is_updated(m) m->_is_updated (m)
#define mailbox_get_timeout(m, t) m->_get_timeout (m, t)
#define mailbox_set_timeout(m, t) m->_set_timeout (m, t)
#define mailbox_get_refresh(m, r) m->_get_refresh (m, r)
#define mailbox_set_refresh(m, r) m->_set_refresh (m, r)
#define mailbox_get_size(m, mid, sh, sb) m->_get_size(m, mid, sh, sb)
#define mailbox_set_notification(m, func) m->_set_notification (m, func)
#endif /* MU_USE_MACROS */
#ifdef __cplusplus
}
......
......@@ -15,15 +15,17 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <mbx_imap.h>
#include <url_imap.h>
#include <mailbox0.h>
#include <registrar0.h>
#include <errno.h>
struct mailbox_type _mailbox_imap_type =
static int mailbox_imap_init (mailbox_t *mbox, const char *name);
static void mailbox_imap_destroy (mailbox_t *mbox);
struct mailbox_registrar _mailbox_imap_registrar =
{
"IMAP4",
(int)&_url_imap_type, &_url_imap_type,
mailbox_imap_init, mailbox_imap_destroy
};
......
......@@ -15,24 +15,19 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <mailbox0.h>
#include <registrar0.h>
#include <url_mbox.h>
#include <mbx_mbox.h>
#include <mbx_unix.h>
#include <mbx_mdir.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
struct mailbox_type _mailbox_mbox_type =
static int mailbox_mbox_init (mailbox_t *mbox, const char *name);
static void mailbox_mbox_destroy (mailbox_t *mbox);
struct mailbox_registrar _mailbox_mbox_registrar =
{
"UNIX_MBOX/Maildir/MMDF",
(int)&_url_mbox_type, &_url_mbox_type,
mailbox_mbox_init, mailbox_mbox_destroy
};
......@@ -49,7 +44,7 @@ struct mailbox_type _mailbox_mbox_type =
mailbox.
*/
int
static int
mailbox_mbox_init (mailbox_t *mbox, const char *name)
{
struct stat st;
......@@ -65,9 +60,7 @@ mailbox_mbox_init (mailbox_t *mbox, const char *name)
What is the best course of action ??
*/
if (stat (name, &st) < 0)
{
return errno; /* errno set by stat () */
}
return _mailbox_unix_registrar._init (mbox, name);
if (S_ISREG (st.st_mode))
{
......@@ -99,7 +92,7 @@ mailbox_mbox_init (mailbox_t *mbox, const char *name)
if (count == 0) /*empty file*/
{
close (fd);
return mailbox_unix_init (mbox, name);
return _mailbox_unix_registrar._init (mbox, name);
}
if (count >= 5)
......@@ -108,27 +101,26 @@ mailbox_mbox_init (mailbox_t *mbox, const char *name)
{
/* This is Unix Mbox */
close (fd);
return mailbox_unix_init (mbox, name);
return _mailbox_unix_registrar._init (mbox, name);
}
}
/* Try MMDF */
close (fd);
#endif
return mailbox_unix_init (mbox, name);
return _mailbox_unix_registrar._init (mbox, name);
}
else if (S_ISDIR (st.st_mode))
{
/* Is that true ? Are all directories Maildir ?? */
return mailbox_maildir_init (mbox, name);
}
else if (S_ISDIR (st.st_mode))
return _mailbox_maildir_registrar._init (mbox, name);
/* Why can't a mailbox be FIFO ? or a DOOR/Portal ? */
/* Why can't a mailbox be FIFO ? or a DOOR/Portal ??? */
return EINVAL;
}
void
mailbox_mbox_destroy (mailbox_t *mbox)
static void
mailbox_mbox_destroy (mailbox_t *pmbox)
{
(*mbox)->mtype->_destroy (mbox);
if (pmbox && *pmbox)
_mailbox_unix_registrar._destroy (pmbox);
}
......
......@@ -15,14 +15,16 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <url_mdir.h>
#include <mbx_mdir.h>
#include <mailbox0.h>
#include <registrar0.h>
#include <errno.h>
struct mailbox_type _mailbox_maildir_type =
static int mailbox_maildir_init (mailbox_t *mbox, const char *name);
static void mailbox_maildir_destroy (mailbox_t *mbox);
struct mailbox_registrar _mailbox_maildir_registrar =
{
"MAILDIR",
(int)&_url_maildir_type, &_url_maildir_type,
mailbox_maildir_init, mailbox_maildir_destroy
};
......
......@@ -15,10 +15,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <mailbox0.h>
#include <registrar0.h>
#include <dirent.h>
#include <errno.h>
......@@ -26,13 +24,15 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
typedef int _url_mh_type;
static int mailbox_mh_init (mailbox_t *pmbox, const char *name);
static void mailbox_mh_destroy (mailbox_t *pmbox);
struct mailbox_type _mailbox_mh_type =
struct mailbox_registrar _mailbox_mh_registrar =
{
"MH"
(int)&_url_mh_type, &_url_mh_type,
"MH",
mailbox_mh_init, mailbox_mh_destroy
};
......@@ -41,9 +41,12 @@ typedef struct _mh_data
time_t mtime; /* used for checking if mailbox was updated */
} mh_data;
static int mh_open (mailbox_t mbox, int flags);
static int mh_close (mailbox_t mbox);
static int mh_scan (mailbox_t mbox, size_t *msgs);
static int mh_sequence(const char *name);
int
static int
mailbox_mh_init (mailbox_t *pmbox, const char *name)
{
mailbox_t mbox;
......@@ -54,12 +57,16 @@ mailbox_mh_init (mailbox_t *pmbox, const char *name)
mbox->name = malloc(strlen(name) + 1);
strcpy(mbox->name, name);
mbox->data = data;
mbox->_init = mailbox_mh_init;
mbox->_destroy = mailbox_mh_destroy;
mbox->_open = mh_open;
mbox->_close = mh_close;
*pmbox = mbox;
return 0;
}
void
static void
mailbox_mh_destroy (mailbox_t *pmbox)
{
free((*pmbox)->data);
......@@ -77,6 +84,7 @@ mh_open (mailbox_t mbox, int flags)
struct stat st;
mh_data *data;
(void) flags;
if (stat(mbox->name, &st) == -1)
return errno;
......@@ -141,6 +149,7 @@ mh_scan (mailbox_t mbox, size_t *msgs)
closedir(maildir);
if(parse_sequence_file && count) {
FILE *fp;
char *path = malloc(strlen(mbox->name) + strlen(".mh_sequences") + 2);
sprintf(path, "%s/.mh_sequences", mbox->name);
fp = fopen(path, "r");
......@@ -167,7 +176,7 @@ mh_scan (mailbox_t mbox, size_t *msgs)
static int
mh_sequence(const char *name)
{
char *sequence;
const char *sequence;
int i;
for(i = 0, sequence = name; *sequence; sequence++) {
......
......@@ -15,25 +15,28 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <url_mmdf.h>
#include <mbx_mmdf.h>
#include <mailbox0.h>
#include <registrar0.h>
#include <errno.h>
struct mailbox_type _mailbox_mmdf_type =
static int mailbox_mmdf_init (mailbox_t *mbox, const char *name);
static void mailbox_mmdf_destroy (mailbox_t *mbox);
struct mailbox_registrar _mailbox_mmdf_registrar =
{
"MMDF",
(int)&_url_mmdf_type, &_url_mmdf_type,
mailbox_mmdf_init, mailbox_mmdf_destroy
};
int
static int
mailbox_mmdf_init (mailbox_t *mbox, const char *name)
{
(void)mbox; (void)name;
return ENOSYS;
}
void
static void
mailbox_mmdf_destroy (mailbox_t *mbox)
{
(void)mbox;
......
......@@ -15,25 +15,28 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <url_pop.h>
#include <mbx_pop.h>
#include <mailbox0.h>
#include <registrar0.h>
#include <errno.h>
struct mailbox_type _mailbox_pop_type =
static int mailbox_pop_init (mailbox_t *mbox, const char *name);
static void mailbox_pop_destroy (mailbox_t *mbox);
struct mailbox_registrar _mailbox_pop_registrar =
{
"POP3",
(int)&_url_pop_type, &_url_pop_type,
mailbox_pop_init, mailbox_pop_destroy
};
void
static void
mailbox_pop_destroy (mailbox_t *mbox)
{
(void)mbox;
return;
}
int
static int
mailbox_pop_init (mailbox_t *mbox, const char *name)
{
(void)mbox; (void)name;
......
......@@ -15,12 +15,14 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <url_unix.h>
#include <mbx_unix.h>
#include <mailbox0.h>
#include <registrar0.h>
#include <message0.h>
#include <attribute0.h>
#include <auth.h>
#include <locker.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define HAVE_PTHREAD_H
#include <stdlib.h>
#include <stdio.h>
......@@ -30,226 +32,121 @@
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <pthread.h>
#ifdef HAVE_PTHREAD_H
# include <pthread.h>
#else
# define flockfile(arg)
# define funlockfile(arg)
#endif
#include <string.h>
#include <ctype.h>
struct mailbox_type _mailbox_unix_type =
static int mailbox_unix_init (mailbox_t *pmbox, const char *name);
static void mailbox_unix_destroy (mailbox_t *pmbox);
struct mailbox_registrar _mailbox_unix_registrar =
{
"UNIX MBOX",
(int)&_url_unix_type, &_url_unix_type,
mailbox_unix_init, mailbox_unix_destroy
};
typedef struct _mailbox_unix_msg
/*
* Keep a reference of where the header and body starts
* and end.
*/
typedef struct _mailbox_unix_message
{
off_t header;
off_t header_end;
off_t body;
off_t end;
int deleted;
int is_read;
int is_seen;
} *mailbox_unix_msg_t;
off_t body_end;
attribute_t attribute;
} *mailbox_unix_message_t;
typedef struct _mailbox_unix_data
{
mailbox_unix_msg_t messages;
mailbox_unix_message_t messages;
size_t messages_count;
size_t num_deleted;
FILE *file;
char *dirname;
char *basename;
int flags;
#ifdef HAVE_PTHREAD_H
pthread_mutex_t mutex;
#endif
int lock;
int ilock;
time_t mtime;
size_t size;
} *mailbox_unix_data_t;
/* forward prototypes */
static int mailbox_unix_open (mailbox_t mbox, int flag);
static int mailbox_unix_close (mailbox_t mbox);
//static int mailbox_unix_get_name (mailbox_t, int *id, char *name,
// size_t len, size_t *n);
/* passwd */
/* updating/deleting */
static int mailbox_unix_is_deleted (mailbox_t, size_t msgno);
static int mailbox_unix_append_message (mailbox_t, message_t msg);
static int mailbox_unix_messages_count (mailbox_t, size_t *msgno);
static int mailbox_unix_delete (mailbox_t, size_t msgno);
static int mailbox_unix_undelete (mailbox_t, size_t msgno);
static int mailbox_unix_is_deleted (mailbox_t, size_t msgno);
static int mailbox_unix_expunge (mailbox_t);
static int mailbox_unix_is_updated (mailbox_t);
static int mailbox_unix_scan (mailbox_t, size_t *msgs);
/* appending */
static int mailbox_unix_new_msg (mailbox_t, size_t *msgno);
static int mailbox_unix_set_header (mailbox_t, size_t msgno, const char *h,
size_t len, int replace);
static int mailbox_unix_set_body (mailbox_t, size_t msgno, const char *b,
size_t len, int replace);
static int mailbox_unix_append (mailbox_t, size_t msgno);
static int mailbox_unix_destroy_msg (mailbox_t, size_t msgno);
/* reading */
static int mailbox_unix_get_body (mailbox_t, size_t msgno, off_t off,
char *b, size_t len, size_t *n);
static int mailbox_unix_get_header (mailbox_t, size_t msgno, off_t off,
char *h, size_t len, size_t *n);
static int mailbox_unix_num_deleted (mailbox_t, size_t *);
static int mailbox_unix_get_size (mailbox_t, size_t msgno, size_t *header,
size_t *body);
/* setting flags */
static int mailbox_unix_is_read (mailbox_t, size_t msgno);
static int mailbox_unix_set_read (mailbox_t, size_t msgno);
static int mailbox_unix_is_seen (mailbox_t, size_t msgno);
static int mailbox_unix_set_seen (mailbox_t, size_t msgno);
/* owner and group
static int mailbox_unix_set_owner (mailbox_t mbox, uid_t uid);
static int mailbox_unix_get_owner (mailbox_t mbox, uid_t *uid);
static int mailbox_unix_set_group (mailbox_t mbox, gid_t gid);
static int mailbox_unix_get_group (mailbox_t mbox, gid_t *gid);
*/
/* locking */
static int mailbox_unix_lock (mailbox_t, int flag);
static int mailbox_unix_unlock (mailbox_t);
static int mailbox_unix_ilock (mailbox_t, int flag);
static int mailbox_unix_iunlock (mailbox_t);
static int mailbox_unix_scan (mailbox_t, size_t *msgs);
static int mailbox_unix_is_updated (mailbox_t);
static int mailbox_unix_size (mailbox_t, off_t *size);
static ssize_t mailbox_unix_get_header (mailbox_t, size_t msgno, char *h,
size_t len, off_t off, int *err);
static ssize_t mailbox_unix_get_body (mailbox_t, size_t msgno, char *b,
size_t len, off_t off, int *err);
/* private stuff */
static int mailbox_unix_is_from (const char *);
static int mailbox_unix_readhdr (mailbox_t mbox, char *buf, size_t len,
off_t *content_length);
//static int mailbox_unix_sigblock ();
//static int mailbox_unix_sigunblock ();
/* Having a structure initialize at compiletime instead of runtime
may speed thing a bit, but it is a real pain to maintain with
the changing API */
static struct _mailbox unixmbox =
{
/* Data */
(char *)NULL, /* char *name ; */
(uid_t)-1, /* uid_t owner; */
(gid_t)-1, /* gid_t group; */
0, /* messages */
0, /* num_deleted */
(off_t)0, /* size */
0, /* lock */
0, /* timeout; */
0, /* refresh; */
(int (*)())NULL, /* (*func) __P ((mailbox_t, void *arg)) */
/* type of mailbox */
&_mailbox_unix_type, /*struct mailbox_type *mtype; */
/* back pointer to the specific mailbox */
(void *)NULL, /* void *data; */
/* Functions */
mailbox_unix_open, /* (*_open) */
mailbox_unix_close, /* (*_close) */
/* type */
NULL, /* (*_get_name) */
NULL, /* (*_get_mname) */
/* passwd if needed */
NULL, /* (*_get_passwd) */
NULL, /* (*_get_mpasswd) */
NULL, /* (*_set_passwd) */
/* updating/deleting mesgs */
mailbox_unix_is_deleted, /* (*_is_deleted) */
mailbox_unix_delete, /* (*_delete) */
mailbox_unix_undelete, /* (*_undelete) */
mailbox_unix_expunge, /* (*_expunge) */
mailbox_unix_is_updated, /* (*_is_updated) */
mailbox_unix_scan, /* (*_scan) */
/* appending messages */
mailbox_unix_new_msg, /* (*_new_msg) */
mailbox_unix_set_header, /* (*_set_header) */
mailbox_unix_set_body, /* (*_set_body) */
mailbox_unix_append, /* (*_append) */
mailbox_unix_destroy_msg, /* (*_destroy_msg) */
/* external locking */
mailbox_unix_lock, /* (*_lock) */
mailbox_unix_unlock, /* (*_unlock) */
/* internal locking */
mailbox_unix_ilock, /* (*_ilock) */
mailbox_unix_iunlock, /* (*_iunlock) */
/* reading mesgs */
mailbox_unix_get_body, /* (*_get_body) */
NULL, /* (*_get_mbody) */
mailbox_unix_get_header, /* (*_get_header) */
NULL, /* (*_get_mheader) */
mailbox_unix_get_size, /* (*_get_msg_size) */
/* setting flags */
mailbox_unix_is_read, /* (*_msg_is_read) */
mailbox_unix_set_read, /* (*_msg_set_read) */
mailbox_unix_is_seen, /* (*_msg_is_seen) */
mailbox_unix_set_seen, /* (*_msg_set_seen) */
/* owner and group */
NULL, /* (*_set_owner) */
NULL, /* (*_get_owner) */
NULL, /* (*_set_group) */
NULL, /* (*_get_group) */
mailbox_unix_size, /* (*_size) */
NULL, /* (*_get_timeout) */
NULL, /* (*_set_timeout) */
NULL, /* (*_get_refresh) */
NULL, /* (*_set_refresh) */
NULL, /* (*_set_notification) */
};
off_t *content_length, attribute_t attr);
static int mailbox_unix_lock (mailbox_t mbox, int flag);
static int mailbox_unix_unlock (mailbox_t mbox);
static int mailbox_unix_ilock (mailbox_t mbox, int flag);
static int mailbox_unix_iunlock (mailbox_t mbox);
int
static int
mailbox_unix_init (mailbox_t *pmbox, const char *name)
{
mailbox_t mbox;
size_t len;
mailbox_unix_data_t mud;
char *sep;
const char *sep;
size_t name_len;
int i;
/* sanity check */
if (name == NULL || *name == '\0')
{
return EINVAL;
}
name_len = strlen (name);
#define UNIX_SCHEME "unix:"
#define UNIX_SCHEME_LEN 5
#define SEPARATOR '/'
/* pass the url */
sep = strstr (name, "unix://");
if (sep)
name += 7;
if (name_len > UNIX_SCHEME_LEN &&
name[0] == 'u' && name[1] == 'n' &&
name[2] == 'i' && name[3] == 'x' &&
name[4] == ':')
{
name += UNIX_SCHEME_LEN;
name_len -= UNIX_SCHEME_LEN;
}
/* allocate memory for mbox */
mbox = calloc (1, sizeof (*mbox));
if (mbox == NULL)
{
return ENOMEM; /* errno set by calloc() */
}
/* FIXME: what does the next comment mean? */
/* binary copy of the function */
*mbox = unixmbox;
return ENOMEM;
/* specific unix mbox data */
/* allocate specific unix mbox data */
mud = mbox->data = calloc (1, sizeof (*mud));
if (mbox->data == NULL)
{
......@@ -258,21 +155,29 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name)
}
/* copy the name */
len = strlen (name) + 1;
mbox->name = calloc (len, sizeof (char));
mbox->name = calloc (name_len + 1, sizeof (char));
if (mbox->name == NULL)
{
mailbox_unix_destroy (&mbox);
return ENOMEM;
}
memcpy (mbox->name, name, len);
memcpy (mbox->name, name, name_len);
/* save the basename and dirname */
sep = strrchr (name, '/');
for (i = name_len, sep = NULL; i >= 0; i--)
{
/* break on the first separator */
if (name[i] == SEPARATOR)
{
sep = &(name[i]);
break;
}
}
if (sep)
{
size_t baseln;
mud->dirname = calloc (sep - name + 1, sizeof (char));
/* split it into two */
mud->dirname = calloc ((sep - name) + 1, sizeof (char));
if (mud->dirname == NULL)
{
mailbox_unix_destroy (&mbox);
......@@ -280,17 +185,19 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name)
}
memcpy (mud->dirname, name, sep - name);
baseln = strlen (++sep) + 1;
mud->basename = calloc (baseln, sizeof (char));
++sep;
mud->basename = calloc (name_len - (sep - name) + 1, sizeof (char));
if (mud->basename == NULL)
{
mailbox_unix_destroy (&mbox);
return ENOMEM;
}
memcpy (mud->basename, sep, baseln);
memcpy (mud->basename, sep, name_len - (sep - name));
}
else
{
/* use the relative directory "." */
/* FIXME: should we call getcwd() instead ? */
mud->dirname = calloc (2 , sizeof (char));
if (mud->dirname == NULL)
{
......@@ -299,13 +206,13 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name)
}
mud->dirname[0] = '.';
mud->basename = calloc (len, sizeof (char));
mud->basename = calloc (name_len + 1, sizeof (char));
if (mud->basename == NULL)
{
mailbox_unix_destroy (&mbox);
return ENOMEM;
}
memcpy (mud->basename, name, len);
memcpy (mud->basename, name, name_len);
}
/* mutex when accessing the structure fields */
......@@ -314,13 +221,35 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name)
pthread_mutex_init (&(mud->mutex), NULL);
#endif
mbox->_init = mailbox_unix_init;
mbox->_destroy = mailbox_unix_destroy;
mbox->_open = mailbox_unix_open;
mbox->_close = mailbox_unix_close;
/* messages */
mbox->_append_message = mailbox_unix_append_message;
mbox->_messages_count = mailbox_unix_messages_count;
mbox->_delete = mailbox_unix_delete;
mbox->_undelete = mailbox_unix_undelete;
mbox->_is_deleted = mailbox_unix_is_deleted;
mbox->_expunge = mailbox_unix_expunge;
mbox->_num_deleted = mailbox_unix_num_deleted;
mbox->_get_size = mailbox_unix_get_size;
mbox->_is_updated = mailbox_unix_is_updated;
mbox->_size = mailbox_unix_size;
mbox->_get_header = mailbox_unix_get_header;
mbox->_get_body = mailbox_unix_get_body;
(*pmbox) = mbox;
return 0; /* okdoke */
}
void
static void
mailbox_unix_destroy (mailbox_t *pmbox)
{
if (pmbox && *pmbox)
......@@ -329,58 +258,71 @@ mailbox_unix_destroy (mailbox_t *pmbox)
mailbox_unix_close (mbox);
if (mbox->data)
{
size_t i;
mailbox_unix_data_t mud = mbox->data;
if (mud->dirname)
free (mud->dirname);
if (mud->basename)
free (mud->basename);
if (mud->messages)
for (i = 0; i < mud->messages_count; i++)
{
/* orphan the message */
mud->messages[i].attribute->message = NULL;
attribute_destroy (&(mud->messages[i].attribute));
}
free (mud->messages);
free (mbox->data);
}
if (mbox->name)
free (mbox->name);
if (mbox->messages)
{
size_t i;
for (i = 0; i < mbox->messages_num; i++)
{
/* first orphan them */
mbox->messages[i]->mailbox = NULL;
message_destroy (&(mbox->messages[i]));
}
}
free (mbox->messages);
free (*pmbox);
pmbox = NULL;
*pmbox = NULL;
}
}
/* start of Mbox Implementation */
/* start of mbox Implementation */
static int
mailbox_unix_open (mailbox_t mbox, int flags)
{
mailbox_unix_data_t mud = mbox->data;
mailbox_unix_data_t mud;
int fd = -1;
int flg = 0;
char * mode;
char *mode;
/*
FIXME: This is another problem, should we have a special set of flags
MU_MB_{CREAT,APPEND,RDONLY,RDWR} or use the default open(2)
and if RDONLY, should we have some security checks ?
*/
if (flags & MU_MB_WRONLY)
{
if (mbox == NULL ||
(mud = (mailbox_unix_data_t)mbox->data) == NULL)
return EINVAL;
if (flags & MU_MAILBOX_WRONLY)
flg = O_WRONLY;
}
else if (flags & MU_MB_RDWR)
{
else if (flags & MU_MAILBOX_RDWR)
flg = O_RDWR;
}
else /* default */
{
flg = O_RDONLY;
}
if (flags & MU_MB_APPEND)
{
/* FIXME: only if the file is open Write */
if (flags & MU_MAILBOX_APPEND)
flg |= O_APPEND;
}
/* FIXME: does not really work, but local folders
* should not block since it is local disk ???
*/
if (flags & MU_MAILBOX_NONBLOCK)
flg |= O_NONBLOCK;
/* handle CREAT with care, not to follow symlinks */
if (flags & MU_MB_CREAT)
if (flags & MU_MAILBOX_CREAT)
{
/* Grab the lock for any race conditions */
mailbox_unix_lock (mbox, MU_LOCKER_WRLOCK);
{
/* first see if the file already exists */
fd = open(mbox->name, flg);
......@@ -388,55 +330,52 @@ mailbox_unix_open (mailbox_t mbox, int flags)
{
/* oops bail out */
if (errno != ENOENT)
{
return errno;
}
/* Create the file */
fd = open(mbox->name, flg|O_CREAT|O_EXCL, 0600);
if (fd < 0)
{
return errno;
}
}
/*
FIXME: How about owner(uid), to whom we set it to ?
do We need a _set_owner(uid) to mailbox_t
*/
(void)fchown (fd, mbox->owner, mbox->group);
/* FIXME: should we have a mode field ? */
(void)fchmod (fd, 0600);
if (mbox->auth)
{
auth_t auth = mbox->auth;
gid_t g ; uid_t u; mode_t m;
g = u = -1; m = 0600;
/* FIXME: what to do when they failed */
auth_get_owner (auth, &u);
auth_get_group (auth, &g);
auth_get_mode (auth, &m);
(void)fchown (fd, u, g);
(void)fchmod (fd, m);
}
}
mailbox_unix_unlock (mbox);
}
else
{
fd = open (mbox->name, flg);
if (fd < 0)
{
return errno;
}
}
/* we use FILE * object */
if (flg & MU_MB_RDWR)
{
if (flags & MU_MAILBOX_APPEND)
mode = "a";
else if (flags & MU_MAILBOX_RDWR)
mode = "r+";
}
else if (flg & MU_MB_WRONLY)
{
else if (flags & MU_MAILBOX_WRONLY)
mode = "w";
}
else if (flg & MU_MB_APPEND)
{
mode = "a";
}
else /* default readonly*/
{
mode = "r";
}
/* clean up */
/* clean up, make sure there was nothing before */
mailbox_unix_close (mbox);
mailbox_unix_ilock (mbox, MU_MB_WRLOCK);
mailbox_unix_ilock (mbox, MU_LOCKER_WRLOCK);
{
mud->file = fdopen (fd, mode);
if (mud->file == NULL)
......@@ -445,15 +384,15 @@ mailbox_unix_open (mailbox_t mbox, int flags)
mailbox_unix_iunlock (mbox);
return ENOMEM;
}
/* Is this necessary ?? */
/* Check to make sure this is indeed a Unix Mail format */
flockfile (mud->file);
{
char buf [BUFSIZ];
if (fgets (buf, sizeof (buf), mud->file) == NULL)
{
if (feof (mud->file))
{
clearerr (mud->file); /* the file maybe empty */
}
else if (ferror (mud->file))
{
mailbox_unix_iunlock (mbox);
......@@ -470,88 +409,108 @@ mailbox_unix_open (mailbox_t mbox, int flags)
return EIO;
}
else
{
rewind (mud->file);
}
}
}
funlockfile (mud->file);
}
mailbox_unix_iunlock (mbox);
mud->flags = flags;
return 0;
}
static int
mailbox_unix_close (mailbox_t mbox)
{
mailbox_unix_data_t mud = (mailbox_unix_data_t)mbox->data;
mailbox_unix_ilock (mbox, MU_MB_WRLOCK);
{
mailbox_unix_data_t mud;
/* make sure we do not hold any lock for that file */
if (mbox == NULL ||
(mud = (mailbox_unix_data_t)mbox->data) == NULL)
return EINVAL;
mailbox_unix_unlock (mbox);
if (mud->file)
mailbox_unix_ilock (mbox, MU_LOCKER_WRLOCK);
{
if (mud->file)
fclose (mud->file);
}
mud->file = NULL;
/* make sure we do not hold any lock for that file */
mailbox_unix_unlock (mbox);
}
mailbox_unix_iunlock (mbox);
return 0;
}
/*
static int
mailbox_unix_get_name (mailbox_t mbox, int *id, char *name,
size_t len, size_t *n)
{
char *s = _mailbox_unix_type.name;
size_t i = strlen (s);
if (id)
{
*id = _mailbox_unix_type.id;
}
if (name && len > 0)
{
i = (len < i) ? len : i;
strncpy (name, s, i - 1);
name [i - 1] = 0;
}
if (n)
{
*n = i;
}
return 0;
}
*/
/* passwd */
/* We don't care */
/* FIXME: hmmm, all of the files i check lack a timezone field */
/* FIXME: a little weak, we should do full reconnaissance of the
the "From " header :
From email weekday month day time timezone year
* the "From " header :
* From <user> <weekday> <month> <day> <hr:min:sec>
* [T1 [T2]] <year> [remote-list]
*/
static int
mailbox_unix_is_from (const char *from)
{
const char *sep;
return (strncmp (from, "From ", 5) == 0
&& (sep = strchr (from, ':')) != NULL
&& strchr (sep, ':') != NULL);
/* From_ */
if (strncmp (from, "From ", 5) != 0)
return 0;
from += 5;
/* <user> */
sep = strchr (from, ' ');
if (sep == NULL)
return 0;
from = ++sep;
/* weekday */
sep = strchr (from, ' ');
if (sep == NULL)
return 0;
from = ++sep;
/* month */
sep = strchr (from, ' ');
if (sep == NULL)
return 0;
from = ++sep;
/* day */
sep = strchr (from, ' ');
if (sep == NULL)
return 0;
from = ++sep;
/* hr:min:sec */
/* hr */
sep = strchr (from, ':');
if (sep == NULL)
return 0;
from = ++sep;
/* min */
sep = strchr (from, ':');
if (sep == NULL)
return 0;
from = ++sep ;
/* sec */
sep = strchr (from, ' ');
if (sep == NULL)
return 0;
/* FIXME PLEASE: the rest is getting more complex, finish it later */
return 1;
}
/*
* We skip over the rest of the header. Scan for
* Status: to set the attribute. Hopfully the Content-Length
* in there too.
*/
static int
mailbox_unix_readhdr (mailbox_t mbox, char *buf, size_t len,
off_t *content_length)
off_t *content_length, attribute_t attribute)
{
mailbox_unix_data_t mud = (mailbox_unix_data_t)mbox->data;
mailbox_unix_msg_t mum = mud->messages;
char *sep;
size_t count = mbox->messages;
/* skip over the remaining header */
while (fgets (buf, len, mud->file))
......@@ -563,9 +522,7 @@ mailbox_unix_readhdr (mailbox_t mbox, char *buf, size_t len,
*/
if (strcmp (buf, "\n") == 0 || strcmp (buf, "\r\n") == 0
|| (isalpha (buf[0]) && (sep = strchr (buf, ':')) == NULL))
{
break;
}
/* get the the Content lenght of the body if possible */
if (strncmp (buf, "Content-Length:", 15) == 0)
{
......@@ -573,27 +530,34 @@ mailbox_unix_readhdr (mailbox_t mbox, char *buf, size_t len,
sep[strlen (sep) - 1] = '\0'; /* chop the newline */
*content_length = strtol (sep + 1, NULL, 10);
}
/* Set the attribute */
if (strncmp (buf, "Status:", 7) == 0)
{
sep = strchr(buf, ':'); /* pass the ':' */
if (strchr (sep, 'R') != NULL)
{
mum[count - 1].is_read = 1;
}
attribute_set_read (attribute);
if (strchr (sep, 'O') != NULL)
{
mum[count - 1].is_seen = 1;
}
attribute_set_seen (attribute);
if (strchr (sep, 'A') != NULL)
attribute_set_answered (attribute);
if (strchr (sep, 'F') != NULL)
attribute_set_flagged (attribute);
}
}
/* check for any dubious conditions */
if (feof (mud->file) || ferror (mud->file))
{
return EIO;
}
return 0;
}
/* Updating/deleting */
/* Parsing.
* This a bit fragile, I need to secure this.
* The approach is to detect the "From " as start of a
* new message give the position of the header and scan
* until "\n" set header_end, set body position, we have
* a Content-Length header jump to the point if not
* scan until we it another "From " and set body_end.
*/
static int
mailbox_unix_scan (mailbox_t mbox, size_t *msgs)
{
......@@ -602,139 +566,131 @@ mailbox_unix_scan (mailbox_t mbox, size_t *msgs)
int body = 0;
off_t content_length = -1;
size_t count = 0;
mailbox_unix_data_t mud = (mailbox_unix_data_t) mbox->data;
mailbox_unix_msg_t mum;
mailbox_unix_data_t mud;
mailbox_unix_message_t mum;
struct stat st;
mailbox_unix_ilock (mbox, MU_MB_WRLOCK);
/* FIXME: please clarify next comment */
/* FIXME: I should also block signals since
We can affor to be intr */
if (mbox == NULL ||
(mud = (mailbox_unix_data_t)mbox->data) == NULL)
return EINVAL;
/* FIXME: I should also block signals and check cancelstate(Pthread)
since We can not afford to be intr */
mailbox_unix_ilock (mbox, MU_LOCKER_WRLOCK);
mailbox_unix_lock (mbox, MU_LOCKER_RDLOCK);
flockfile (mud->file);
rewind (mud->file);
if (fstat (fileno (mud->file), &st) != 0)
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
mailbox_unix_unlock (mbox);
return EIO;
}
mud->mtime = st.st_mtime;
mud->size = st.st_size;
rewind (mud->file);
while (fgets (buf, sizeof (buf), mud->file))
{
if (mailbox_unix_is_from (buf))
{
if (body && count)
{
int over = strlen (buf);
mum[count - 1].body_end = ftell (mud->file);
mum[count - 1].body_end -= (over + 1);
body = 0;
}
header = 1;
}
/* header */
if ((header && mailbox_unix_is_from (buf)))
if (header)
{
/* FIXME: What happen if some mailer violates the rfc822 and the
"From " field contains a NULL byte */
int over = strlen (buf);
count++;
if (count > mbox->messages)
/* FIXME: This is a bad idea, we should not be allowed to
* jump out from the scanning this way. We sit at the mercy
* of this function(_progress) waiting for disaster.
*/
if (mbox->_progress)
{
/* FIXME: and its getting better, they can even bailout */
if (mbox->_progress (count, mbox->progress_arg) != 0)
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
mailbox_unix_unlock (mbox);
return EINTR;
}
}
if (count > mud->messages_count)
{
mum = realloc (mud->messages, count * sizeof (*mum));
if (mum == NULL)
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
mailbox_unix_unlock (mbox);
return ENOMEM;
}
mbox->messages++;
mud->messages_count++;
memset (&mum[count - 1], 0, sizeof (*mum));
attribute_init (&(mum[count - 1].attribute));
}
mud->messages = mum;
mum[count - 1].header = ftell (mud->file);
mum[count - 1].header -= over;
/* skip over the remaining header */
if (mailbox_unix_readhdr (mbox, buf, sizeof (buf),
&content_length) != 0)
if (mailbox_unix_readhdr (mbox, buf, sizeof (buf), &content_length,
mum[count - 1].attribute) != 0)
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
mailbox_unix_unlock (mbox);
return EIO;
}
mum[count - 1].header_end = ftell (mud->file) - strlen(buf);
header = 0;
body = !header;
} /* header */
/* body */
if (body && content_length >= 0)
{
/* ouf ! we got the size */
mum[count - 1].body = ftell (mud->file) - strlen (buf);
fseek (mud->file, content_length, SEEK_CUR);
mum[count - 1].end = ftell (mud->file);
content_length = -1;
header = 1;
body = !header;
}
else if (body)
if (body)
{
/* oops! some heuristic since we do not know the size of the body */
if (mum[count - 1].body == 0)
{
mum[count - 1].body = ftell (mud->file) - strlen (buf);
}
mum[count - 1].body = ftell (mud->file);
if (mailbox_unix_is_from (buf))
{
int over = strlen (buf);
mum[count - 1].end = ftell (mud->file);
mum[count - 1].end -= over;
count++;
if (count > mbox->messages)
{
mum = realloc (mud->messages, count * sizeof (*mum));
if (mum == NULL)
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
return ENOMEM;
}
mbox->messages++;
memset (&mum[count - 1], 0, sizeof (*mum));
}
mud->messages = mum;
mum[count - 1].header = ftell (mud->file);
mum[count - 1].header -= over;
/* skip over the remaining header */
if (mailbox_unix_readhdr (mbox, buf, sizeof (buf),
&content_length) != 0)
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
return EIO;
}
mum[count - 1].body = ftell (mud->file) - strlen (buf);
if (content_length >= 0)
{
/* ouf ! we got the size */
mum[count - 1].body_end = mum[count -1].body + content_length;
fseek (mud->file, content_length, SEEK_CUR);
mum[count - 1].end = ftell (mud->file);
content_length = -1;
header = 0;
body = !header;
body = 0;
}
}
} /* body */
} /* while */
mum[count - 1].end = ftell (mud->file);
mum[count - 1].body_end = ftell (mud->file);
if (feof (mud->file))
{
clearerr (mud->file);
}
else if (ferror (mud->file))
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
mailbox_unix_unlock (mbox);
return EIO;
}
rewind (mud->file);
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
mailbox_unix_unlock (mbox);
if (msgs)
*msgs = count;
return 0;
......@@ -743,118 +699,132 @@ mailbox_unix_scan (mailbox_t mbox, size_t *msgs)
static int
mailbox_unix_is_updated (mailbox_t mbox)
{
mailbox_unix_data_t mud = (mailbox_unix_data_t) mbox->data;
mailbox_unix_data_t mud;
struct stat st;
if (mud == 0 || fstat (fileno (mud->file), &st) < 0)
{
if (mbox == NULL ||
(mud = (mailbox_unix_data_t)mbox->data) == NULL ||
fstat (fileno (mud->file), &st) < 0)
return 0;
}
return (mud->mtime == st.st_mtime);
}
static int
mailbox_unix_is_valid (mailbox_t mbox, size_t msgno)
{
mailbox_unix_data_t mud;
if (mbox == NULL || (mud = (mailbox_unix_data_t) mbox->data) == NULL)
return 0;
/* valid ? */
return (mbox->messages > 0 && msgno <= mbox->messages);
return (mud->messages_count > 0 && msgno <= mud->messages_count);
}
static int
mailbox_unix_is_deleted (mailbox_t mbox, size_t msgno)
{
mailbox_unix_data_t mud = (mailbox_unix_data_t) mbox->data;
mailbox_unix_data_t mud;
/* Do we have a consistent view of the mbox ? */
if (mud == NULL || ! mailbox_unix_is_valid (mbox, msgno))
{
if (mbox == NULL ||
(mud = (mailbox_unix_data_t)mbox->data) == NULL ||
! mailbox_unix_is_valid (mbox, msgno))
return 0;
}
return mud->messages[msgno].deleted;
return attribute_is_deleted (mud->messages[msgno].attribute);
}
static int
mailbox_unix_delete (mailbox_t mbox, size_t msgno)
{
mailbox_unix_data_t mud = (mailbox_unix_data_t) mbox->data;
mailbox_unix_data_t mud;
if (mbox == NULL ||
(mud = (mailbox_unix_data_t) mbox->data) == NULL)
return EINVAL;
/* oops out of range ? */
/* if already deleted, noop */
if (mud == NULL || ! mailbox_unix_is_valid (mbox, msgno)
|| mailbox_unix_is_deleted (mbox, msgno))
{
if (! mailbox_unix_is_valid (mbox, msgno) ||
mailbox_unix_is_deleted (mbox, msgno))
return 0;
}
/* Mark for deletion */
mud->messages[msgno].deleted = 1;
mbox->num_deleted++;
attribute_set_deleted (mud->messages[msgno].attribute);
mud->num_deleted++;
return 0;
}
static int
mailbox_unix_num_deleted (mailbox_t mbox, size_t *num)
{
mailbox_unix_data_t mud;
if (mbox == NULL ||
(mud = (mailbox_unix_data_t) mbox->data) == NULL)
return EINVAL;
if (num)
*num = mud->num_deleted;
return 0;
}
static int
mailbox_unix_undelete (mailbox_t mbox, size_t msgno)
{
mailbox_unix_data_t mud = (mailbox_unix_data_t) mbox->data;
mailbox_unix_data_t mud;
if (mbox == NULL ||
(mud = (mailbox_unix_data_t) mbox->data) == NULL)
return EINVAL;
/* oops out of range ? */
/* if already undeleted, noop */
if (mud == 0 || ! mailbox_unix_is_valid (mbox, msgno)
|| ! mailbox_unix_is_deleted (mbox, msgno))
{
if (! mailbox_unix_is_valid (mbox, msgno) ||
! mailbox_unix_is_deleted (mbox, msgno))
return 0;
}
/* Mark undeletion */
mud->messages[msgno].deleted = 0;
mbox->num_deleted--;
attribute_unset_deleted (mud->messages[msgno].attribute);
mud->num_deleted--;
return 0;
}
/*
FIXME: the use of tmpfile() on some system can lead to
race condition, We should use a safer approach.
We take a very naive approach for this, it involves unfortunately
two copies.
*/
static FILE *
mailbox_unix_tmpfile ()
{
/*FIXME: racing conidtions, to correct, .i.e don;t use tmpfile*/
/*FIXME: racing conditions, to correct, .i.e don;t use tmpfile*/
//return tmpfile ();
return fopen ("/tmp/mymail", "w");
}
/*
FIXME: the use of tmpfile() on some system can lead to
race condition, We should use a safer approach.
We take a very naive approach to this, it involves unfortunately
two copies.
*/
static int
mailbox_unix_expunge (mailbox_t mbox)
{
mailbox_unix_data_t mud = (mailbox_unix_data_t)mbox->data;
mailbox_unix_msg_t mum;
mailbox_unix_data_t mud;
mailbox_unix_message_t mum;
sigset_t sigset;
FILE *tmpfile;
size_t i;
off_t total = 0;
char buffer [BUFSIZ];
if (mud == NULL)
{
if (mbox == NULL ||
(mud = (mailbox_unix_data_t)mbox->data) == NULL)
return EINVAL;
}
if (mbox->messages == 0 || mbox->num_deleted <= 0)
{
/* noop */
if (mud->messages_count == 0 || mud->num_deleted <= 0)
return 0;
}
tmpfile = mailbox_unix_tmpfile ();
if (tmpfile == NULL)
{
return errno;
}
/* Get the lock */
mailbox_unix_ilock (mbox, MU_MB_RDLOCK);
mailbox_unix_ilock (mbox, MU_LOCKER_RDLOCK);
flockfile (mud->file);
if (mailbox_unix_lock (mbox, MU_MB_WRLOCK) < 0)
if (mailbox_unix_lock (mbox, MU_LOCKER_WRLOCK) < 0)
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
......@@ -873,13 +843,12 @@ mailbox_unix_expunge (mailbox_t mbox)
return EAGAIN;
}
rewind (mud->file);
/* copy to temp file emails not mark deleted emails */
for (i = 1; i <= mbox->messages; i++)
for (i = 1; i <= mud->messages_count; i++)
{
mum = &mud->messages[i];
if ( ! mum->deleted)
if ( ! attribute_is_deleted (mum->attribute))
{
size_t len = mum->body - mum->header;
size_t nread;
......@@ -908,10 +877,8 @@ mailbox_unix_expunge (mailbox_t mbox)
total += nread;
}
/* FIXME: We should set the seen flag also here */
/* copy the body */
len = mum->end - mum->body;
len = mum->body_end - mum->body;
if (fseek (mud->file, mum->body, SEEK_SET) < 0)
{
mailbox_unix_unlock (mbox);
......@@ -987,265 +954,290 @@ mailbox_unix_expunge (mailbox_t mbox)
return 0;
}
/* appending */
static int
mailbox_unix_new_msg (mailbox_t mbox, size_t *msgno)
{
(void)mbox; (void)msgno;
return ENOSYS;
}
static int
mailbox_unix_set_header (mailbox_t mbox, size_t msgno, const char *h,
size_t len, int replace)
{
(void)mbox; (void)msgno; (void)h; (void)len; (void)replace;
return ENOSYS;
}
static int
mailbox_unix_set_body (mailbox_t mbox, size_t msgno, const char *b,
size_t len, int replace)
{
(void)mbox; (void)msgno; (void)b; (void)len; (void)replace;
return ENOSYS;
}
static int
mailbox_unix_append (mailbox_t mbox, size_t msgno)
{
(void)mbox; (void)msgno;
return ENOSYS;
}
static int
mailbox_unix_destroy_msg (mailbox_t mbox, size_t msgno)
{
(void)mbox; (void)msgno;
return ENOSYS;
}
/* reading */
static int
mailbox_unix_get_body (mailbox_t mbox, size_t msgno, off_t off,
char *buffer, size_t len, size_t *n)
static ssize_t
mailbox_unix_get_body (mailbox_t mbox, size_t msgno, char *buffer,
size_t len, off_t off, int *err)
{
mailbox_unix_data_t mud = (mailbox_unix_data_t) mbox->data;
size_t nread;
mailbox_unix_data_t mud;
size_t nread = 0;
if (mbox == NULL ||
(mud = (mailbox_unix_data_t)mbox->data) == NULL)
{
if (err)
*err = EINVAL;
return -1;
}
/* check if valid */
if (len < 1 || mud == NULL || ! mailbox_unix_is_valid (mbox, msgno))
{
return EINVAL;
if (err)
*err = EINVAL;
return -1;
}
mailbox_unix_ilock (mbox, MU_MB_RDLOCK);
mailbox_unix_ilock (mbox, MU_LOCKER_RDLOCK);
flockfile (mud->file);
{
mailbox_unix_msg_t mum = &(mud->messages[msgno]);
off_t ln = mum->end - mum->body + off;
if (ln < 0)
mailbox_unix_message_t mum = &(mud->messages[msgno]);
off_t ln = mum->body_end - (mum->body + off);
if (ln > 0)
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
return EIO;
}
nread = ((size_t)ln < len) ? ln : len;
/* position the file pointer and the buffer */
if (fseek (mud->file, mum->body + off, SEEK_SET) < 0)
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
return EIO;
if (err)
*err = EIO;
return -1;
}
if (fread (buffer, sizeof (*buffer), nread, mud->file) != nread)
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
return EIO;
if (err)
*err = EIO;
return -1;
}
}
buffer[nread - 1] = '\0';
else
nread = 0;
}
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
if (n)
*n = nread;
return 0;
return nread;
}
static int
mailbox_unix_get_header (mailbox_t mbox, size_t msgno, off_t off,
char *buffer, size_t len, size_t *n)
static ssize_t
mailbox_unix_get_header (mailbox_t mbox, size_t msgno, char *buffer,
size_t len, off_t off, int *err)
{
mailbox_unix_data_t mud = (mailbox_unix_data_t) mbox->data;
mailbox_unix_data_t mud;
size_t nread = 0;
if (mbox == NULL ||
(mud = (mailbox_unix_data_t)mbox->data) == NULL)
{
if (err)
*err = EINVAL;
return -1;
}
/* check if valid */
if ( len < 1 || mud == NULL || ! mailbox_unix_is_valid (mbox, msgno))
if (len < 1 || ! mailbox_unix_is_valid (mbox, msgno))
{
return EINVAL;
if (err)
*err = EINVAL;
return -1;
}
mailbox_unix_ilock (mbox, MU_MB_RDLOCK);
mailbox_unix_ilock (mbox, MU_LOCKER_RDLOCK);
flockfile (mud->file);
{
mailbox_unix_msg_t mum = &(mud->messages[msgno]);
off_t ln = mum->body - mum->header + off;
if (ln < 0)
mailbox_unix_message_t mum = &(mud->messages[msgno]);
off_t ln = mum->header_end - (mum->header + off);
if (ln > 0)
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
return EIO;
}
nread = ((size_t)ln < len) ? ln : len;
/* position the file pointer and the buffer */
if (fseek (mud->file, mum->header + off, SEEK_SET) < 0)
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
return EIO;
if (err)
*err = EIO;
return -1;
}
if (fread (buffer, sizeof (*buffer), nread, mud->file) != nread)
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
return EIO;
if (err)
*err = EIO;
return -1;
}
}
buffer[nread - 1] = '\0';
else
nread = 0;
}
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
if (n)
*n = nread;
return 0;
return nread;
}
/* setting flags */
static int
mailbox_unix_is_read (mailbox_t mbox, size_t msgno)
mailbox_unix_append_message (mailbox_t mbox, message_t msg)
{
mailbox_unix_data_t mud = (mailbox_unix_data_t) mbox->data;
if (mud == 0 || ! mailbox_unix_is_valid (mbox, msgno))
mailbox_unix_data_t mud;
if (mbox == NULL || msg == NULL ||
(mud = (mailbox_unix_data_t)mbox->data) == NULL)
return EINVAL;
if (! ((mud->flags & MU_MAILBOX_APPEND) ||
(mud->flags & MU_MAILBOX_RDWR) ||
(mud->flags & MU_MAILBOX_WRONLY)))
return EACCES;
mailbox_unix_lock (mbox, MU_LOCKER_WRLOCK);
flockfile (mud->file);
{
return 0;
}
return mud->messages[msgno].is_read;
}
struct stat st;
int fd;
char buffer[BUFSIZ];
header_t hdr;
off_t off = 0;
int err;
size_t nread;
static int
mailbox_unix_set_read (mailbox_t mbox, size_t msgno)
{
mailbox_unix_data_t mud = (mailbox_unix_data_t) mbox->data;
if (mud == 0 || ! mailbox_unix_is_valid (mbox, msgno))
fd = fileno (mud->file);
if (fstat (fd, &st) != 0)
{
return EINVAL;
funlockfile (mud->file);
mailbox_unix_unlock (mbox);
return errno;
}
mud->messages[msgno].is_read = 1;;
return 0;
}
static int
mailbox_unix_is_seen (mailbox_t mbox, size_t msgno)
{
mailbox_unix_data_t mud = (mailbox_unix_data_t) mbox->data;
if (mud == 0 || ! mailbox_unix_is_valid (mbox, msgno))
if (fseek(mud->file, st.st_size, SEEK_SET) != 0)
{
return 0;
funlockfile (mud->file);
mailbox_unix_unlock (mbox);
return errno;
}
message_get_header (msg, &hdr);
if (st.st_size != 0)
fputc ('\n', mud->file);
while ((nread = header_get_data (hdr, buffer, sizeof (buffer),
off, &err)) > 0)
{
fwrite (buffer, sizeof (*buffer), nread, mud->file);
off += nread;
}
fputc ('\n', mud->file);
off = 0;
while ((nread = message_get_content (msg, buffer, sizeof (buffer),
off, &err)) > 0)
{
fwrite (buffer, sizeof (*buffer), nread, mud->file);
off += nread;
}
return mud->messages[msgno].is_seen;
}
fflush(mud->file);
funlockfile (mud->file);
mailbox_unix_unlock (mbox);
return 0;
}
static int
mailbox_unix_set_seen (mailbox_t mbox, size_t msgno)
mailbox_unix_size (mailbox_t mbox, off_t *size)
{
mailbox_unix_data_t mud = (mailbox_unix_data_t) mbox->data;
if (mud == 0 || ! mailbox_unix_is_valid (mbox, msgno))
{
mailbox_unix_data_t mud;
struct stat st;
int fd;
if (mbox == NULL ||
(mud = (mailbox_unix_data_t)mbox->data) == NULL)
return EINVAL;
}
mud->messages[msgno].is_seen = 1;
/* maybe was not open yet ?? */
if (mud->file == NULL)
return EIO;
fd = fileno (mud->file);
/* oops !! */
if (fstat (fd, &st) != 0)
return errno;
*size = st.st_size;
return 0;
}
/* locking */
static int
mailbox_unix_ilock (mailbox_t mbox, int flag)
mailbox_unix_get_size (mailbox_t mbox, size_t msgno, size_t *h, size_t *b)
{
#ifdef HAVE_PTHREAD_H
mailbox_unix_data_t mud = (mailbox_unix_data_t) mbox->data;
(void)flag; /* we should use rwlocks for more concurency */
pthread_mutex_lock (&(mud->mutex));
#else
(void)mbox; (void)flag;
#endif
mailbox_unix_data_t mud;
mailbox_unix_message_t mum;
if (mbox == NULL ||
(mud = (mailbox_unix_data_t)mbox->data) == NULL)
return EINVAL;
if (mailbox_unix_is_valid (mbox, msgno))
return EINVAL;
mum = &(mud->messages[msgno]);
if (h)
*h = mum->header_end - mum->header;
if (b)
*b = mum->body_end - mum->body;
return 0;
}
static int
mailbox_unix_iunlock (mailbox_t mbox)
static int mailbox_unix_messages_count (mailbox_t mbox, size_t *count)
{
#ifdef HAVE_PTHREAD_H
mailbox_unix_data_t mud = (mailbox_unix_data_t) mbox->data;
pthread_mutex_unlock (&(mud->mutex));
#else
(void)mbox;
#endif
mailbox_unix_data_t mud;
if (mbox == NULL || (mud = (mailbox_unix_data_t) mbox->data) == NULL)
return EINVAL;
if (! mailbox_is_updated (mbox))
return mailbox_unix_scan (mbox, count);
if (count)
*count = mud->messages_count;
return 0;
}
/* locking */
static int
mailbox_unix_lock (mailbox_t mbox, int flag)
{
#ifdef HAVE_MAILOCK_H
#else
(void)mbox; (void)flag;
#endif
if (mbox && mbox->locker != NULL)
{
locker_t locker = mbox->locker;
locker_lock (locker, flag);
}
return 0;
}
static int
mailbox_unix_unlock (mailbox_t mbox)
{
#ifdef HAVE_MAILOCK_H
#else
(void)mbox;
#endif
if (mbox && mbox->locker != NULL)
{
locker_t locker = mbox->locker;
locker_unlock (locker);
}
return 0;
}
/* miscellany */
static int
mailbox_unix_size (mailbox_t mbox, off_t *size)
mailbox_unix_ilock (mailbox_t mbox, int flag)
{
mailbox_unix_data_t mud = (mailbox_unix_data_t) mbox->data;
struct stat st;
int fd;
if (mud == NULL || mud->file == NULL)
{
/* maybe was not open yet ?? */
return EIO;
}
fd = fileno (mud->file);
if (fstat (fd, &st) != 0)
{
/* oops !! */
/* errno set by fstat () */
return EIO;
}
*size = st.st_size;
#ifdef HAVE_PTHREAD_H
mailbox_unix_data_t mud;
(void)flag; /* we should use rwlocks for more concurency */
if (mbox == NULL ||
(mud = (mailbox_unix_data_t)mbox->data) == NULL)
return EINVAL;
return pthread_mutex_lock (&(mud->mutex));
#else
(void)mbox; (void)flag;
return 0;
#endif
}
static int
mailbox_unix_get_size (mailbox_t mbox, size_t msgno, size_t *h, size_t *b)
mailbox_unix_iunlock (mailbox_t mbox)
{
mailbox_unix_data_t mud = (mailbox_unix_data_t) mbox->data;
mailbox_unix_msg_t mum;
if (mailbox_unix_is_valid (mbox, msgno))
{
#ifdef HAVE_PTHREAD_H
mailbox_unix_data_t mud;
if (mbox == NULL ||
(mud = (mailbox_unix_data_t)mbox->data) == NULL)
return EINVAL;
}
mum = &(mud->messages[msgno]);
if (h)
*h = mum->header - mum->body;
if (b)
*b = mum->body - mum->header;
return pthread_mutex_unlock (&(mud->mutex));
#else
(void)mbox;
return 0;
#endif
}
......