Commit 94eda4fb 94eda4fb6f6ae904fe56f37203a10bf8cb583ee6 by Alain Magloire

pop: Check for Berkeley DB in configure and define HAVE_DB_H and WITH_BDB2

pop: RETR and TOP if buffer is not a full line i.e terminated by a '\n' realloc
the buffer and try again.
pop: STAT remove excess comment.
pop: user use the /dev/null scheme if mailbox does not exist.
mailbox: buglet if the mailbox format we were reading less then expected.
1 parent 5bc4fc41
/* GNU mailutils - a suite of utilities for electronic mail
Copyright (C) 1999, 2000 Free Software Foundation, Inc.
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -18,10 +18,14 @@
/* Define if using libpam */
#undef USE_LIBPAM
/* Define if have snprintf() */
#undef HAVE_SNPRINTF
/* Define if enable Posix Thread */
#undef WITH_PTHREAD
/* Define if using Berkeley DB2 */
#undef WITH_BDB2
/* Define if using libreadline */
#undef WITH_READLINE
......
......@@ -11,7 +11,7 @@ AM_PROG_LIBTOOL
dnl Check for arguments
AC_ARG_ENABLE(pam,
[ --disable-pam disable pam],
[ --disable-pam disable pam],
[case "${enableval}" in
yes) testpam=yes ;;
no) testpam=no ;;
......@@ -19,7 +19,7 @@ AC_ARG_ENABLE(pam,
esac],[testpam=yes])
AC_ARG_ENABLE(pthread,
[ --disable-pthread disable pthread],
[ --disable-pthread disable pthread],
[case "${enableval}" in
yes) usepthread=yes ;;
no) usepthread=no ;;
......@@ -27,13 +27,21 @@ AC_ARG_ENABLE(pthread,
esac],[usepthread=yes])
AC_ARG_WITH(readline,
[ --without-readline do not use readline],
[ --without-readline do not use readline],
[case "${withval}" in
yes) usereadline=yes ;;
no) usereadline=no ;;
*) AC_MSG_ERROR(bad value ${withval} for --without-readline) ;;
esac],[usereadline=yes])
AC_ARG_WITH(db2,
[ --with-db2 use Berkeley DB],
[case "${withval}" in
yes) usedb2=yes ;;
no) usedb2=no ;;
*) AC_MSG_ERROR(bad value ${withval} for --with-db) ;;
esac],[usedb2=no])
dnl Check for headers
AC_HEADER_STDC
AC_HEADER_DIRENT
......@@ -58,7 +66,7 @@ AC_FUNC_ALLOCA
# Not use.
#AC_FUNC_MEMCMP
AC_FUNC_MMAP
# Provide the GNU one for loosing platforms
# FIXME: Provide the GNU one for loosing platforms
AC_FUNC_FNMATCH
AC_REPLACE_FUNCS(snprintf strtok_r)
AC_CHECK_FUNCS(mkstemp)
......@@ -85,9 +93,9 @@ AC_SUBST(AUTHLIBS)
dnl Check threading support
if test x"$usepthread" = x"yes"; then
AC_CHECK_HEADERS(pthread.h)
AC_SEARCH_LIBS(pthread_cancel, pthread, AC_DEFINE(WITH_PTHREAD))
AC_CHECK_FUNCS(pthread_rwlock_init)
AC_SEARCH_LIBS(pthread_cancel, pthread,
[AC_CHECK_FUNCS(pthread_rwlock_init)
AC_CHECK_HEADERS(pthread.h, AC_DEFINE(WITH_PTHREAD))])
fi
dnl Do we need extra libs for networking?
......@@ -97,12 +105,18 @@ AC_CHECK_FUNC(gethostbyname, [true],
AC_CHECK_FUNC(socket, [true],
AC_CHECK_LIB(socket, socket, LIBS="-lsocket $LIBS"))
dnl Check for readline
dnl Check for GNU Readline
if test x"$usereadline" = x"yes"; then
AC_CHECK_LIB(readline, readline,
AC_CHECK_HEADERS(readline/readline.h, AC_DEFINE(WITH_READLINE)))
fi
dnl Check for Berkeley DB
if test x"${usedb2}" = x"yes"; then
AC_CHECK_LIB(db, db_open, [AC_CHECK_HEADERS(db.h, AC_DEFINE(WITH_BDB2))
LIBS="$LIBS -ldb"])
fi
dnl Output Makefiles
AC_OUTPUT(Makefile mailutils.spec include/Makefile include/mailutils/Makefile
m4/Makefile doc/Makefile lib/Makefile mailbox/Makefile imap4d/Makefile
......
......@@ -201,13 +201,12 @@ usage (const char *argv)
exit (0);
}
/* This a close of the elm program call "frm". It is a good example on
/* This is a clone of the elm program call "frm". It is a good example on
how to use the observable(callback) of libmailutils. "frm" has to
be very interactive so it is not possible to call mailbox_messages_count()
be very interactive, it is not possible to call mailbox_messages_count()
and wait for the scanning to finish before displaying. As soon as the scan
find a new message we want to know about it, this is done by registering
an observable type MU_MAILBOX_NEW_MSG. The rest is simple displaying
formating code. */
an observable type MU_MAILBOX_MSG_ADD. The rest is formating code. */
int
main(int argc, char **argv)
......
......@@ -102,7 +102,7 @@ _mapfile_readline (stream_t stream, char *optr, size_t osize,
nl = memchr (mfs->ptr + offset, '\n', mfs->size - offset);
n = nl - (mfs->ptr + offset) + 1;
n = (n) > osize ? osize : n;
n = (n > osize) ? osize : n;
memcpy (optr, mfs->ptr + offset, n);
if (nbytes)
*nbytes = n;
......
/* GNU mailutils - a suite of utilities for electronic mail
Copyright (C) 1999, 2000 Free Software Foundation, Inc.
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Library General Public License as published by
......@@ -68,7 +68,13 @@ _mailbox_file_init (mailbox_t mbox)
{
status = _mailbox_mbox_init (mbox);
}
else if (S_ISREG (st.st_mode))
else if (S_ISDIR (st.st_mode))
{
/* Is that true ? Are all directories Maildir ?? */
/* NOT SUPPORTED: status = _mailbox_maildir_init (mbox);*/
status = ENOSYS;
}
else
{
/*
FIXME: We should do an open() and try
......@@ -76,12 +82,6 @@ _mailbox_file_init (mailbox_t mbox)
maybe MMDF. For now assume Unix MBox */
status = _mailbox_mbox_init (mbox);
}
/* Is that true ? Are all directories Maildir ?? */
else if (S_ISDIR (st.st_mode))
{
/*status = _mailbox_maildir_init (mbox);*/
status = EINVAL;
}
free (path);
return status;
......
......@@ -270,15 +270,29 @@ mbox_open (mailbox_t mailbox, int flags)
/* We do not try to mmap for CREAT or APPEND, it is not supported. */
status = (flags & MU_STREAM_CREAT)
|| (mailbox->flags & MU_STREAM_APPEND);
/* Try to mmap() the file first. */
if (status == 0)
status = mapfile_stream_create (&(mailbox->stream));
{
status = mapfile_stream_create (&(mailbox->stream));
if (status == 0)
{
status = stream_open (mailbox->stream, mud->name, 0,
mailbox->flags);
if (status != 0)
stream_destroy (&mailbox->stream, NULL);
}
}
/* Fall back to normal file if mmap() failed. */
if (status != 0)
{
status = file_stream_create (&(mailbox->stream));
if (status != 0)
return status;
status = stream_open (mailbox->stream, mud->name, 0, mailbox->flags);
}
status = stream_open (mailbox->stream, mud->name, 0, mailbox->flags);
/* All failed, bail out. */
if (status != 0)
return status;
}
......@@ -845,14 +859,26 @@ mbox_body_readstream (stream_t is, char *buffer, size_t buflen,
off_t ln = mum->body_end - (mum->body + off);
if (ln > 0)
{
nread = ((size_t)ln < buflen) ? ln : buflen;
/* Position the file pointer and the buffer. */
if (isreadline)
status = stream_readline (mum->stream, buffer, nread,
mum->body + off, &nread);
{
status = stream_readline (mum->stream, buffer, buflen,
mum->body + off, &nread);
/* This mean we went pass the message boundary, thechnically it
should not be sine we are reading by line, but just in case
truncate the string. */
if (nread > (size_t)ln)
{
buffer[ln] = '\0';
nread = ln;
}
}
else
status = stream_read (mum->stream, buffer, nread,
mum->body + off, &nread);
{
nread = ((size_t)ln < buflen) ? ln : buflen;
status = stream_read (mum->stream, buffer, nread,
mum->body + off, &nread);
}
}
}
monitor_unlock (mum->mud->mailbox->monitor);
......
......@@ -18,14 +18,14 @@
#include "pop3d.h"
/* Check if a username exists in APOP password file
returns pinter to password if found, otherwise NULL */
returns pointer to password if found, otherwise NULL */
char *
pop3_apopuser (const char *user)
{
char *password;
char buf[POP_MAXCMDLEN];
struct stat st;
#ifdef BDB2
#ifdef WITH_BDB2
int errno;
DB *dbp;
DBT key, data;
......@@ -43,7 +43,7 @@ pop3_apopuser (const char *user)
return NULL;
}
#ifdef BDB2
#ifdef WITH_BDB2
errno = db_open (APOP_PASSFILE ".db", DB_HASH, DB_RDONLY, 0600, NULL,
NULL, &dbp);
if (errno != 0)
......@@ -76,7 +76,7 @@ pop3_apopuser (const char *user)
sprintf (password, "%.*s", (int) data.size, (char *) data.data);
dbp->close (dbp, 0);
return password;
#else /* !BDBD2 */
#else /* !WITH_BDBD2 */
apop_file = fopen (APOP_PASSFILE ".passwd", "r");
if (apop_file == NULL)
{
......@@ -118,7 +118,7 @@ pop3_apopuser (const char *user)
}
return password;
#endif /* BDB2 */
#endif /* WITH_BDB2 */
}
int
......@@ -130,6 +130,7 @@ pop3_apop (const char *arg)
struct md5_ctx md5context;
unsigned char md5digest[16];
int i;
int status;
if (state != AUTHORIZATION)
return ERR_WRONG_STATE;
......@@ -194,11 +195,26 @@ pop3_apop (const char *arg)
state = AUTHORIZATION;
return ERR_UNKNOWN;
}
else if (mailbox_open (mbox, MU_STREAM_RDWR) != 0)
else if ((status = mailbox_open (mbox, MU_STREAM_RDWR)) != 0)
{
free (username);
state = AUTHORIZATION;
return ERR_MBOX_LOCK;
mailbox_destroy (&mbox);
/* For non existent mailbox, we fake. */
if (status == ENOENT)
{
if (mailbox_create (&mbox, "/dev/null") != 0
|| mailbox_open (mbox, MU_STREAM_READ) != 0)
{
free (username);
state = AUTHORIZATION;
return ERR_UNKNOWN;
}
}
else
{
free (username);
state = AUTHORIZATION;
return ERR_MBOX_LOCK;
}
}
state = TRANSACTION;
......
......@@ -101,8 +101,8 @@
#include <mailutils/registrar.h>
/* For Berkley DB2 APOP password file */
#ifdef BDB2
#include <db2/db.h>
#ifdef HAVE_DB_H
#include <db.h>
#endif
/* The path to the mail spool files */
......
......@@ -23,7 +23,8 @@ int
pop3_retr (const char *arg)
{
size_t mesgno, n;
char buf[BUFFERSIZE];
char *buf;
size_t buflen = BUFFERSIZE;
message_t msg;
attribute_t attr;
stream_t stream;
......@@ -46,13 +47,26 @@ pop3_retr (const char *arg)
message_get_stream (msg, &stream);
fprintf (ofile, "+OK\r\n");
off = n = 0;
while (stream_readline (stream, buf, sizeof (buf) - 1, off, &n) == 0
buf = malloc (buflen * sizeof (*buf));
if (buf == NULL)
pop3_abquit (ERR_NO_MEM);
while (stream_readline (stream, buf, buflen - 1, off, &n) == 0
&& n > 0)
{
/* Nuke the trainline newline. */
if (buf[n - 1] == '\n')
buf[n - 1] = '\0';
else /* Make room for the line. */
{
buflen *= 2;
buf = realloc (buf, buflen * sizeof (*buf));
if (buf == NULL)
pop3_abquit (ERR_NO_MEM);
continue;
}
if (buf[0] == '.')
fprintf (ofile, ".%s\r\n", buf);
else
......@@ -60,6 +74,7 @@ pop3_retr (const char *arg)
off += n;
}
free (buf);
fprintf (ofile, ".\r\n");
return OK;
......
......@@ -30,13 +30,16 @@ pop3_stat (const char *arg)
size_t tsize = 0;
message_t msg;
attribute_t attr;
if (strlen (arg) != 0)
return ERR_BAD_ARGS;
if (state != TRANSACTION)
return ERR_WRONG_STATE;
/* rfc1939: if the POP3 server host internally represents end-of-line as a
single character, then the POP3 server simply counts each occurrence of
this character in a message as two octets. */
mailbox_messages_count (mbox, &total);
for (mesgno = 1; mesgno <= total; mesgno++)
{
......@@ -50,25 +53,9 @@ pop3_stat (const char *arg)
num++;
}
}
/* rfc1939: Note that messages marked as deleted are not counted in either
total. */
fprintf (ofile, "+OK %d %d\r\n", num, tsize);
return OK;
}
#if 0
int
pop3_stat (const char *arg)
{
unsigned int count = 0;
off_t size = 0;
mailbox_size (mbox, &size);
mailbox_messages_count (mbox, &count);
fprintf (ofile, "+OK %d %d\r\n", count, (int)size);
return OK;
}
#endif
......
......@@ -30,7 +30,8 @@ pop3_top (const char *arg)
body_t body;
stream_t stream;
char *mesgc, *linesc;
char buf[BUFFERSIZE];
char *buf;
size_t buflen = BUFFERSIZE;
size_t n;
off_t off;
......@@ -43,7 +44,7 @@ pop3_top (const char *arg)
mesgc = pop3_cmd (arg);
linesc = pop3_args (arg);
mesgno = strtoul (mesgc, NULL, 10);
lines = strlen (linesc) > 0 ? strtoul (linesc, NULL, 10) : -1;
lines = strlen (linesc) > 0 ? strtol (linesc, NULL, 10) : -1;
free (mesgc);
free (linesc);
......@@ -62,14 +63,25 @@ pop3_top (const char *arg)
/* Header. */
message_get_header (msg, &hdr);
header_get_stream (hdr, &stream);
buf = malloc (buflen * sizeof (*buf));
if (buf == NULL)
pop3_abquit (ERR_NO_MEM);
off = n = 0;
while (stream_readline (stream, buf, sizeof (buf) - 1, off, &n) == 0)
while (stream_readline (stream, buf, buflen - 1, off, &n) == 0)
{
if (n == 0)
break;
/* Nuke the trainline newline. */
if (buf[n - 1] == '\n')
buf [n - 1] = '\0';
else /* Make room for the line. */
{
buflen *= 2;
buf = realloc (buf, buflen * sizeof (*buf));
if (buf == NULL)
pop3_abquit (ERR_NO_MEM);
continue;
}
off += n;
fprintf (ofile, "%s\r\n", buf);
}
......@@ -79,20 +91,31 @@ pop3_top (const char *arg)
{
message_get_body (msg, &body);
body_get_stream (body, &stream);
for (n = off = 0; lines > 0; lines--, off += n)
n = off = 0;
while (stream_readline (stream, buf, buflen - 1, off, &n) == 0
&& n > 0 && lines > 0)
{
int status = stream_readline (stream, buf, sizeof (buf), off, &n);
if (status != 0 || n == 0)
break;
/* Nuke the trainline newline. */
if (buf[n - 1] == '\n')
buf[n - 1] = '\0';
else /* make room for the line. */
{
buflen *= 2;
buf = realloc (buf, buflen * sizeof (*buf));
if (buf == NULL)
pop3_abquit (ERR_NO_MEM);
continue;
}
if (buf[0] == '.')
fprintf (ofile, ".%s\r\n", buf);
else
fprintf (ofile, "%s\r\n", buf);
lines--;
off += n;
}
}
free (buf);
fprintf (ofile, ".\r\n");
return OK;
......
......@@ -80,6 +80,7 @@ pop3_user (const char *arg)
{
char *buf, pass[POP_MAXCMDLEN], *tmp, *cmd;
struct passwd *pw;
int status;
#ifdef USE_LIBPAM
pam_handle_t *pamh;
int pamerror;
......@@ -171,10 +172,24 @@ pop3_user (const char *arg)
state = AUTHORIZATION;
return ERR_UNKNOWN;
}
else if (mailbox_open (mbox, MU_STREAM_RDWR) != 0)
else if ((status = mailbox_open (mbox, MU_STREAM_RDWR)) != 0)
{
state = AUTHORIZATION;
return ERR_MBOX_LOCK;
mailbox_destroy (&mbox);
/* For non existent mailbox, we fake. */
if (status == ENOENT)
{
if (mailbox_create (&mbox, "/dev/null") != 0
|| mailbox_open (mbox, MU_STREAM_READ) != 0)
{
state = AUTHORIZATION;
return ERR_UNKNOWN;
}
}
else
{
state = AUTHORIZATION;
return ERR_MBOX_LOCK;
}
}
username = strdup (arg);
......