Commit b0f41a71 b0f41a7171dc889b5cf45b6d0ce60c5df462663e by Alain Magloire

Finally!!!! I can use the GNU imap4d with Netscape .... It kinda work 8-)

sigh ... still more to do.
1 parent 5c2bb927
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
......
......@@ -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
......
......@@ -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]);
msgno = (isuid) ? uid_to_msgno (set[i]) : set[i];
if (msgno)
{
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 != ')')
{
util_token (item, sizeof (item), &items);
if (uid_sent && strcasecmp (item, "UID") == 0)
continue;
if (fcmd)
util_send (" ");
space = 1;
/* Search in the table. */
fcmd = fetch_getcommand (item, fetch_command_table);
if (fcmd)
{
fcmd->msgno = (isuid) ? uid_to_msgno (set[i]) : set[i];
if (fcmd->msgno != 0)
if (space)
{
rc = fcmd->func (fcmd, items);
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)
{
start = 0;
util_send (" {%u}\r\n", end);
}
else
util_send ("<%lu> {%u}\r\n", start , end);
while (start < end &&
stream_read (rfc, buffer, sizeof (buffer), start, &n) == 0
&& n > 0)
p = buffer = calloc (end + 2, 1);
while (end > 0 && stream_read (rfc, buffer, end + 1, offset, &n) == 0 && n > 0)
{
start += n;
offset += n;
total += n;
if (total > end)
{
size_t diff = n - (total - end);
buffer[diff] = '\0';
end -= n;
buffer += n;
}
util_send ("%s", buffer);
/* Make sure we null terminate. */
*buffer = '\0';
if (start != ULONG_MAX)
util_send ("<%lu>", start);
if (total)
{
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);
}
}
}
......
......@@ -23,37 +23,177 @@ mailbox_t mbox;
char *homedir;
int state = STATE_NONAUTH;
/* 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;
}
......
......@@ -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 **));
......
......@@ -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)
......
......@@ -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;
......
......@@ -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);
}
util_quit (0);
imap4d_bye (OK);
return 0;
}
......
......@@ -24,7 +24,41 @@
int
imap4d_lsub (struct imap4d_command *command, char *arg)
{
char *sp;
char *ref;
char *wcard;
char *file;
const char *delim = "/";
FILE *fp;
if (! (command->states & state))
return util_finish (command, RESP_BAD, "Wrong state");
return util_finish (command, RESP_NO, "Not supported");
ref = util_getword (arg, &sp);
wcard = util_getword (NULL, &sp);
if (!ref || !wcard)
return util_finish (command, RESP_BAD, "Too few arguments");
/* Remove the double quotes. */
util_unquote (&ref);
util_unquote (&wcard);
/* FIXME: Get the matching in list. */
asprintf (&file, "%s/.mailboxlist", homedir);
fp = fopen (file, "r");
free (file);
if (fp)
{
char buffer[124];
while (fgets (buffer, sizeof (buffer), fp))
{
size_t n = strlen (buffer);
if (n && buffer[n - 1] == '\n')
buffer[n - 1] = '\0';
util_out (RESP_NONE, "LIST () \"%s\" %s", delim, buffer);
}
fclose (fp);
return util_finish (command, RESP_OK, "Completed");
}
return util_finish (command, RESP_NO, "Can not list subscriber");
}
......
......@@ -37,10 +37,9 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags)
/* FIXME: Check state. */
mailbox_name = util_getword (arg, &sp);
if (mailbox_name == NULL)
util_unquote (&mailbox_name);
if (mailbox_name == NULL || *mailbox_name == '\0')
return util_finish (command, RESP_BAD, "Too few arguments");
if (util_getword (NULL, &sp))
return util_finish (command, RESP_BAD, "Too many arguments");
/* Even if a mailbox is slected, a SLECT EXAMINE or LOGOUT
command MAY be issued without previously issuing a CLOSE command.
......@@ -56,7 +55,7 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags)
if (strcasecmp (mailbox_name, "INBOX") == 0)
{
pw = getpwuid (getuid());
pw = getpwuid (getuid ());
if (pw)
mailbox_name = pw->pw_name;
}
......
......@@ -109,8 +109,11 @@ imap4d_store0 (char *arg, int isuid, char *resp, size_t resplen)
char *flags = strdup ("");
int first = 1;
size_t msgno;
char *p = items;
msgno = (isuid) ? uid_to_msgno (set[i]) : set[i];
if (msgno)
{
mailbox_get_message (mbox, msgno, &msg);
message_get_attribute (msg, &attr);
......@@ -141,9 +144,10 @@ imap4d_store0 (char *arg, int isuid, char *resp, size_t resplen)
strcat (flags, item);
}
}
}
if (ack && *flags)
util_out (RESP_NONE, "%d FETCH FLAGS (%s)", set[i], flags);
free (items);
util_out (RESP_NONE, "%d FETCH FLAGS (%s)", msgno, flags);
free (p);
free (flags);
/* Update the flags of uid table. */
imap4d_sync_flags (set[i]);
......
......@@ -18,13 +18,34 @@
#include "imap4d.h"
/*
*
FIXME: We need to lock the file to prevent simultaneous access.
*/
int
imap4d_subscribe (struct imap4d_command *command, char *arg)
{
char *sp = NULL;
char *name;
char *file;
FILE *fp;
if (! (command->states & state))
return util_finish (command, RESP_BAD, "Wrong state");
return util_finish (command, RESP_NO, "Not supported");
name = util_getword (arg, &sp);
util_unquote (&name);
if (!name || *name == '\0')
return util_finish (command, RESP_BAD, "Too few arguments");
asprintf (&file, "%s/.mailboxlist", homedir);
fp = fopen (file, "a");
free (file);
if (fp)
{
fputs (name, fp);
fputs ("\n", fp);
fclose (fp);
return util_finish (command, RESP_OK, "Completed");
}
return util_finish (command, RESP_NO, "Can not subscribe");
}
......
......@@ -37,7 +37,7 @@ add_flag (char **pbuf, const char *f)
char *abuf = *pbuf;
abuf = realloc (abuf, strlen (abuf) + strlen (f) + 2);
if (abuf == NULL)
util_quit (ERR_NO_MEM);
imap4d_bye (ERR_NO_MEM);
if (*abuf)
strcat (abuf, " ");
strcat (abuf, "\\Seen");
......@@ -58,7 +58,7 @@ notify_flag (size_t msgno, attribute_t oattr)
{
char *abuf = malloc (1);;
if (!abuf)
util_quit (ERR_NO_MEM);
imap4d_bye (ERR_NO_MEM);
*abuf = '\0';
if (attribute_is_seen (nattr) && attribute_is_read (nattr))
if (!attribute_is_seen (oattr) && !attribute_is_read (oattr))
......@@ -197,7 +197,7 @@ reset_uids (void)
uid_table = realloc (uid_table, sizeof (*uid_table) *
(uid_table_count + 1));
if (!uid_table)
util_quit (ERR_NO_MEM);
imap4d_bye (ERR_NO_MEM);
mailbox_get_message (mbox, i, &msg);
message_get_attribute (msg, &attr);
message_get_uid (msg, &uid);
......
......@@ -24,7 +24,68 @@
int
imap4d_unsubscribe (struct imap4d_command *command, char *arg)
{
char *sp = NULL;
char *name;
char *file;
FILE *fp;
if (! (command->states & state))
return util_finish (command, RESP_BAD, "Wrong state");
return util_finish (command, RESP_NO, "Not supported");
name = util_getword (arg, &sp);
util_unquote (&name);
if (!name || *name == '\0')
return util_finish (command, RESP_BAD, "Too few arguments");
asprintf (&file, "%s/.mailboxlist", homedir);
fp = fopen (file, "r");
free (file);
if (fp)
{
char buffer[124];
int found = 0;
while (fgets (buffer, sizeof (buffer), fp))
{
size_t n = strlen (buffer);
if (n && buffer[n - 1] == '\n')
buffer[n - 1] = '\0';
if (strcmp (buffer, name) == 0)
{
found = 1;
break;
}
}
if (found)
{
FILE *fp2;
asprintf (&file, "%s/.mailboxlist.%d", homedir, getpid ());
fp2 = fopen (file, "a");
if (fp2)
{
rewind (fp);
while (fgets (buffer, sizeof (buffer), fp))
{
size_t n = strlen (buffer);
if (n && buffer[n - 1] == '\n')
buffer[n - 1] = '\0';
if (strcmp (buffer, name) == 0)
continue;
fputs (buffer, fp2);
fputs ("\n", fp2);
}
fclose (fp2);
remove (file);
}
free (file);
}
else
{
fclose (fp);
return util_finish (command, RESP_NO, "Can not unsubscribe");
}
fclose (fp);
}
else
return util_finish (command, RESP_NO, "Can not unsubscribe");
return util_finish (command, RESP_OK, "Completed");
}
......
......@@ -184,6 +184,9 @@ util_msgset (char *s, size_t **set, int *n, int isuid)
status = mailbox_messages_count (mbox, &max);
if (status != 0)
return status;
/* The number after the "*" in an untagged FETCH response is always a
message sequence number, not a unique identifier, even for a UID
command response. But do what they meant not what they say. */
/* If it is a uid sequence, override max with the UID. */
if (isuid)
{
......@@ -357,24 +360,26 @@ imap4d_readline (FILE *fp)
char *line = malloc (1);
if (!line)
util_quit (ERR_NO_MEM);
imap4d_bye (ERR_NO_MEM);
line[0] = '\0'; /* start with a empty string. */
do
{
alarm (timeout);
if (fgets (buffer, sizeof (buffer), fp) == NULL)
util_quit (0); /* Logout. */
{
imap4d_bye (ERR_NO_OFILE); /* Logout. */
}
alarm (0);
len = strlen (buffer);
/* If we were in a litteral substract. We have to do it since the CR
/* If we were in a litteral substract. We have to do here since the CR
is part of the count in a literal. */
if (number)
number -= len;
/* Remove CR. */
if (len > 2 && buffer[len - 1] == '\n')
if (len > 1 && buffer[len - 1] == '\n')
{
if (buffer[len - 2] == '\r')
{
......@@ -382,10 +387,9 @@ imap4d_readline (FILE *fp)
buffer[len - 1] = '\0';
}
}
line = realloc (line, total + len + 1);
if (!line)
util_quit (ERR_NO_MEM);
imap4d_bye (ERR_NO_MEM);
strcat (line, buffer);
total = strlen (line);
......@@ -413,6 +417,7 @@ imap4d_readline (FILE *fp)
}
}
while (number > 0);
/* syslog (LOG_INFO, "readline: %s", line); */
return line;
}
......@@ -474,24 +479,6 @@ util_start (char *tag)
return 0;
}
/* FIXME: Incomplete send errmsg to syslog, see pop3d:pop3_abquit(). */
void
util_quit (int err)
{
switch (err)
{
case ERR_NO_OFILE:
/*util_out (RESP_BYE, "Server terminating dead socket."); */
break;
case ERR_NO_MEM:
util_out (RESP_BYE, "Server terminating no more ressources.");
break;
default:
util_out (RESP_BYE, "Server terminating");
}
exit (err);
}
/* FIXME: What is this for? */
int
util_getstate (void)
......
......@@ -126,11 +126,18 @@ rfc822_read0 (filter_t filter, char *buffer, size_t buflen,
/* Catch up i.e bring us to the current offset. */
if (rfc822->r_offset != off)
{
rfc822->r_offset = off - rfc822->lines;
rfc822->residue = 0;
/* Try to find a starting point. */
if (rfc822->lines)
{
rfc822->r_offset = off - rfc822->lines;
if (rfc822->r_offset < 0)
rfc822->r_offset = 0;
}
else
rfc822->r_offset = 0;
rfc822->s_offset = rfc822->r_offset;
while (rfc822->r_offset < off)
......@@ -141,7 +148,11 @@ rfc822_read0 (filter_t filter, char *buffer, size_t buflen,
if (status != 0)
return status;
if (n == 0)
break;
{
if (pnread)
*pnread = 0;
return 0;
}
if (c == '\n')
{
rfc822->r_offset++;
......@@ -191,7 +202,7 @@ rfc822_read0 (filter_t filter, char *buffer, size_t buflen,
buffer += nread;
} while (buflen > 0 && !isreadline);
if (isreadline)
if (isreadline && buffer)
*buffer = '\0';
if (pnread)
......
......@@ -812,6 +812,7 @@ imap_literal_string (f_imap_t f_imap, char **ptr)
for (len0 = len = total = 0; total < f_imap->callback.nleft; total += (len + 1))
{
status = imap_readline (f_imap);
/*fprintf (stderr, "%d: %s", strlen (f_imap->buffer), f_imap->buffer);*/
if (status != 0)
{
/* Return what we got so far. */
......
......@@ -45,7 +45,8 @@ url_imap_destroy (url_t url)
int
_url_imap_init (url_t url)
{
const char *host, *indexe;
const char *host_port;
const char *indexe;
char *name = url->name;
/* reject the obvious */
......@@ -67,12 +68,12 @@ _url_imap_init (url_t url)
name += MU_IMAP_SCHEME_LEN; /* pass the scheme */
host = strchr (name, '@');
if (host == NULL)
host= name;
host_port = strchr (name, '@');
if (host_port == NULL)
host_port = name;
/* looking for ";auth=auth-enc" */
for (indexe = name; indexe != host; indexe++)
for (indexe = name; indexe != host_port; indexe++)
{
/* Auth ? */
if (*indexe == ';')
......@@ -93,7 +94,7 @@ _url_imap_init (url_t url)
((char *)memcpy(url->user, name, indexe - name))[indexe - name] = '\0';
/* AUTH */
if (indexe == host)
if (indexe == host_port)
{
/* Use default AUTH '*' */
url->auth = malloc (1 + 1);
......@@ -107,11 +108,11 @@ _url_imap_init (url_t url)
{
/* move pass AUTH= */
indexe += 6;
url->auth = malloc (host - indexe + 1);
url->auth = malloc (host_port - indexe + 1);
if (url->auth)
{
((char *)memcpy (url->auth, indexe, host - indexe))
[host - indexe] = '\0';
((char *)memcpy (url->auth, indexe, host_port - indexe))
[host_port - indexe] = '\0';
}
}
......@@ -121,19 +122,45 @@ _url_imap_init (url_t url)
return -1;
}
/* HOST*/
if (*host == '@')
host++;
/* HOST:PORT*/
if (*host_port == '@')
host_port++;
indexe = strchr (host_port, ':');
if (indexe)
{
char *s = NULL;
long int p = strtol (indexe + 1, &s, 10);
url->host = malloc (indexe - host_port + 1);
if (url->host)
{
((char *)memcpy (url->host, host_port, indexe - host_port))
[indexe - host_port] = '\0';
}
url->port = (p == 0) ? MU_IMAP_PORT : p;
host_port = s;
}
else
url->port = MU_IMAP_PORT;
indexe = strchr (host_port, '/');
indexe = strchr (host, '/');
if (indexe == NULL)
url->host = strdup (host);
{
if (url->host == NULL)
url->host = strdup (host_port);
}
else
{
char *question;
url->host = malloc (indexe - host + 1);
if (url->host == NULL)
{
url->host = malloc (indexe - host_port + 1);
if (url->host)
((char *)memcpy (url->host, host, indexe - host))[indexe - host] = '\0';
((char *)memcpy (url->host, host_port, indexe - host_port))
[indexe - host_port] = '\0';
}
indexe++;
/* The query starts after a '?'. */
question = strchr (indexe, '?');
......@@ -155,6 +182,5 @@ _url_imap_init (url_t url)
return ENOMEM;
}
url->port = MU_IMAP_PORT;
return 0;
}
......
......@@ -126,45 +126,7 @@ pop3d_abquit (int reason)
}
closelog();
exit (1);
}
/* Prints out usage information and exits the program */
void
pop3d_usage (char *argv0)
{
printf ("Usage: %s [OPTIONS]\n", argv0);
printf ("Runs the GNU POP3 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 110, which need not be specified\n");
printf (" -t, --timeout=TIMEOUT sets idle timeout to TIMEOUT seconds\n");
printf (" TIMEOUT default is 600 (10 minutes)\n");
printf (" -v, --version display version information and exit\n");
printf ("\nReport bugs to bug-mailutils@gnu.org\n");
exit (0);
}
/* Default signal handler to call the pop3d_abquit() function */
RETSIGTYPE
pop3d_signal (int signo)
{
syslog (LOG_CRIT, "got signal %d", signo);
/* Master process. */
if (!ofile)
{
syslog(LOG_CRIT, "MASTER: exiting on signal");
exit (1); /* abort(); */
}
if (signo == SIGALRM)
pop3d_abquit (ERR_TIMEOUT);
pop3d_abquit (ERR_SIGNAL);
exit (EXIT_FAILURE);
}
/* Gets a line of input from the client, caller should free() */
......
......@@ -41,6 +41,10 @@ static struct option long_options[] =
const char *short_options ="d::hip:t:v";
static int syslog_error_printer __P ((const char *fmt, va_list ap));
static int pop3d_mainloop __P ((int, int));
static void pop3d_daemon_init __P ((void));
static void pop3d_daemon __P ((unsigned int, unsigned int));
static void pop3d_usage __P ((char *));
#ifndef DEFMAXCHILDREN
# define DEFMAXCHILDREN 10 /* Default maximum number of children */
......@@ -91,7 +95,7 @@ main (int argc, char **argv)
case 'v':
printf (IMPL " ("PACKAGE " " VERSION ")\n");
exit (0);
exit (EXIT_SUCCESS);
break;
default:
......@@ -104,13 +108,13 @@ main (int argc, char **argv)
if (gr == NULL)
{
perror ("Error getting mail group");
exit (1);
exit (EXIT_FAILURE);
}
if (setgid (gr->gr_gid) == -1)
{
perror ("Error setting mail group");
exit (1);
exit (EXIT_FAILURE);
}
/* Register the desire formats. We only need Mbox mail format. */
......@@ -136,7 +140,7 @@ main (int argc, char **argv)
if (mode == DAEMON)
pop3d_daemon_init ();
/* Make sure that to be in the root directory. */
/* Make sure we are in the root directory. */
chdir ("/");
/* Set up for syslog. */
......@@ -150,7 +154,7 @@ main (int argc, char **argv)
/* Actually run the daemon. */
if (mode == DAEMON)
pop3d_daemon (maxchildren, port);
/* exit (0) -- no way out of daemon except a signal. */
/* exit (EXIT_SUCCESS) -- no way out of daemon except a signal. */
else
status = pop3d_mainloop (fileno (stdin), fileno (stdout));
......@@ -160,7 +164,7 @@ main (int argc, char **argv)
}
/* Sets things up for daemon mode. */
void
static void
pop3d_daemon_init (void)
{
pid_t pid;
......@@ -169,10 +173,10 @@ pop3d_daemon_init (void)
if (pid == -1)
{
perror ("fork failed:");
exit (1);
exit (EXIT_FAILURE);
}
else if (pid > 0)
exit (0); /* Parent exits. */
exit (EXIT_SUCCESS); /* Parent exits. */
setsid (); /* Become session leader. */
......@@ -184,10 +188,10 @@ pop3d_daemon_init (void)
if (pid == -1)
{
perror("fork failed:");
exit (1);
exit (EXIT_FAILURE);
}
else if (pid > 0)
exit (0); /* Parent exits. */
exit (EXIT_SUCCESS); /* Parent exits. */
/* Close inherited file descriptors. */
{
......@@ -217,7 +221,7 @@ pop3d_daemon_init (void)
/* The main part of the daemon. This function reads input from the client and
executes the proper functions. Also handles the bulk of error reporting. */
int
static int
pop3d_mainloop (int infile, int outfile)
{
int status = OK;
......@@ -377,7 +381,7 @@ pop3d_mainloop (int infile, int outfile)
(default 110) then executes a pop3d_mainloop() upon accepting a connection.
It starts maxchildren child processes to listen to and accept socket
connections. */
void
static void
pop3d_daemon (unsigned int maxchildren, unsigned int port)
{
struct sockaddr_in server, client;
......@@ -389,7 +393,7 @@ pop3d_daemon (unsigned int maxchildren, unsigned int port)
if (listenfd == -1)
{
syslog (LOG_ERR, "socket: %s", strerror(errno));
exit (1);
exit (EXIT_FAILURE);
}
size = 1; /* Use size here to avoid making a new variable. */
setsockopt (listenfd, SOL_SOCKET, SO_REUSEADDR, &size, sizeof(size));
......@@ -402,13 +406,13 @@ pop3d_daemon (unsigned int maxchildren, unsigned int port)
if (bind (listenfd, (struct sockaddr *)&server, size) == -1)
{
syslog (LOG_ERR, "bind: %s", strerror (errno));
exit (1);
exit (EXIT_FAILURE);
}
if (listen (listenfd, 128) == -1)
{
syslog (LOG_ERR, "listen: %s", strerror (errno));
exit (1);
exit (EXIT_FAILURE);
}
for (;;)
......@@ -425,7 +429,7 @@ pop3d_daemon (unsigned int maxchildren, unsigned int port)
if (errno == EINTR)
continue;
syslog (LOG_ERR, "accept: %s", strerror (errno));
exit (1);
exit (EXIT_FAILURE);
}
pid = fork ();
......@@ -447,6 +451,28 @@ pop3d_daemon (unsigned int maxchildren, unsigned int port)
}
}
/* Prints out usage information and exits the program */
static void
pop3d_usage (char *argv0)
{
printf ("Usage: %s [OPTIONS]\n", argv0);
printf ("Runs the GNU POP3 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 110, which need not be specifi
ed\n");
printf (" -t, --timeout=TIMEOUT sets idle timeout to TIMEOUT seconds\n");
printf (" TIMEOUT default is 600 (10 minutes)\n");
printf (" -v, --version display version information and exit\n");
printf ("\nReport bugs to bug-mailutils@gnu.org\n");
exit (EXIT_SUCCESS);
}
static int
syslog_error_printer (const char *fmt, va_list ap)
{
......
......@@ -175,31 +175,27 @@ extern FILE *ofile;
extern char *md5shared;
extern volatile size_t children;
extern int pop3d_abquit __P ((int));
extern int pop3d_apop __P ((const char *));
extern char *pop3d_apopuser __P ((const char *));
extern char *pop3d_args __P ((const char *));
extern int pop3d_auth __P ((const char *));
extern int pop3d_capa __P ((const char *));
extern char *pop3d_cmd __P ((const char *));
extern int pop3d_dele __P ((const char *));
extern int pop3d_list __P ((const char *));
extern int pop3d_lock __P ((void));
extern int pop3d_noop __P ((const char *));
extern int pop3d_quit __P ((const char *));
extern char *pop3d_readline __P ((FILE *));
extern int pop3d_retr __P ((const char *));
extern int pop3d_rset __P ((const char *));
extern RETSIGTYPE pop3d_sigchld __P ((int));
extern RETSIGTYPE pop3d_signal __P ((int));
extern int pop3d_stat __P ((const char *));
extern int pop3d_top __P ((const char *));
extern int pop3d_touchlock __P ((void));
extern int pop3d_uidl __P ((const char *));
extern int pop3d_user __P ((const char *));
extern int pop3d_apop __P ((const char *));
extern int pop3d_auth __P ((const char *));
extern int pop3d_capa __P ((const char *));
extern char *pop3d_args __P ((const char *));
extern char *pop3d_cmd __P ((const char *));
extern int pop3d_abquit __P ((int));
extern int pop3d_lock __P ((void));
extern int pop3d_touchlock __P ((void));
extern int pop3d_unlock __P ((void));
extern int pop3d_mainloop __P ((int, int));
extern void pop3d_daemon __P ((size_t, unsigned int));
extern void pop3d_usage __P ((char *));
extern RETSIGTYPE pop3d_signal __P ((int));
extern RETSIGTYPE pop3d_sigchld __P ((int));
extern void pop3d_daemon_init __P ((void));
extern char *pop3d_apopuser __P ((const char *));
extern char *pop3d_readline __P ((FILE *));
#endif /* _POP3D_H */
......
......@@ -32,3 +32,21 @@ pop3d_sigchld (int signo)
signal (signo, pop3d_sigchld);
#endif
}
/* Default signal handler to call the pop3d_abquit() function */
RETSIGTYPE
pop3d_signal (int signo)
{
syslog (LOG_CRIT, "got signal %d", signo);
/* Master process. */
if (!ofile)
{
syslog (LOG_CRIT, "MASTER: exiting on signal");
exit (EXIT_FAILURE); /* abort(); */
}
if (signo == SIGALRM)
pop3d_abquit (ERR_TIMEOUT);
pop3d_abquit (ERR_SIGNAL);
}
......