diff options
author | Jeff Bailey <jbailey@gnu.org> | 1999-09-11 22:58:21 +0000 |
---|---|---|
committer | Jeff Bailey <jbailey@gnu.org> | 1999-09-11 22:58:21 +0000 |
commit | 759a29ba3bff2db376a068f90f7e9ede5896a249 (patch) | |
tree | f8978993f6bad674bf0d042302010506022a2b53 /libmailbox | |
parent | aaa222bbc4368755bc3e88fee1cf006613f7afe9 (diff) | |
download | mailutils-759a29ba3bff2db376a068f90f7e9ede5896a249.tar.gz mailutils-759a29ba3bff2db376a068f90f7e9ede5896a249.tar.bz2 |
Diffstat (limited to 'libmailbox')
-rw-r--r-- | libmailbox/Makefile.am | 13 | ||||
-rw-r--r-- | libmailbox/mailbox.c | 99 | ||||
-rw-r--r-- | libmailbox/mailbox.h | 47 | ||||
-rw-r--r-- | libmailbox/unixmbox.c | 268 | ||||
-rw-r--r-- | libmailbox/unixmbox.h | 56 |
5 files changed, 483 insertions, 0 deletions
diff --git a/libmailbox/Makefile.am b/libmailbox/Makefile.am new file mode 100644 index 000000000..1ad179b39 --- /dev/null +++ b/libmailbox/Makefile.am @@ -0,0 +1,13 @@ +# Use automake to process this file -*-Makefile-*- + +if INSTALL_MAILBOX +include_HEADERS = mailbox.h +lib_LTLIBRARIES = libmailbox.la +else +noinst_HEADERS = mailbox.h +noinst_LTLIBRARIES = libmailbox.la +endif + +libmailbox_la_SOURCES = mailbox.c unixmbox.c unixmbox.h +libmailbox_la_LDFLAGS = -version-info 0:0:0 + diff --git a/libmailbox/mailbox.c b/libmailbox/mailbox.c new file mode 100644 index 000000000..51d894ee9 --- /dev/null +++ b/libmailbox/mailbox.c @@ -0,0 +1,99 @@ +/* copyright and license info go here */ + +#include "mailbox.h" +#include "unixmbox.h" + +#ifdef _HAVE_ERRNO_H +#include <errno.h> +#endif + +int _mbox_dummy1 (mailbox * mbox); +int _mbox_dummy2 (mailbox * mbox, int num); +int _mbox_dummy3 (mailbox * mbox, char *c); +char *_mbox_dummy4 (mailbox * mbox, int num); + +mailbox * +mbox_open (char *name) +{ + mailbox *mbox = malloc (sizeof (mailbox)); + if (mbox == NULL) + { + errno = ENOMEM; + return NULL; + } + + /* Set up with default data and dummy functions */ + mbox->name = strdup (name); + if (mbox->name == NULL) + { + errno = ENOMEM; + free (mbox); + return NULL; + } + mbox->messages = 0; + mbox->num_deleted = 0; + mbox->sizes = NULL; + mbox->_data = NULL; + mbox->_close = _mbox_dummy1; + mbox->_delete = _mbox_dummy2; + mbox->_undelete = _mbox_dummy2; + mbox->_expunge = _mbox_dummy1; + mbox->_add_message = _mbox_dummy3; + mbox->_is_deleted = _mbox_dummy2; + mbox->_get_body = _mbox_dummy4; + mbox->_get_header = _mbox_dummy4; + + if (unixmbox_open (mbox) == 0) + return mbox; + else + { + /* + * Check errno to find out why it failed, if it's simply not a + * unix mbox format message, then try other mailbox types, + * otherwise, leave errno set and return NULL + */ + } + + /* for example... + if (maildir_open (mbox, name) == 1) + return mbox; + else if (errno != 0) + return NULL; + else + errno = 0; + */ + + errno = ENOSYS; + return NULL; +} + +/* + * Bogus functions for unimplemented functions that return int + */ +int +_mbox_dummy1 (mailbox * mbox) +{ + errno = ENOSYS; + return -1; +} + +int +_mbox_dummy2 (mailbox * mbox, int num) +{ + return _mbox_dummy1 (mbox); +} +int +_mbox_dummy3 (mailbox * mbox, char *c) +{ + return _mbox_dummy1 (mbox); +} + +/* + * Bogus function for unimplemented functions that return char * + */ +char * +_mbox_dummy4 (mailbox * mbox, int num) +{ + errno = ENOSYS; + return NULL; +} diff --git a/libmailbox/mailbox.h b/libmailbox/mailbox.h new file mode 100644 index 000000000..05b7e32ea --- /dev/null +++ b/libmailbox/mailbox.h @@ -0,0 +1,47 @@ +/* copyright and license info go here */ + +#ifndef _MAILBOX_H +#define _MAILBOX_H 1 + +#ifndef __P +#if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus) +#define __P(args) args +#else +#define __P(args) () +#endif +#endif /*!__P */ + +/* These need to be documented */ +#define mbox_close(m) m->_close(m) +#define mbox_delete(m,n) m->_delete(m,n) +#define mbox_undelete(m,n) m->_undelete(m,n) +#define mbox_expunge(m) m->_expunge(m) +#define mbox_is_deleted(m,n) m->_is_deleted(m,n) +#define mbox_add_message(m,s) m->_add_message(m,s) +#define mbox_get_body(m,n) m->_get_body(m,n) +#define mbox_get_header(m,n) m->_get_header(m,n) + +typedef struct _mailbox + { + /* Data */ + char *name; + int messages; + int num_deleted; + int *sizes; + void *_data; + + /* Functions */ + int (*_close) __P ((struct _mailbox *)); + int (*_delete) __P ((struct _mailbox *, int)); + int (*_undelete) __P ((struct _mailbox *, int)); + int (*_expunge) __P ((struct _mailbox *)); + int (*_add_message) __P ((struct _mailbox *, char *)); + int (*_is_deleted) __P ((struct _mailbox *, int)); + char *(*_get_body) __P ((struct _mailbox *, int)); + char *(*_get_header) __P ((struct _mailbox *, int)); + } +mailbox; + +mailbox *mbox_open __P ((char *name)); + +#endif diff --git a/libmailbox/unixmbox.c b/libmailbox/unixmbox.c new file mode 100644 index 000000000..0e5e855d4 --- /dev/null +++ b/libmailbox/unixmbox.c @@ -0,0 +1,268 @@ +/* copyright and license info go here */ + +#include "unixmbox.h" + +/* + * Opens and locks a mailbox + */ +int +unixmbox_open (mailbox * mbox) +{ + char buf[80]; + unsigned int max_count = 10; + int mess = 0; + unixmbox_data *data = malloc (sizeof (unixmbox_data)); + + if (data == NULL) + { + errno = ENOMEM; + free (data); + return -1; + } + + mbox->_data = data; + data->file = fopen (mbox->name, "r+"); + /* FIXME: do a good, NFS safe, file lock here, with error handling */ + if (data->file == NULL) + { + /* errno is set by fopen() */ + free (data); + return -1; + } + + data->messages = malloc (sizeof (unixmbox_message) * max_count); + mbox->sizes = malloc (sizeof (int) * max_count); + if (data->messages == NULL || mbox->sizes == NULL) + { + unixmbox_close (mbox); + errno = ENOMEM; + return -1; + } + + while (fgets (buf, 80, data->file)) + { + if (!strncmp (buf, "From ", 5)) + { + /* Beginning of a header */ + while (strchr (buf, '\n') == NULL) + fgets (buf, 80, data->file); + + mbox->messages++; + + if (mbox->messages > max_count) + { + max_count = mbox->messages * 2; + data->messages = realloc (data->messages, + max_count * sizeof (unixmbox_message)); + mbox->sizes = realloc (mbox->sizes, max_count * sizeof (int)); + if (data->messages == NULL || mbox->sizes == NULL) + { + unixmbox_close (mbox); + errno = ENOMEM; + return -1; + } + } + + fgetpos (data->file, &(data->messages[mbox->messages - 1].header)); + mbox->sizes[mbox->messages - 1] = 0; + data->messages[mbox->messages - 1].deleted = 0; + mess = 0; + } + else if (((!strncmp (buf, "\r\n", 2) || strlen (buf) <= 1)) && mess == 0) + { + /* Beginning of a body */ + fgetpos (data->file, &(data->messages[mbox->messages - 1].body)); + mbox->sizes[mbox->messages - 1] += strlen (buf) + 1; + mess = 1; + } + else + { + mbox->sizes[mbox->messages - 1] += strlen (buf) + 1; + fgetpos (data->file, &(data->messages[mbox->messages - 1].end)); + } + } + + mbox->_close = unixmbox_close; + mbox->_delete = unixmbox_delete; + mbox->_undelete = unixmbox_undelete; + mbox->_expunge = unixmbox_expunge; + mbox->_add_message = unixmbox_add_message; + mbox->_is_deleted = unixmbox_is_deleted; + mbox->_get_body = unixmbox_get_body; + mbox->_get_header = unixmbox_get_header; + + return 0; +} + +/* + * Closes and unlocks a mailbox, does not expunge + */ +int +unixmbox_close (mailbox * mbox) +{ + unixmbox_data *data = mbox->_data; + /* FIXME: good file unlocking, to go along with the locking above */ + fclose (data->file); + free (data->messages); + free (mbox->sizes); + free (data); + free (mbox); + return 0; +} + +/* + * Marks a message for deletion + */ +int +unixmbox_delete (mailbox * mbox, int num) +{ + unixmbox_data *data = mbox->_data; + if (num > mbox->messages || mbox_is_deleted (mbox, num)) + { + errno = ERANGE; + return -1; + } + else + { + data->messages[num].deleted = 1; + mbox->num_deleted++; + } + return 0; +} + +/* + * Unmark a message for deletion + */ +int +unixmbox_undelete (mailbox * mbox, int num) +{ + unixmbox_data *data = mbox->_data; + if (num > mbox->messages || !mbox_is_deleted (mbox, num)) + { + errno = ERANGE; + return -1; + } + else + { + data->messages[num].deleted = 0; + mbox->num_deleted--; + } + return 0; +} + +/* + * Updates a mailbox to remove message marked for deletion + * FIXME: BROKEN! DOES NOT WORK! BLOWS UP REAL GOOD! + */ +int +unixmbox_expunge (mailbox * mbox) +{ + unixmbox_data *data = mbox->_data; + int i = 0, size = 0; + char *buf; + fpos_t lastpos; + + data->file = freopen (mbox->name, "r+", data->file); + if (data->file == NULL) + { + /* error handling */ + } + fgetpos (data->file, &lastpos); + + for (i = 0; i < mbox->messages; i++) + { + if (data->messages[i].deleted == 0) + { + fgetpos (data->file, &lastpos); + fsetpos (data->file, &(data->messages[i].header)); + read (fileno (data->file), buf, + data->messages[i + 1].header - data->messages[i].header); + fprintf (data->file, "%s", buf); + size += strlen (buf); + free (buf); + } + } + ftruncate (fileno (data->file), size); + return 0; +} + +/* + * Determines whether or a not a message is marked for deletion + */ +int +unixmbox_is_deleted (mailbox * mbox, int num) +{ + unixmbox_data *data = mbox->_data; + return (data->messages[num].deleted == 1); +} + +/* + * Adds a message to the mailbox + */ +int +unixmbox_add_message (mailbox * mbox, char *message) +{ + /* + * FIXME: please write me + * move to end of file and write text, don't forget to update + * mbox->messages and mbox->_data->messages + */ + errno = ENOSYS; + return -1; +} + +/* + * Returns a message body + */ +char * +unixmbox_get_body (mailbox * mbox, int num) +{ + unixmbox_data *data = mbox->_data; + int size = data->messages[num].end - data->messages[num].body; + char *buf = malloc ((1 + size) * sizeof (char)); + if (buf == NULL) + { + errno = ENOMEM; + free (buf); + return NULL; + } + else if (num > mbox->messages || num < 0) + { + errno = ERANGE; + free (buf); + return NULL; + } + + memset (buf, 0, size + 1); + fsetpos (data->file, &(data->messages[num].body)); + fread (buf, size, sizeof (char), data->file); + return buf; +} + +/* + * Returns just the header of a message + */ +char * +unixmbox_get_header (mailbox * mbox, int num) +{ + unixmbox_data *data = mbox->_data; + int size = (data->messages[num].body - 1) - data->messages[num].header ; + char *buf = malloc ((1 + size) * sizeof (char)); + if (buf == NULL) + { + errno = ENOMEM; + free (buf); + return NULL; + } + else if (num > mbox->messages || num < 0) + { + errno = ERANGE; + free (buf); + return NULL; + } + + memset (buf, 0, size + 1); + fsetpos (data->file, &(data->messages[num].header)); + fread (buf, size, sizeof (char), data->file); + return buf; +} diff --git a/libmailbox/unixmbox.h b/libmailbox/unixmbox.h new file mode 100644 index 000000000..65d0784b1 --- /dev/null +++ b/libmailbox/unixmbox.h @@ -0,0 +1,56 @@ +/* copyright and license info go here */ + +#ifndef _UNIXMBOX_H +#define _UNIXMBOX_H 1 +#include <mailbox.h> +#include "config.h" + +#ifdef HAVE_STDIO_H +#include <stdio.h> +#endif + +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif + +#ifdef HAVE_STRING_H +#include <string.h> +#elif HAVE_STRINGS_H +#include <strings.h> +#endif + +typedef struct _unixmbox_message + { + off_t header; + off_t body; + off_t end; + short deleted; + } +unixmbox_message; + +typedef struct _unixmbox_data + { + unixmbox_message *messages; + FILE *file; + } +unixmbox_data; + +int unixmbox_open (mailbox *mbox); +int unixmbox_close (mailbox *mbox); +int unixmbox_delete (mailbox *mbox, int num); +int unixmbox_undelete (mailbox *mbox, int num); +int unixmbox_expunge (mailbox *mbox); +int unixmbox_is_deleted (mailbox *mbox, int num); +int unixmbox_add_message (mailbox *mbox, char *message); +char *unixmbox_get_body (mailbox *mbox, int num); +char *unixmbox_get_header (mailbox *mbox, int num); + +#endif |