summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlain Magloire <alainm@gnu.org>2001-05-09 04:23:52 +0000
committerAlain Magloire <alainm@gnu.org>2001-05-09 04:23:52 +0000
commitb0f41a7171dc889b5cf45b6d0ce60c5df462663e (patch)
tree4f29e650f4ada69cdb5859ded611f1c25ef59e9c
parent5c2bb9274e7e5826e220c29e7b4f5a03269d2d27 (diff)
downloadmailutils-b0f41a7171dc889b5cf45b6d0ce60c5df462663e.tar.gz
mailutils-b0f41a7171dc889b5cf45b6d0ce60c5df462663e.tar.bz2
Finally!!!! I can use the GNU imap4d with Netscape .... It kinda work 8-)
sigh ... still more to do.
-rw-r--r--ChangeLog21
-rw-r--r--imap4d/Makefile.am8
-rw-r--r--imap4d/fetch.c132
-rw-r--r--imap4d/imap4d.c319
-rw-r--r--imap4d/imap4d.h59
-rw-r--r--imap4d/list.c15
-rw-r--r--imap4d/login.c18
-rw-r--r--imap4d/logout.c3
-rw-r--r--imap4d/lsub.c36
-rw-r--r--imap4d/select.c7
-rw-r--r--imap4d/store.c52
-rw-r--r--imap4d/subscribe.c25
-rw-r--r--imap4d/sync.c6
-rw-r--r--imap4d/unsubscribe.c63
-rw-r--r--imap4d/util.c35
-rw-r--r--mailbox/filter_rfc822.c19
-rw-r--r--mailbox/folder_imap.c1
-rw-r--r--mailbox/url_imap.c62
-rw-r--r--pop3d/extra.c40
-rw-r--r--pop3d/pop3d.c58
-rw-r--r--pop3d/pop3d.h28
-rw-r--r--pop3d/signal.c18
22 files changed, 761 insertions, 264 deletions
diff --git a/ChangeLog b/ChangeLog
index 4e6f69bc8..ea09fde17 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2001-05-09 Alain Magloire
+
+ Take the missing pieces from the pop3d and make the
+ imap4d a standalone daemon.
+
+ * imap4d/fetch.c: Remove fetch_body_peek().
+ and use fetch_body() instead.
+ (fetch_operation): Malloc the entire message... not good.
+ * imap4d/bye.c: New file.
+ * imap4d/imap4d.c: Put the networking code taken from
+ pop3d.c.
+ * imap4d/lsub.c: Implemented.
+ * imap4d/subscribe.c: Implemented.
+ * imap4d/unsubscribe.c: Implemented.
+
+ * pop3d/pop3d.c: pop3d_usage() move from extra.c
+ * pop3d/signal.c: pop3d_signal () move from extra.c
+
+ * mailbox/url_imap.c: It was not checking for the port number.
+ * mailbox/filter_rfc822.c: Check for the lines if available.
+
2001-05-07 Alain Magloire
Now we can have multiple access to the mailbox and the server
diff --git a/imap4d/Makefile.am b/imap4d/Makefile.am
index 169aee81a..9f279ea8d 100644
--- a/imap4d/Makefile.am
+++ b/imap4d/Makefile.am
@@ -4,7 +4,7 @@ INCLUDES = -I$(top_srcdir)/lib -I$(top_srcdir)/include
sbin_PROGRAMS = imap4d
imap4d_LDADD = ../mailbox/libmailbox.la ../lib/libmailutils.a @AUTHLIBS@
-imap4d_SOURCES = imap4d.c imap4d.h capability.c noop.c logout.c authenticate.c \
- login.c select.c examine.c create.c delete.c rename.c subscribe.c \
- unsubscribe.c list.c lsub.c status.c append.c check.c close.c \
- expunge.c search.c fetch.c store.c sync.c copy.c uid.c util.c commands.c
+imap4d_SOURCES = append.c authenticate.c bye.c capability.c check.c close.c \
+ commands.c copy.c create.c delete.c examine.c expunge.c fetch.c imap4d.c \
+ imap4d.h list.c logout.c login.c lsub.c noop.c rename.c search.c select.c \
+ signal.c status.c store.c subscribe.c sync.c uid.c unsubscribe.c util.c
diff --git a/imap4d/fetch.c b/imap4d/fetch.c
index c648369e0..4a13c5e73 100644
--- a/imap4d/fetch.c
+++ b/imap4d/fetch.c
@@ -48,7 +48,6 @@ static int fetch_rfc822 __P ((struct fetch_command *, char*));
static int fetch_bodystructure __P ((struct fetch_command *, char*));
static int fetch_bodystructure0 __P ((message_t, int));
static int bodystructure __P ((message_t, int));
-static int fetch_body_peek __P ((struct fetch_command *, char*));
static int fetch_body __P ((struct fetch_command *, char*));
static int fetch_uid __P ((struct fetch_command *, char*));
@@ -92,11 +91,9 @@ struct fetch_command
{"RFC822", fetch_rfc822, 0},
#define F_BODYSTRUCTURE 10
{"BODYSTRUCTURE", fetch_bodystructure, 0},
-#define F_BODY_PEEK 11
- {"BODY.PEEK", fetch_body_peek, 0},
-#define F_BODY 12
+#define F_BODY 11
{"BODY", fetch_body, 0},
-#define F_UID 13
+#define F_UID 12
{"UID", fetch_uid, 0},
{ NULL, 0, 0}
};
@@ -160,40 +157,51 @@ imap4d_fetch0 (char *arg, int isuid, char *resp, size_t resplen)
char item[32];
char *items = strdup (sp);
char *p = items;
+ size_t msgno;
+ int space = 0;
int uid_sent = !isuid; /* Pretend we sent the uid if via fetch. */
- util_send ("* %d FETCH (", set[i]);
- item[0] = '\0';
- /* Get the fetch command names. */
- while (*items && *items != ')')
+
+ msgno = (isuid) ? uid_to_msgno (set[i]) : set[i];
+ if (msgno)
{
- util_token (item, sizeof (item), &items);
- if (fcmd)
- util_send (" ");
- /* Search in the table. */
- fcmd = fetch_getcommand (item, fetch_command_table);
- if (fcmd)
+ fcmd = NULL;
+ util_send ("* %d FETCH (", msgno);
+ item[0] = '\0';
+ /* Server implementations MUST implicitly
+ include the UID message data item as part of any FETCH response
+ caused by a UID command, regardless of whether a UID was specified
+ as a message data item to the FETCH. */
+ if (!uid_sent)
+ {
+ fcmd = &fetch_command_table[F_UID];
+ fcmd->msgno = msgno;
+ rc = fetch_uid (fcmd, p);
+ uid_sent = 1;
+ }
+ /* Get the fetch command names. */
+ while (*items && *items != ')')
{
- fcmd->msgno = (isuid) ? uid_to_msgno (set[i]) : set[i];
- if (fcmd->msgno != 0)
+ util_token (item, sizeof (item), &items);
+ if (uid_sent && strcasecmp (item, "UID") == 0)
+ continue;
+ if (fcmd)
+ space = 1;
+ /* Search in the table. */
+ fcmd = fetch_getcommand (item, fetch_command_table);
+ if (fcmd)
{
+ if (space)
+ {
+ util_send (" ");
+ space = 0;
+ }
+ fcmd->msgno = msgno;
rc = fcmd->func (fcmd, items);
}
}
- if (!uid_sent)
- uid_sent = ((strstr (item, "UID") != NULL)
- || (strstr (item, "uid") != NULL));
- }
- /* Always send the UID when fetch was done via the uid command. */
- if (!uid_sent)
- {
- struct fetch_command c_uid = fetch_command_table[F_UID];
- c_uid.msgno = set[i];
- if (fcmd)
- util_send (" ");
- rc = fetch_uid (&c_uid, items);
+ util_send (")\r\n");
}
free (p);
- util_send (")\r\n");
}
free (set);
snprintf (resp, resplen, "Completed");
@@ -733,8 +741,6 @@ bodystructure (message_t msg, int extension)
static int
fetch_body (struct fetch_command *command, char *arg)
{
- struct fetch_command c_body_p = fetch_command_table[F_BODY_PEEK];
- c_body_p.msgno = command->msgno;
/* It's BODY set the message as seen */
if (*arg == '[')
{
@@ -766,15 +772,8 @@ fetch_body (struct fetch_command *command, char *arg)
util_send (")");
return RESP_OK;
}
- return fetch_body_peek (&c_body_p, arg);
-}
-
-static int
-fetch_body_peek (struct fetch_command *command, char *arg)
-{
- util_send ("%s ", command->name);
- fetch_operation (command->msgno, arg, 0);
- return RESP_OK;
+ util_send ("%s", command->name);
+ return fetch_operation (command->msgno, arg, 0);
}
static int
@@ -903,32 +902,37 @@ static int
fetch_io (stream_t stream, unsigned long start, unsigned long end)
{
stream_t rfc = NULL;
- char buffer[1024];
+ char *buffer, *p;
size_t n = 0;
size_t total = 0;
+ off_t offset;
+
+ offset = (start == ULONG_MAX) ? 0 : start;
filter_create (&rfc, stream, "rfc822", MU_FILTER_ENCODE, MU_STREAM_READ);
- if (start == ULONG_MAX)
+
+ p = buffer = calloc (end + 2, 1);
+ while (end > 0 && stream_read (rfc, buffer, end + 1, offset, &n) == 0 && n > 0)
{
- start = 0;
- util_send (" {%u}\r\n", end);
+ offset += n;
+ total += n;
+ end -= n;
+ buffer += n;
}
- else
- util_send ("<%lu> {%u}\r\n", start , end);
+ /* Make sure we null terminate. */
+ *buffer = '\0';
- while (start < end &&
- stream_read (rfc, buffer, sizeof (buffer), start, &n) == 0
- && n > 0)
+ if (start != ULONG_MAX)
+ util_send ("<%lu>", start);
+
+ if (total)
{
- start += n;
- total += n;
- if (total > end)
- {
- size_t diff = n - (total - end);
- buffer[diff] = '\0';
- }
- util_send ("%s", buffer);
+ util_send (" {%u}\r\n", total);
+ util_send ("%s", p);
}
+ else
+ util_send (" \"\"");
+ free (p);
return RESP_OK;
}
@@ -946,7 +950,7 @@ fetch_header_fields (message_t msg, char *arg, unsigned long start,
status = memory_stream_create (&stream);
if (status != 0)
- util_quit (ERR_NO_MEM);
+ imap4d_bye (ERR_NO_MEM);
/* Save the fields in an array. */
{
@@ -957,7 +961,7 @@ fetch_header_fields (message_t msg, char *arg, unsigned long start,
{
array = realloc (array, (array_len + 1) * sizeof (*array));
if (!array)
- util_quit (ERR_NO_MEM);
+ imap4d_bye (ERR_NO_MEM);
array[array_len] = field;
}
}
@@ -984,7 +988,7 @@ fetch_header_fields (message_t msg, char *arg, unsigned long start,
if (status != 0)
{
free (array);
- util_quit (ERR_NO_MEM);
+ imap4d_bye (ERR_NO_MEM);
}
}
}
@@ -1027,7 +1031,7 @@ fetch_header_fields_not (message_t msg, char *arg, unsigned long start,
status = memory_stream_create (&stream);
if (status)
- util_quit (ERR_NO_MEM);
+ imap4d_bye (ERR_NO_MEM);
/* Save the field we want to ignore. */
{
@@ -1038,7 +1042,7 @@ fetch_header_fields_not (message_t msg, char *arg, unsigned long start,
{
array = realloc (array, (array_len + 1) * sizeof (*array));
if (!array)
- util_quit (ERR_NO_MEM);
+ imap4d_bye (ERR_NO_MEM);
array[array_len] = field;
}
}
@@ -1093,7 +1097,7 @@ fetch_header_fields_not (message_t msg, char *arg, unsigned long start,
if (status != 0)
{
free (array);
- util_quit (ERR_NO_MEM);
+ imap4d_bye (ERR_NO_MEM);
}
}
}
diff --git a/imap4d/imap4d.c b/imap4d/imap4d.c
index 4f3da79a1..9e62b7847 100644
--- a/imap4d/imap4d.c
+++ b/imap4d/imap4d.c
@@ -23,37 +23,177 @@ mailbox_t mbox;
char *homedir;
int state = STATE_NONAUTH;
-static int imap4d_mainloop __P ((int, int));
+/* Number of child processes. */
+volatile size_t children;
+
+static struct option long_options[] =
+{
+ {"daemon", optional_argument, 0, 'd'},
+ {"help", no_argument, 0, 'h'},
+ {"inetd", no_argument, 0, 'i'},
+ {"port", required_argument, 0, 'p'},
+ {"timeout", required_argument, 0, 't'},
+ {"version", no_argument, 0, 'v'},
+ {0, 0, 0, 0}
+};
+
+const char *short_options ="d::hip:t:v";
+
+static int syslog_error_printer __P ((const char *fmt, va_list ap));
+static int imap4d_mainloop __P ((int, int));
+static void imap4d_daemon_init __P ((void));
+static void imap4d_daemon __P ((unsigned int, unsigned int));
+static int imap4d_mainloop __P ((int, int));
+static void imap4d_usage __P ((char *));
+
+#ifndef DEFMAXCHILDREN
+# define DEFMAXCHILDREN 20 /* Default maximum number of children */
+#endif
int
main (int argc, char **argv)
{
- chdir ("/");
- openlog ("imap4d", LOG_PID, LOG_MAIL);
+ struct group *gr;
+ static int mode = INTERACTIVE;
+ size_t maxchildren = DEFMAXCHILDREN;
+ int c = 0;
+ int status = EXIT_SUCCESS;
+ unsigned int port;
+
+ port = 143; /* Default IMAP4 port. */
+ timeout = 1800; /* RFC2060: 30 minutes, if enable. */
+ state = STATE_NONAUTH; /* Starting state in non-auth. */
+
+ while ((c = getopt_long (argc, argv, short_options, long_options, NULL))
+ != -1)
+ {
+ switch (c)
+ {
+ case 'd':
+ mode = DAEMON;
+ if (optarg)
+ maxchildren = strtoul (optarg, NULL, 10);
+ if (maxchildren == 0)
+ maxchildren = DEFMAXCHILDREN;
+ break;
+
+ case 'h':
+ imap4d_usage (argv[0]);
+ break;
+
+ case 'i':
+ mode = INTERACTIVE;
+ break;
+
+ case 'p':
+ mode = DAEMON;
+ port = strtoul (optarg, NULL, 10);
+ break;
+
+ case 't':
+ timeout = strtoul (optarg, NULL, 10);
+ break;
+
+ case 'v':
+ printf ("GNU imap4 daemon" "("PACKAGE " " VERSION ")\n");
+ exit (0);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* First we want our group to be mail so we can access the spool. */
+ gr = getgrnam ("mail");
+ if (gr == NULL)
+ {
+ perror ("Error getting mail group");
+ exit (1);
+ }
+
+ if (setgid (gr->gr_gid) == -1)
+ {
+ perror ("Error setting mail group");
+ exit (1);
+ }
/* Register the desire formats. We only need Mbox mail format. */
{
list_t bookie;
registrar_get_list (&bookie);
+ /* list_append (bookie, mbox_record); */
list_append (bookie, path_record);
}
- /* FIXME: Incomplete, make it work for standalone, see pop3d. */
- imap4d_mainloop (fileno (stdin), fileno (stdout));
- return 0;
+
+ /* Set the signal handlers. */
+ signal (SIGINT, imap4d_signal);
+ signal (SIGQUIT, imap4d_signal);
+ signal (SIGILL, imap4d_signal);
+ signal (SIGBUS, imap4d_signal);
+ signal (SIGFPE, imap4d_signal);
+ signal (SIGSEGV, imap4d_signal);
+ signal (SIGTERM, imap4d_signal);
+ signal (SIGSTOP, imap4d_signal);
+ signal (SIGPIPE, imap4d_signal);
+ /*signal (SIGPIPE, SIG_IGN); */
+ signal (SIGABRT, imap4d_signal);
+
+ if (mode == DAEMON)
+ imap4d_daemon_init ();
+
+ /* Make sure we are in the root. */
+ chdir ("/");
+
+ /* Set up for syslog. */
+ openlog ("gnu-imap4d", LOG_PID, LOG_FACILITY);
+
+ /* Redirect any stdout error from the library to syslog, they
+ should not go to the client. */
+ mu_error_set_print (syslog_error_printer);
+
+ umask (S_IROTH | S_IWOTH | S_IXOTH); /* 007 */
+
+ /* Actually run the daemon. */
+ if (mode == DAEMON)
+ imap4d_daemon (maxchildren, port);
+ /* exit (0) -- no way out of daemon except a signal. */
+ else
+ status = imap4d_mainloop (fileno (stdin), fileno (stdout));
+
+ /* Close the syslog connection and exit. */
+ closelog ();
+
+ return status;
}
static int
imap4d_mainloop (int infile, int outfile)
{
- const char *remote_host = "";
FILE *ifile;
+
+ /* Reset hup to exit. */
+ signal (SIGHUP, imap4d_signal);
+ /* Timeout alarm. */
+ signal (SIGALRM, imap4d_signal);
+
ifile = fdopen (infile, "r");
ofile = fdopen (outfile, "w");
if (!ofile || !ifile)
- util_quit (ERR_NO_OFILE);
+ imap4d_bye (ERR_NO_OFILE);
- /* FIXME: Retreive hostname with getpeername() and log. */
- syslog (LOG_INFO, "Incoming connection from %s", remote_host);
+ syslog (LOG_INFO, "Incoming connection opened");
+
+ /* log information on the connecting client */
+ {
+ struct sockaddr_in cs;
+ int len = sizeof cs;
+ if (getpeername (infile, (struct sockaddr*)&cs, &len) < 0)
+ syslog (LOG_ERR, "can't obtain IP address of client: %s",
+ strerror (errno));
+ else
+ syslog (LOG_INFO, "connect from %s", inet_ntoa(cs.sin_addr));
+ }
/* Greetings. */
util_out (RESP_OK, "IMAP4rev1 GNU " PACKAGE " " VERSION);
@@ -71,5 +211,164 @@ imap4d_mainloop (int infile, int outfile)
}
closelog ();
+ return EXIT_SUCCESS;
+}
+
+/* Sets things up for daemon mode. */
+static void
+imap4d_daemon_init (void)
+{
+ pid_t pid;
+
+ pid = fork ();
+ if (pid == -1)
+ {
+ perror ("fork failed:");
+ exit (1);
+ }
+ else if (pid > 0)
+ exit (0); /* Parent exits. */
+
+ setsid (); /* Become session leader. */
+
+ signal (SIGHUP, SIG_IGN); /* Ignore SIGHUP. */
+
+ /* The second fork is to guarantee that the daemon cannot acquire a
+ controlling terminal. */
+ pid = fork ();
+ if (pid == -1)
+ {
+ perror("fork failed:");
+ exit (1);
+ }
+ else if (pid > 0)
+ exit (0); /* Parent exits. */
+
+ /* Close inherited file descriptors. */
+ {
+ size_t i;
+#if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
+ size_t fdlimit = sysconf(_SC_OPEN_MAX);
+#else
+ size_t fdlimit = 64;
+#endif
+ for (i = 0; i < fdlimit; ++i)
+ close (i);
+ }
+
+ /* SIGCHLD is not ignore but rather use to do some simple load balancing. */
+#ifdef HAVE_SIGACTION
+ {
+ struct sigaction act;
+ act.sa_handler = imap4d_sigchld;
+ sigemptyset (&act.sa_mask);
+ act.sa_flags = 0;
+ sigaction (SIGCHLD, &act, NULL);
+ }
+#else
+ signal (SIGCHLD, imap4d_sigchld);
+#endif
+}
+
+/* Runs GNU imap4d in standalone daemon mode. This opens and binds to a port
+ (default 143) then executes a imap4d_mainloop() upon accepting a connection.
+ It starts maxchildren child processes to listen to and accept socket
+ connections. */
+static void
+imap4d_daemon (unsigned int maxchildren, unsigned int port)
+{
+ struct sockaddr_in server, client;
+ pid_t pid;
+ int listenfd, connfd;
+ size_t size;
+
+ listenfd = socket (AF_INET, SOCK_STREAM, 0);
+ if (listenfd == -1)
+ {
+ syslog (LOG_ERR, "socket: %s", strerror(errno));
+ exit (1);
+ }
+ size = 1; /* Use size here to avoid making a new variable. */
+ setsockopt (listenfd, SOL_SOCKET, SO_REUSEADDR, &size, sizeof(size));
+ size = sizeof (server);
+ memset (&server, 0, size);
+ server.sin_family = AF_INET;
+ server.sin_addr.s_addr = htonl (INADDR_ANY);
+ server.sin_port = htons (port);
+
+ if (bind (listenfd, (struct sockaddr *)&server, size) == -1)
+ {
+ syslog (LOG_ERR, "bind: %s", strerror (errno));
+ exit (1);
+ }
+
+ if (listen (listenfd, 128) == -1)
+ {
+ syslog (LOG_ERR, "listen: %s", strerror (errno));
+ exit (1);
+ }
+
+ for (;;)
+ {
+ if (children > maxchildren)
+ {
+ syslog (LOG_ERR, "too many children (%d)", children);
+ pause ();
+ continue;
+ }
+ connfd = accept (listenfd, (struct sockaddr *)&client, &size);
+ if (connfd == -1)
+ {
+ if (errno == EINTR)
+ continue;
+ syslog (LOG_ERR, "accept: %s", strerror (errno));
+ exit (1);
+ }
+
+ pid = fork ();
+ if (pid == -1)
+ syslog(LOG_ERR, "fork: %s", strerror (errno));
+ else if (pid == 0) /* Child. */
+ {
+ int status;
+ close (listenfd);
+ status = imap4d_mainloop (connfd, connfd);
+ closelog ();
+ exit (status);
+ }
+ else
+ {
+ ++children;
+ }
+ close (connfd);
+ }
+}
+
+/* Prints out usage information and exits the program */
+
+static void
+imap4d_usage (char *argv0)
+{
+ printf ("Usage: %s [OPTIONS]\n", argv0);
+ printf ("Runs the GNU IMAP4 daemon.\n\n");
+ printf (" -d, --daemon=MAXCHILDREN runs in daemon mode with a maximum\n");
+ printf (" of MAXCHILDREN child processes\n");
+ printf (" -h, --help display this help and exit\n");
+ printf (" -i, --inetd runs in inetd mode (default)\n");
+ printf (" -p, --port=PORT specifies port to listen on, implies -d\n"
+);
+ printf (" defaults to 143, which need not be specifi
+ed\n");
+ printf (" -t, --timeout=TIMEOUT sets idle timeout to TIMEOUT seconds\n");
+ printf (" TIMEOUT default is 1800 (30 minutes)\n");
+ printf (" -v, --version display version information and exit\n");
+ printf ("\nReport bugs to bug-mailutils@gnu.org\n");
+ exit (0);
+}
+
+static int
+syslog_error_printer (const char *fmt, va_list ap)
+{
+ vsyslog (LOG_CRIT, fmt, ap);
return 0;
}
diff --git a/imap4d/imap4d.h b/imap4d/imap4d.h
index 1d346e8fa..d5aa8e2d6 100644
--- a/imap4d/imap4d.h
+++ b/imap4d/imap4d.h
@@ -49,6 +49,12 @@
#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>
+#include <signal.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include "getopt.h"
#ifdef HAVE_ALLOCA_H
# include <alloca.h>
@@ -66,6 +72,7 @@
#include <mailutils/registrar.h>
#include <mailutils/filter.h>
#include <mailutils/stream.h>
+#include <mailutils/error.h>
#ifdef __cplusplus
extern "C" {
@@ -89,6 +96,10 @@ struct imap4d_command
char *tag;
};
+/* Daemon modes. */
+#define INTERACTIVE 0
+#define DAEMON 1
+
/* Global variables and constants*/
#define STATE_NONE (0)
#define STATE_NONAUTH (1 << 0)
@@ -107,8 +118,11 @@ struct imap4d_command
#define RESP_NONE 4
/* Error values. */
+#define OK 0
#define ERR_NO_MEM 1
#define ERR_NO_OFILE 2
+#define ERR_TIMEOUT 3
+#define ERR_SIGNAL 4
extern struct imap4d_command imap4d_command_table[];
extern FILE *ofile;
@@ -116,42 +130,48 @@ extern unsigned int timeout;
extern mailbox_t mbox;
extern char *homedir;
extern int state;
+extern volatile size_t children;
/* Imap4 commands */
-extern int imap4d_capability __P ((struct imap4d_command *, char *));
-extern int imap4d_noop __P ((struct imap4d_command *, char *));
-extern int imap4d_logout __P ((struct imap4d_command *, char *));
-extern int imap4d_authenticate __P ((struct imap4d_command *, char *));
-extern int imap4d_login __P ((struct imap4d_command *, char *));
-extern int imap4d_select __P ((struct imap4d_command *, char *));
-extern int imap4d_select0 __P ((struct imap4d_command *, char *, int));
-extern int imap4d_examine __P ((struct imap4d_command *, char *));
-extern int imap4d_create __P ((struct imap4d_command *, char *));
-extern int imap4d_delete __P ((struct imap4d_command *, char *));
-extern int imap4d_rename __P ((struct imap4d_command *, char *));
-extern int imap4d_subscribe __P ((struct imap4d_command *, char *));
-extern int imap4d_unsubscribe __P ((struct imap4d_command *, char *));
-extern int imap4d_list __P ((struct imap4d_command *, char *));
-extern int imap4d_lsub __P ((struct imap4d_command *, char *));
-extern int imap4d_status __P ((struct imap4d_command *, char *));
extern int imap4d_append __P ((struct imap4d_command *, char *));
+extern int imap4d_authenticate __P ((struct imap4d_command *, char *));
+extern int imap4d_capability __P ((struct imap4d_command *, char *));
extern int imap4d_check __P ((struct imap4d_command *, char *));
extern int imap4d_close __P ((struct imap4d_command *, char *));
+extern int imap4d_copy __P ((struct imap4d_command *, char *));
+extern int imap4d_copy0 __P ((char *, int, char *, size_t));
+extern int imap4d_create __P ((struct imap4d_command *, char *));
+extern int imap4d_delete __P ((struct imap4d_command *, char *));
+extern int imap4d_examine __P ((struct imap4d_command *, char *));
extern int imap4d_expunge __P ((struct imap4d_command *, char *));
-extern int imap4d_search __P ((struct imap4d_command *, char *));
extern int imap4d_fetch __P ((struct imap4d_command *, char *));
extern int imap4d_fetch0 __P ((char *, int, char *, size_t));
+extern int imap4d_list __P ((struct imap4d_command *, char *));
+extern int imap4d_lsub __P ((struct imap4d_command *, char *));
+extern int imap4d_login __P ((struct imap4d_command *, char *));
+extern int imap4d_logout __P ((struct imap4d_command *, char *));
+extern int imap4d_noop __P ((struct imap4d_command *, char *));
+extern int imap4d_rename __P ((struct imap4d_command *, char *));
+extern int imap4d_search __P ((struct imap4d_command *, char *));
+extern int imap4d_select __P ((struct imap4d_command *, char *));
+extern int imap4d_select0 __P ((struct imap4d_command *, char *, int));
+extern int imap4d_status __P ((struct imap4d_command *, char *));
extern int imap4d_store __P ((struct imap4d_command *, char *));
extern int imap4d_store0 __P ((char *, int, char *, size_t));
-extern int imap4d_copy __P ((struct imap4d_command *, char *));
-extern int imap4d_copy0 __P ((char *, int, char *, size_t));
+extern int imap4d_subscribe __P ((struct imap4d_command *, char *));
extern int imap4d_uid __P ((struct imap4d_command *, char *));
+extern int imap4d_unsubscribe __P ((struct imap4d_command *, char *));
/* Synchronisation on simultenous access. */
extern int imap4d_sync __P ((void));
extern int imap4d_sync_flags __P ((size_t));
extern size_t uid_to_msgno __P ((size_t));
+/* Signal handling. */
+extern RETSIGTYPE imap4d_sigchld __P ((int));
+extern RETSIGTYPE imap4d_signal __P ((int));
+extern int imap4d_bye __P ((int));
+
/* Helper functions. */
extern int util_out __P ((int, const char *, ...));
extern int util_send __P ((const char *, ...));
@@ -160,7 +180,6 @@ extern int util_finish __P ((struct imap4d_command *, int, const char *, ...));
extern int util_getstate __P ((void));
extern int util_do_command __P ((char *));
extern char *imap4d_readline __P ((FILE*));
-extern void util_quit __P ((int));
extern char *util_getword __P ((char *, char **));
extern int util_token __P ((char *, size_t, char **));
extern void util_unquote __P ((char **));
diff --git a/imap4d/list.c b/imap4d/list.c
index 7716aef18..ab59e0287 100644
--- a/imap4d/list.c
+++ b/imap4d/list.c
@@ -47,7 +47,7 @@
static int match __P ((const char *, const char *, const char *));
static int imap_match __P ((const char *, const char *, const char *));
-static void list_file __P ((const char *, const char *, char *, const char *));
+static void list_file __P ((const char *, const char *, const char *, const char *));
static void print_file __P ((const char *, const char *, const char *));
static void print_dir __P ((const char *, const char *, const char *));
@@ -150,7 +150,7 @@ imap4d_list (struct imap4d_command *command, char *arg)
if (chdir (cwd) == 0)
{
- list_file (cwd, ref, dir, delim);
+ list_file (cwd, ref, (dir) ? dir : "", delim);
chdir (homedir);
}
free (cwd);
@@ -161,17 +161,22 @@ imap4d_list (struct imap4d_command *command, char *arg)
/* Recusively calling the files. */
static void
-list_file (const char *cwd, const char *ref, char *pattern, const char *delim)
+list_file (const char *cwd, const char *ref, const char *pattern,
+ const char *delim)
{
DIR *dirp;
struct dirent *dp;
char *next;
/* Shortcut no wildcards. */
- if (!strpbrk (pattern, "%*"))
+ if (*pattern == '\0' || !strpbrk (pattern, "%*"))
{
/* Equivalent to stat(). */
- int status = match (pattern, pattern, delim);
+ int status;
+ if (*pattern == '\0')
+ status = match (cwd, cwd, delim);
+ else
+ status = match (pattern, pattern, delim);
if (status & NOSELECT)
print_dir (ref, pattern, delim);
else if (status & NOINFERIORS)
diff --git a/imap4d/login.c b/imap4d/login.c
index 7e1d15274..854fd95c4 100644
--- a/imap4d/login.c
+++ b/imap4d/login.c
@@ -32,7 +32,7 @@ static int _perr = 0;
return util_finish (command, RESP_NO, "User name or passwd rejected"); }
static int
-PAM_gnupop3d_conv (int num_msg, const struct pam_message **msg,
+PAM_gnuimap4d_conv (int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr)
{
int replies = 0;
@@ -73,7 +73,7 @@ PAM_gnupop3d_conv (int num_msg, const struct pam_message **msg,
return PAM_SUCCESS;
}
-static struct pam_conv PAM_conversation = { &PAM_gnupop3d_conv, NULL };
+static struct pam_conv PAM_conversation = { &PAM_gnuimap4d_conv, NULL };
#endif /* USE_LIBPAM */
int
@@ -91,12 +91,16 @@ imap4d_login (struct imap4d_command *command, char *arg)
username = util_getword (arg, &sp);
pass = util_getword (NULL, &sp);
- if (username == NULL || pass == NULL)
+ /* Remove the double quotes. */
+ util_unquote (&username);
+ util_unquote (&pass);
+
+ if (username == NULL || *username == '\0' || pass == NULL)
return util_finish (command, RESP_NO, "Too few args");
else if (util_getword (NULL, &sp))
return util_finish (command, RESP_NO, "Too many args");
- pw = getpwnam (arg);
+ pw = getpwnam (username);
#ifndef USE_LIBPAM
if (pw == NULL || pw->pw_uid < 1)
@@ -105,17 +109,17 @@ imap4d_login (struct imap4d_command *command, char *arg)
{
#ifdef HAVE_SHADOW_H
struct spwd *spw;
- spw = getspnam (arg);
+ spw = getspnam (username);
if (spw == NULL || strcmp (spw->sp_pwdp, (char *)crypt (pass, spw->sp_pwdp)))
#endif /* HAVE_SHADOW_H */
return util_finish (command, RESP_NO, "User name or passwd rejected");
}
#else /* !USE_LIBPAM */
- _user = (char *) arg;
+ _user = (char *) username;
_pwd = pass;
/* libpam doesn't log to LOG_MAIL */
closelog ();
- pamerror = pam_start ("gnu-imap4d", arg, &PAM_conversation, &pamh);
+ pamerror = pam_start ("gnu-imap4d", username, &PAM_conversation, &pamh);
PAM_ERROR;
pamerror = pam_authenticate (pamh, 0);
PAM_ERROR;
diff --git a/imap4d/logout.c b/imap4d/logout.c
index 029df63ed..0d29e999a 100644
--- a/imap4d/logout.c
+++ b/imap4d/logout.c
@@ -29,7 +29,6 @@ imap4d_logout (struct imap4d_command *command, char *arg)
return util_finish (command, RESP_BAD, "Wrong state");
if (util_getword (arg, &sp))
return util_finish (command, RESP_BAD, "Too many args");
- util_out (RESP_BYE, "Logging out");
util_finish (command, RESP_OK, "Completed");
/* Even if a mailbox is slected, a SLECT EXAMINE or LOGOUT
command MAY be issued without previously issuing a CLOSE command.
@@ -40,6 +39,6 @@ imap4d_logout (struct imap4d_command *command, char *arg)
mailbox_close (mbox);
mailbox_destroy (&mbox);
}</