Commit acae1d25 acae1d257c398950d72b5ad692f489538f1c7fea by Jeff Bailey

Initial revision

0 parents
Jakob Kaivo <jkaivo@ndn.net>
1999-09-11 Jeff Bailey <jbailey@cr499794-a.crdva1.bc.wave.home.com>
* libmailbox/unixmbox.h: Do not prefix config.h defines with _
1999-09-10 Jeff Bailey <jbailey@cr499794-a.crdva1.bc.wave.home.com>
* */*: Accomidate directory rearrange
AUTOMAKE_OPTIONS = gnu 1.4
SUBDIRS = libmailbox mail
File mode changed
File mode changed
dnl Process this file with autoconf to procude a configure script. -*-m4-*-
AC_INIT(libmailbox/mailbox.c)
AM_INIT_AUTOMAKE(libmailbox, 0.0.19990909)
AM_CONFIG_HEADER(config.h)
AM_MAINTAINER_MODE
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_LIBTOOL
AC_ARG_ENABLE(-mailbox-install,
[ --enable-mailbox-install install libmailbox])
AM_CONDITIONAL(INSTALL_MAILBOX, test x"${enable_mailbox_install-no}" != xno)
AC_HEADER_STDC
AC_CHECK_HEADERS(malloc.h stdlib.h stdio.h errno.h unistd.h)
AC_CHECK_HEADERS(string.h strings.h, break)
AC_OUTPUT(Makefile libmailbox/Makefile mail/Makefile)
# 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
/* 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;
}
/* 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
/* 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;
}
/* 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
CPPFLAGS = -I$(top_srcdir)/libmailbox
bin_PROGRAMS = mail
mail_LDADD = ../libmailbox/libmailbox.la
/* copyright and license info go here */
#include <mailbox.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
#ifndef _PATH_MAILDIR
#define _PATH_MAILDIR "/var/spool/mail"
#endif
int
main (int argc, char **argv)
{
char *foo, bar[80];
int i = 0;
char c = 0;
char *mboxname;
mailbox *mbox;
if (argc != 1)
{
fprintf (stderr, "Usage: %s\n", argv[0]);
return 1;
}
mboxname = getenv ("MAIL");
if (mboxname == NULL)
{
foo = getenv ("LOGNAME");
mboxname = malloc ((strlen(foo) + strlen(_PATH_MAILDIR) + 2) * sizeof(char));
strcpy (mboxname, _PATH_MAILDIR "/");
strcat (mboxname, foo);
free (foo);
}
mbox = mbox_open (mboxname);
printf ("Number of messages: %d\n", mbox->messages);
while (1)
{
printf ("& ");
fflush (stdout);
fgets (bar, 80, stdin);
c = bar[0];
if (c == 'd' || c == 'D' || c == 'b' || c == 'B' || c == 'h' ||
c == 'H' || c == 'r' || c == 'R')
{
printf ("# ");
fgets (bar, 80, stdin);
}
switch (c)
{
case 'q':
case 'Q':
mbox_close (mbox);
return 0;
break;
case 'r':
case 'R':
foo = mbox_get_header (mbox, atoi (bar) - 1);
printf ("%s\n", foo);
free (foo);
foo = mbox_get_body (mbox, atoi (bar) - 1);
printf ("%s", foo);
free (foo);
break;
case 'h':
case 'H':
foo = mbox_get_header (mbox, atoi (bar) - 1);
printf ("%s", foo);
free (foo);
break;
case 'b':
case 'B':
foo = mbox_get_body (mbox, atoi (bar) - 1);
printf ("%s", foo);
free (foo);
break;
case 'd':
case 'D':
mbox_delete (mbox, atoi (bar) - 1);
break;
case 'x':
case 'X':
mbox_expunge (mbox);
break;
default:
break;
}
}
}