diff options
author | Alain Magloire <alainm@gnu.org> | 2001-05-09 04:23:52 +0000 |
---|---|---|
committer | Alain Magloire <alainm@gnu.org> | 2001-05-09 04:23:52 +0000 |
commit | b0f41a7171dc889b5cf45b6d0ce60c5df462663e (patch) | |
tree | 4f29e650f4ada69cdb5859ded611f1c25ef59e9c | |
parent | 5c2bb9274e7e5826e220c29e7b4f5a03269d2d27 (diff) | |
download | mailutils-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-- | ChangeLog | 21 | ||||
-rw-r--r-- | imap4d/Makefile.am | 8 | ||||
-rw-r--r-- | imap4d/fetch.c | 132 | ||||
-rw-r--r-- | imap4d/imap4d.c | 319 | ||||
-rw-r--r-- | imap4d/imap4d.h | 59 | ||||
-rw-r--r-- | imap4d/list.c | 15 | ||||
-rw-r--r-- | imap4d/login.c | 18 | ||||
-rw-r--r-- | imap4d/logout.c | 3 | ||||
-rw-r--r-- | imap4d/lsub.c | 36 | ||||
-rw-r--r-- | imap4d/select.c | 7 | ||||
-rw-r--r-- | imap4d/store.c | 52 | ||||
-rw-r--r-- | imap4d/subscribe.c | 25 | ||||
-rw-r--r-- | imap4d/sync.c | 6 | ||||
-rw-r--r-- | imap4d/unsubscribe.c | 63 | ||||
-rw-r--r-- | imap4d/util.c | 35 | ||||
-rw-r--r-- | mailbox/filter_rfc822.c | 19 | ||||
-rw-r--r-- | mailbox/folder_imap.c | 1 | ||||
-rw-r--r-- | mailbox/url_imap.c | 62 | ||||
-rw-r--r-- | pop3d/extra.c | 40 | ||||
-rw-r--r-- | pop3d/pop3d.c | 58 | ||||
-rw-r--r-- | pop3d/pop3d.h | 28 | ||||
-rw-r--r-- | pop3d/signal.c | 18 |
22 files changed, 761 insertions, 264 deletions
@@ -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); } |