summaryrefslogtreecommitdiff
path: root/imap/src/ipopd
diff options
context:
space:
mode:
Diffstat (limited to 'imap/src/ipopd')
-rw-r--r--imap/src/ipopd/Makefile58
-rw-r--r--imap/src/ipopd/ipop2d.c711
-rw-r--r--imap/src/ipopd/ipop3d.c1082
-rw-r--r--imap/src/ipopd/ipopd.875
-rw-r--r--imap/src/ipopd/makefile.nt57
-rw-r--r--imap/src/ipopd/makefile.ntk58
-rw-r--r--imap/src/ipopd/makefile.w2k56
7 files changed, 2097 insertions, 0 deletions
diff --git a/imap/src/ipopd/Makefile b/imap/src/ipopd/Makefile
new file mode 100644
index 00000000..accb5408
--- /dev/null
+++ b/imap/src/ipopd/Makefile
@@ -0,0 +1,58 @@
+# ========================================================================
+# Copyright 1988-2006 University of Washington
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+#
+# ========================================================================
+
+
+# Program: IPOPD client Makefile
+#
+# Author: Mark Crispin
+# Networks and Distributed Computing
+# Computing & Communications
+# University of Washington
+# Administration Building, AG-44
+# Seattle, WA 98195
+# Internet: MRC@CAC.Washington.EDU
+#
+# Date: 28 October 1990
+# Last Edited: 30 August 2006
+
+
+C = ../c-client
+CCLIENTLIB = $C/c-client.a
+SHELL = /bin/sh
+
+# Get local definitions from c-client directory
+
+CC = `cat $C/CCTYPE`
+CFLAGS = -I$C `cat $C/CFLAGS`
+LDFLAGS = $(CCLIENTLIB) `cat $C/LDFLAGS`
+
+ipopd: ipop2d ipop3d
+
+ipop2d: $(CCLIENTLIB) ipop2d.o
+ $(CC) $(CFLAGS) -o ipop2d ipop2d.o $(LDFLAGS)
+
+ipop3d: $(CCLIENTLIB) ipop3d.o
+ $(CC) $(CFLAGS) -o ipop3d ipop3d.o $(LDFLAGS)
+
+ipop2d.o: $C/mail.h $C/misc.h $C/osdep.h
+
+ipop3d.o: $C/mail.h $C/misc.h $C/osdep.h
+
+$(CCLIENTLIB):
+ cd $C;make
+
+clean:
+ rm -f *.o ipop2d ipop3d || true
+
+# A monument to a hack of long ago and far away...
+love:
+ @echo 'not war?'
diff --git a/imap/src/ipopd/ipop2d.c b/imap/src/ipopd/ipop2d.c
new file mode 100644
index 00000000..14cbe52f
--- /dev/null
+++ b/imap/src/ipopd/ipop2d.c
@@ -0,0 +1,711 @@
+/* ========================================================================
+ * Copyright 1988-2008 University of Washington
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *
+ * ========================================================================
+ */
+
+/*
+ * Program: IPOP2D - IMAP to POP2 conversion server
+ *
+ * Author: Mark Crispin
+ * UW Technology
+ * University of Washington
+ * Seattle, WA 98195
+ * Internet: MRC@Washington.EDU
+ *
+ * Date: 28 October 1990
+ * Last Edited: 13 February 2008
+ */
+
+
+/* Parameter files */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+extern int errno; /* just in case */
+#include <signal.h>
+#include <time.h>
+#include "c-client.h"
+
+
+/* Autologout timer */
+#define KODTIMEOUT 60*5
+#define LOGINTIMEOUT 60*3
+#define TIMEOUT 60*30
+
+
+/* Size of temporary buffers */
+#define TMPLEN 1024
+
+
+/* Server states */
+
+#define LISN 0
+#define AUTH 1
+#define MBOX 2
+#define ITEM 3
+#define NEXT 4
+#define DONE 5
+
+/* Global storage */
+
+char *version = "75"; /* edit number of this server */
+short state = LISN; /* server state */
+short critical = NIL; /* non-zero if in critical code */
+MAILSTREAM *stream = NIL; /* mailbox stream */
+time_t idletime = 0; /* time we went idle */
+unsigned long nmsgs = 0; /* number of messages */
+unsigned long current = 1; /* current message number */
+unsigned long size = 0; /* size of current message */
+char status[MAILTMPLEN]; /* space for status string */
+char *user = ""; /* user name */
+char *pass = ""; /* password */
+unsigned long *msg = NIL; /* message translation vector */
+char *logout = "Logout";
+char *goodbye = "+ Sayonara\015\012";
+
+
+/* Function prototypes */
+
+int main (int argc,char *argv[]);
+void sayonara (int status);
+void clkint ();
+void kodint ();
+void hupint ();
+void trmint ();
+short c_helo (char *t,int argc,char *argv[]);
+short c_fold (char *t);
+short c_read (char *t);
+short c_retr (char *t);
+short c_acks (char *t);
+short c_ackd (char *t);
+short c_nack (char *t);
+
+/* Main program */
+
+int main (int argc,char *argv[])
+{
+ char *s,*t;
+ char cmdbuf[TMPLEN];
+ char *pgmname = (argc && argv[0]) ?
+ (((s = strrchr (argv[0],'/')) || (s = strrchr (argv[0],'\\'))) ?
+ s+1 : argv[0]) : "ipop2d";
+ /* set service name before linkage */
+ mail_parameters (NIL,SET_SERVICENAME,(void *) "pop");
+#include "linkage.c"
+ if (mail_parameters (NIL,GET_DISABLEPLAINTEXT,NIL)) {
+ goodbye = "- POP2 server disabled on this system\015\012";
+ sayonara (1);
+ }
+ /* initialize server */
+ server_init (pgmname,"pop",NIL,clkint,kodint,hupint,trmint,NIL);
+ /* There are reports of POP2 clients which get upset if anything appears
+ * between the "+" and the "POP2" in the greeting.
+ */
+ printf ("+ POP2 %s %s.%s server ready\015\012",tcp_serverhost (),
+ CCLIENTVERSION,version);
+ fflush (stdout); /* dump output buffer */
+ state = AUTH; /* initial server state */
+ while (state != DONE) { /* command processing loop */
+ idletime = time (0); /* get a command under timeout */
+ alarm ((state != AUTH) ? TIMEOUT : LOGINTIMEOUT);
+ clearerr (stdin); /* clear stdin errors */
+ while (!fgets (cmdbuf,TMPLEN-1,stdin)) {
+ if (ferror (stdin) && (errno == EINTR)) clearerr (stdin);
+ else {
+ char *e = ferror (stdin) ?
+ strerror (errno) : "Unexpected client disconnect";
+ alarm (0); /* disable all interrupts */
+ server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
+ sprintf (logout = cmdbuf,"%.80s while reading line",e);
+ state = DONE;
+ stream = mail_close (stream);
+ goodbye = NIL;
+ sayonara (1);
+ }
+ }
+ alarm (0); /* make sure timeout disabled */
+ idletime = 0; /* no longer idle */
+ /* find end of line */
+ if (!strchr (cmdbuf,'\012')) {
+ server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
+ logout = "- Command line too long\015\012";
+ state = DONE;
+ }
+ else if (!(s = strtok (cmdbuf," \015\012"))) {
+ server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
+ goodbye = "- Missing or null command\015\012";
+ state = DONE;
+ }
+ else { /* dispatch based on command */
+ ucase (s); /* canonicalize case */
+ /* snarf argument */
+ t = strtok (NIL,"\015\012");
+ if ((state == AUTH) && !strcmp (s,"HELO")) state = c_helo (t,argc,argv);
+ else if ((state == MBOX || state == ITEM) && !strcmp (s,"FOLD"))
+ state = c_fold (t);
+ else if ((state == MBOX || state == ITEM) && !strcmp (s,"READ"))
+ state = c_read (t);
+ else if ((state == ITEM) && !strcmp (s,"RETR")) state = c_retr (t);
+ else if ((state == NEXT) && !strcmp (s,"ACKS")) state = c_acks (t);
+ else if ((state == NEXT) && !strcmp (s,"ACKD")) state = c_ackd (t);
+ else if ((state == NEXT) && !strcmp (s,"NACK")) state = c_nack (t);
+ else if ((state == AUTH || state == MBOX || state == ITEM) &&
+ !strcmp (s,"QUIT")) {
+ server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
+ state = DONE; /* done in either case */
+ if (t) goodbye = "- Bogus argument given to QUIT\015\012";
+ else { /* expunge the stream */
+ if (stream && nmsgs) stream = mail_close_full (stream,CL_EXPUNGE);
+ stream = NIL; /* don't repeat it */
+ }
+ }
+ else { /* some other or inappropriate command */
+ server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
+ goodbye = "- Bogus or out of sequence command\015\012";
+ state = DONE;
+ }
+ }
+ fflush (stdout); /* make sure output blatted */
+ }
+ /* clean up the stream */
+ if (stream) mail_close (stream);
+ sayonara (0);
+ return 0; /* stupid compilers */
+}
+
+
+/* Say goodbye
+ * Accepts: exit status
+ *
+ * Does not return
+ */
+
+void sayonara (int status)
+{
+ logouthook_t lgoh = (logouthook_t) mail_parameters (NIL,GET_LOGOUTHOOK,NIL);
+ if (goodbye) { /* have a goodbye message? */
+ fputs (goodbye,stdout);
+ fflush (stdout); /* make sure blatted */
+ }
+ syslog (LOG_INFO,"%s user=%.80s host=%.80s",logout,
+ user ? (char *) user : "???",tcp_clienthost ());
+ /* do logout hook if needed */
+ if (lgoh) (*lgoh) (mail_parameters (NIL,GET_LOGOUTDATA,NIL));
+ _exit (status); /* all done */
+}
+
+/* Clock interrupt
+ */
+
+void clkint ()
+{
+ alarm (0); /* disable all interrupts */
+ server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
+ goodbye = "- Autologout; idle for too long\015\012";
+ logout = "Autologout";
+ state = DONE; /* mark state done in either case */
+ if (!critical) { /* badly host if in critical code */
+ if (stream && !stream->lock) mail_close (stream);
+ stream = NIL;
+ sayonara (1); /* die die die */
+ }
+}
+
+
+/* Kiss Of Death interrupt
+ */
+
+void kodint ()
+{
+ /* only if in command wait */
+ if (idletime && ((time (0) - idletime) > KODTIMEOUT)) {
+ alarm (0); /* disable all interrupts */
+ server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
+ goodbye = "- Killed (lost mailbox lock)\015\012";
+ logout = "Killed (lost mailbox lock)";
+ state = DONE; /* mark state done in either case */
+ if (!critical) { /* badly host if in critical code */
+ if (stream && !stream->lock) mail_close (stream);
+ stream = NIL;
+ sayonara (1); /* die die die */
+ }
+ }
+}
+
+
+/* Hangup interrupt
+ */
+
+void hupint ()
+{
+ alarm (0); /* disable all interrupts */
+ server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
+ goodbye = NIL;
+ logout = "Hangup";
+ state = DONE; /* mark state done in either case */
+ if (!critical) { /* badly host if in critical code */
+ if (stream && !stream->lock) mail_close (stream);
+ stream = NIL;
+ sayonara (1); /* die die die */
+ }
+}
+
+
+/* Termination interrupt
+ */
+
+void trmint ()
+{
+ alarm (0); /* disable all interrupts */
+ server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
+ goodbye = "- Killed (terminated)\015\012";
+ logout = "Killed (terminated)";
+ if (critical) state = DONE; /* mark state done in either case */
+ /* Make no attempt at graceful closure since a shutdown may be in
+ * progress, and we won't have any time to do mail_close() actions.
+ */
+ else sayonara (1); /* die die die */
+}
+
+/* Parse HELO command
+ * Accepts: pointer to command argument
+ * Returns: new state
+ */
+
+short c_helo (char *t,int argc,char *argv[])
+{
+ char *s,*u,*p;
+ char tmp[TMPLEN];
+ if ((!(t && *t && (u = strtok (t," ")) && (p = strtok (NIL,"\015\012")))) ||
+ (strlen (p) >= TMPLEN)) { /* get user name and password */
+ fputs ("- Missing user or password\015\012",stdout);
+ return DONE;
+ }
+ /* copy password, handle quoting */
+ for (s = tmp; *p; p++) *s++ = (*p == '\\') ? *++p : *p;
+ *s = '\0'; /* tie off string */
+ pass = cpystr (tmp);
+ if (!(s = strchr (u,':'))) { /* want remote mailbox? */
+ /* no, delimit user from possible admin */
+ if (s = strchr (u,'*')) *s++ = '\0';
+ if (server_login (user = cpystr (u),pass,s,argc,argv)) {
+ syslog (LOG_INFO,"%sLogin user=%.80s host=%.80s",s ? "Admin " : "",
+ user,tcp_clienthost ());
+ return c_fold ("INBOX"); /* local; select INBOX */
+ }
+ }
+#ifndef DISABLE_POP_PROXY
+ /* can't do if can't log in as anonymous */
+ else if (anonymous_login (argc,argv)) {
+ *s++ = '\0'; /* separate host name from user name */
+ user = cpystr (s); /* note user name */
+ syslog (LOG_INFO,"IMAP login to host=%.80s user=%.80s host=%.80s",u,user,
+ tcp_clienthost ());
+ /* initially remote INBOX */
+ sprintf (tmp,"{%.128s/user=%.128s}INBOX",u,user);
+ /* disable rimap just in case */
+ mail_parameters (NIL,SET_RSHTIMEOUT,0);
+ return c_fold (tmp);
+ }
+#endif
+ fputs ("- Bad login\015\012",stdout);
+ return DONE;
+}
+
+/* Parse FOLD command
+ * Accepts: pointer to command argument
+ * Returns: new state
+ */
+
+short c_fold (char *t)
+{
+ unsigned long i,j,flags;
+ char *s = NIL,tmp[2*TMPLEN];
+ NETMBX mb;
+ if (!(t && *t)) { /* make sure there's an argument */
+ fputs ("- Missing mailbox name\015\012",stdout);
+ return DONE;
+ }
+ myusername_full (&flags); /* get user type flags */
+ /* expunge old stream */
+ if (stream && nmsgs) mail_expunge (stream);
+ nmsgs = 0; /* no more messages */
+ if (msg) fs_give ((void **) &msg);
+#ifndef DISABLE_POP_PROXY
+ if (flags == MU_ANONYMOUS) { /* don't permit proxy to leave IMAP */
+ if (stream) { /* not first time */
+ if (!(stream->mailbox && (s = strchr (stream->mailbox,'}'))))
+ fatal ("bad previous mailbox name");
+ strncpy (tmp,stream->mailbox,i = (++s - stream->mailbox));
+ if (i >= TMPLEN) fatal ("ridiculous network prefix");
+ strcpy (tmp+i,t); /* append mailbox to initial spec */
+ t = tmp;
+ }
+ /* must be net name first time */
+ else if (!mail_valid_net_parse (t,&mb)) fatal ("anonymous folder bogon");
+ }
+#endif
+ /* open mailbox, note # of messages */
+ if (j = (stream = mail_open (stream,t,NIL)) ? stream->nmsgs : 0) {
+ sprintf (tmp,"1:%lu",j); /* fetch fast information for all messages */
+ mail_fetch_fast (stream,tmp,NIL);
+ msg = (unsigned long *) fs_get ((stream->nmsgs + 1) *
+ sizeof (unsigned long));
+ for (i = 1; i <= j; i++) /* find undeleted messages, add to vector */
+ if (!mail_elt (stream,i)->deleted) msg[++nmsgs] = i;
+ }
+#ifndef DISABLE_POP_PROXY
+ if (!stream && (flags == MU_ANONYMOUS)) {
+ fputs ("- Bad login\015\012",stdout);
+ return DONE;
+ }
+#endif
+ printf ("#%lu messages in %s\015\012",nmsgs,stream ? stream->mailbox :
+ "<none>");
+ return MBOX;
+}
+
+/* Parse READ command
+ * Accepts: pointer to command argument
+ * Returns: new state
+ */
+
+short c_read (char *t)
+{
+ MESSAGECACHE *elt = NIL;
+ if (t && *t) { /* have a message number argument? */
+ /* validity check message number */
+ if (((current = strtoul (t,NIL,10)) < 1) || (current > nmsgs)) {
+ fputs ("- Invalid message number given to READ\015\012",stdout);
+ return DONE;
+ }
+ }
+ else if (current > nmsgs) { /* at end of mailbox? */
+ fputs ("=0 No more messages\015\012",stdout);
+ return MBOX;
+ }
+ /* set size if message valid and exists */
+ size = msg[current] ? (elt = mail_elt(stream,msg[current]))->rfc822_size : 0;
+ if (elt) sprintf (status,"Status: %s%s\015\012",
+ elt->seen ? "R" : " ",elt->recent ? " " : "O");
+ else status[0] = '\0'; /* no status */
+ size += strlen (status); /* update size to reflect status */
+ /* display results */
+ printf ("=%lu characters in message %lu\015\012",size + 2,current);
+ return ITEM;
+}
+
+
+/* Parse RETR command
+ * Accepts: pointer to command argument
+ * Returns: new state
+ */
+
+short c_retr (char *t)
+{
+ unsigned long i,j;
+ STRING *bs;
+ if (t) { /* disallow argument */
+ fputs ("- Bogus argument given to RETR\015\012",stdout);
+ return DONE;
+ }
+ if (size) { /* message size valid? */
+ t = mail_fetch_header (stream,msg[current],NIL,NIL,&i,FT_PEEK);
+ if (i > 2) { /* only if there is something */
+ i -= 2; /* lop off last two octets */
+ while (i) { /* blat the header */
+ if (!(j = fwrite (t,sizeof (char),i,stdout))) return DONE;
+ if (i -= j) t += j; /* advance to incomplete data */
+ }
+ }
+ fputs (status,stdout); /* yes, output message */
+ fputs ("\015\012",stdout); /* delimit header from text */
+ if (t = mail_fetch_text (stream,msg[current],NIL,&i,FT_RETURNSTRINGSTRUCT))
+ while (i) { /* blat the text */
+ if (!(j = fwrite (t,sizeof (char),i,stdout))) return DONE;
+ if (i -= j) t += j; /* advance to incomplete data */
+ }
+ else for (bs = &stream->private.string; i--; )
+ if (putc (SNX (bs),stdout) == EOF) return DONE;
+ fputs ("\015\012",stdout); /* trailer to coddle PCNFS' NFSMAIL */
+ }
+ else return DONE; /* otherwise go away */
+ return NEXT;
+}
+
+/* Parse ACKS command
+ * Accepts: pointer to command argument
+ * Returns: new state
+ */
+
+short c_acks (char *t)
+{
+ char tmp[TMPLEN];
+ if (t) { /* disallow argument */
+ fputs ("- Bogus argument given to ACKS\015\012",stdout);
+ return DONE;
+ }
+ /* mark message as seen */
+ sprintf (tmp,"%lu",msg[current++]);
+ mail_setflag (stream,tmp,"\\Seen");
+ return c_read (NIL); /* end message reading transaction */
+}
+
+
+/* Parse ACKD command
+ * Accepts: pointer to command argument
+ * Returns: new state
+ */
+
+short c_ackd (char *t)
+{
+ char tmp[TMPLEN];
+ if (t) { /* disallow argument */
+ fputs ("- Bogus argument given to ACKD\015\012",stdout);
+ return DONE;
+ }
+ /* mark message as seen and deleted */
+ sprintf (tmp,"%lu",msg[current]);
+ mail_setflag (stream,tmp,"\\Seen \\Deleted");
+ msg[current++] = 0; /* mark message as deleted */
+ return c_read (NIL); /* end message reading transaction */
+}
+
+
+/* Parse NACK command
+ * Accepts: pointer to command argument
+ * Returns: new state
+ */
+
+short c_nack (char *t)
+{
+ if (t) { /* disallow argument */
+ fputs ("- Bogus argument given to NACK\015\012",stdout);
+ return DONE;
+ }
+ return c_read (NIL); /* end message reading transaction */
+}
+
+/* Co-routines from MAIL library */
+
+
+/* Message matches a search
+ * Accepts: MAIL stream
+ * message number
+ */
+
+void mm_searched (MAILSTREAM *stream,unsigned long msgno)
+{
+ /* Never called */
+}
+
+
+/* Message exists (i.e. there are that many messages in the mailbox)
+ * Accepts: MAIL stream
+ * message number
+ */
+
+void mm_exists (MAILSTREAM *stream,unsigned long number)
+{
+ /* Can't use this mechanism. POP has no means of notifying the client of
+ new mail during the session. */
+}
+
+
+/* Message expunged
+ * Accepts: MAIL stream
+ * message number
+ */
+
+void mm_expunged (MAILSTREAM *stream,unsigned long number)
+{
+ if (state != DONE) { /* ignore if closing */
+ /* someone else screwed us */
+ goodbye = "- Mailbox expunged from under me!\015\012";
+ if (stream && !stream->lock) mail_close (stream);
+ stream = NIL;
+ sayonara (1);
+ }
+}
+
+
+/* Message status changed
+ * Accepts: MAIL stream
+ * message number
+ */
+
+void mm_flags (MAILSTREAM *stream,unsigned long number)
+{
+ /* This isn't used */
+}
+
+
+/* Mailbox found
+ * Accepts: MAIL stream
+ * hierarchy delimiter
+ * mailbox name
+ * mailbox attributes
+ */
+
+void mm_list (MAILSTREAM *stream,int delimiter,char *name,long attributes)
+{
+ /* This isn't used */
+}
+
+
+/* Subscribe mailbox found
+ * Accepts: MAIL stream
+ * hierarchy delimiter
+ * mailbox name
+ * mailbox attributes
+ */
+
+void mm_lsub (MAILSTREAM *stream,int delimiter,char *name,long attributes)
+{
+ /* This isn't used */
+}
+
+
+/* Mailbox status
+ * Accepts: MAIL stream
+ * mailbox name
+ * mailbox status
+ */
+
+void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status)
+{
+ /* This isn't used */
+}
+
+/* Notification event
+ * Accepts: MAIL stream
+ * string to log
+ * error flag
+ */
+
+void mm_notify (MAILSTREAM *stream,char *string,long errflg)
+{
+ mm_log (string,errflg); /* just do mm_log action */
+}
+
+
+/* Log an event for the user to see
+ * Accepts: string to log
+ * error flag
+ */
+
+void mm_log (char *string,long errflg)
+{
+ switch (errflg) {
+ case NIL: /* information message */
+ case PARSE: /* parse glitch */
+ break; /* too many of these to log */
+ case WARN: /* warning */
+ syslog (LOG_DEBUG,"%s",string);
+ break;
+ case BYE: /* driver broke connection */
+ if (state != DONE) {
+ char tmp[MAILTMPLEN];
+ alarm (0); /* disable all interrupts */
+ server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
+ sprintf (logout = tmp,"Mailbox closed (%.80s)",string);
+ sayonara (1);
+ }
+ break;
+ case ERROR: /* error that broke command */
+ default: /* default should never happen */
+ syslog (LOG_NOTICE,"%s",string);
+ break;
+ }
+}
+
+
+/* Log an event to debugging telemetry
+ * Accepts: string to log
+ */
+
+void mm_dlog (char *string)
+{
+ /* Not doing anything here for now */
+}
+
+
+/* Get user name and password for this host
+ * Accepts: parse of network mailbox name
+ * where to return user name
+ * where to return password
+ * trial count
+ */
+
+void mm_login (NETMBX *mb,char *username,char *password,long trial)
+{
+ /* set user name */
+ strncpy (username,*mb->user ? mb->user : user,NETMAXUSER-1);
+ strncpy (password,pass,255); /* and password */
+ username[NETMAXUSER] = password[255] = '\0';
+}
+
+/* About to enter critical code
+ * Accepts: stream
+ */
+
+void mm_critical (MAILSTREAM *stream)
+{
+ ++critical;
+}
+
+
+/* About to exit critical code
+ * Accepts: stream
+ */
+
+void mm_nocritical (MAILSTREAM *stream)
+{
+ --critical;
+}
+
+
+/* Disk error found
+ * Accepts: stream
+ * system error code
+ * flag indicating that mailbox may be clobbered
+ * Returns: abort flag
+ */
+
+long mm_diskerror (MAILSTREAM *stream,long errcode,long serious)
+{
+ if (serious) { /* try your damnest if clobberage likely */
+ syslog (LOG_ALERT,
+ "Retrying after disk error user=%.80s host=%.80s mbx=%.80s: %.80s",
+ user,tcp_clienthost (),
+ (stream && stream->mailbox) ? stream->mailbox : "???",
+ strerror (errcode));
+ alarm (0); /* make damn sure timeout disabled */
+ sleep (60); /* give it some time to clear up */
+ return NIL;
+ }
+ syslog (LOG_ALERT,"Fatal disk error user=%.80s host=%.80s mbx=%.80s: %.80s",
+ user,tcp_clienthost (),
+ (stream && stream->mailbox) ? stream->mailbox : "???",
+ strerror (errcode));
+ return T;
+}
+
+
+/* Log a fatal error event
+ * Accepts: string to log
+ */
+
+void mm_fatal (char *string)
+{
+ mm_log (string,ERROR); /* shouldn't happen normally */
+}
diff --git a/imap/src/ipopd/ipop3d.c b/imap/src/ipopd/ipop3d.c
new file mode 100644
index 00000000..41dd96a6
--- /dev/null
+++ b/imap/src/ipopd/ipop3d.c
@@ -0,0 +1,1082 @@
+/* ========================================================================
+ * Copyright 1988-2008 University of Washington
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *
+ * ========================================================================
+ */
+
+/*
+ * Program: IPOP3D - IMAP to POP3 conversion server
+ *
+ * Author: Mark Crispin
+ * UW Technology
+ * University of Washington
+ * Seattle, WA 98195
+ * Internet: MRC@Washington.EDU
+ *
+ * Date: 1 November 1990
+ * Last Edited: 19 February 2008
+ */
+
+/* Parameter files */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+extern int errno; /* just in case */
+#include <signal.h>
+#include <time.h>
+#include "c-client.h"
+
+
+#define CRLF PSOUT ("\015\012") /* primary output terpri */
+
+
+/* Autologout timer */
+#define KODTIMEOUT 60*5
+#define LOGINTIMEOUT 60*3
+#define TIMEOUT 60*10
+
+
+/* Server states */
+
+#define AUTHORIZATION 0
+#define TRANSACTION 1
+#define UPDATE 2
+#define LOGOUT 3
+
+/* Eudora food */
+
+#define STATUS "Status: %s%s\015\012"
+#define SLEN (sizeof (STATUS)-3)
+
+
+/* Global storage */
+
+char *version = "104"; /* edit number of this server */
+short state = AUTHORIZATION; /* server state */
+short critical = NIL; /* non-zero if in critical code */
+MAILSTREAM *stream = NIL; /* mailbox stream */
+time_t idletime = 0; /* time we went idle */
+unsigned long nmsgs = 0; /* current number of messages */
+unsigned long ndele = 0; /* number of deletes */
+unsigned long nseen = 0; /* number of mark-seens */
+unsigned long last = 0; /* highest message accessed */
+unsigned long il = 0; /* initial last message */
+char challenge[128]; /* challenge */
+char *host = NIL; /* remote host name */
+char *user = NIL; /* user name */
+char *pass = NIL; /* password */
+char *initial = NIL; /* initial response */
+long *msg = NIL; /* message translation vector */
+short *flags = NIL; /* flags */
+char *logout = "Logout";
+char *goodbye = "+OK Sayonara\015\012";
+
+
+/* POP3 flags */
+
+#define DELE 0x1
+#define SEEN 0x2
+
+
+/* Function prototypes */
+
+int main (int argc,char *argv[]);
+void sayonara (int status);
+void clkint ();
+void kodint ();
+void hupint ();
+void trmint ();
+int pass_login (char *t,int argc,char *argv[]);
+char *apop_login (char *chal,char *user,char *md5,int argc,char *argv[]);
+char *responder (void *challenge,unsigned long clen,unsigned long *rlen);
+int mbxopen (char *mailbox);
+long blat (char *text,long lines,unsigned long size,STRING *st);
+void rset ();
+
+/* Main program */
+
+int main (int argc,char *argv[])
+{
+ unsigned long i,j,k;
+ char *s,*t;
+ char tmp[MAILTMPLEN];
+ time_t autologouttime;
+ char *pgmname = (argc && argv[0]) ?
+ (((s = strrchr (argv[0],'/')) || (s = strrchr (argv[0],'\\'))) ?
+ s+1 : argv[0]) : "ipop3d";
+ /* set service name before linkage */
+ mail_parameters (NIL,SET_SERVICENAME,(void *) "pop");
+#include "linkage.c"
+ /* initialize server */
+ server_init (pgmname,"pop3","pop3s",clkint,kodint,hupint,trmint,NIL);
+ mail_parameters (NIL,SET_BLOCKENVINIT,VOIDT);
+ s = myusername_full (&i); /* get user name and flags */
+ mail_parameters (NIL,SET_BLOCKENVINIT,NIL);
+ if (i == MU_LOGGEDIN) { /* allow EXTERNAL if logged in already */
+ mail_parameters (NIL,UNHIDE_AUTHENTICATOR,(void *) "EXTERNAL");
+ mail_parameters (NIL,SET_EXTERNALAUTHID,(void *) s);
+ }
+ { /* set up MD5 challenge */
+ AUTHENTICATOR *auth = mail_lookup_auth (1);
+ while (auth && compare_cstring (auth->name,"CRAM-MD5")) auth = auth->next;
+ /* build challenge -- less than 128 chars */
+ if (auth && auth->server && !(auth->flags & AU_DISABLE))
+ sprintf (challenge,"<%lx.%lx@%.64s>",(unsigned long) getpid (),
+ (unsigned long) time (0),tcp_serverhost ());
+ else challenge[0] = '\0'; /* no MD5 authentication */
+ }
+ /* There are reports of POP3 clients which get upset if anything appears
+ * between the "+OK" and the "POP3" in the greeting.
+ */
+ PSOUT ("+OK POP3 ");
+ if (!challenge[0]) { /* if no MD5 enable, output host name */
+ PSOUT (tcp_serverhost ());
+ PBOUT (' ');
+ }
+ PSOUT (CCLIENTVERSION);
+ PBOUT ('.');
+ PSOUT (version);
+ PSOUT (" server ready");
+ if (challenge[0]) { /* if MD5 enable, output challenge here */
+ PBOUT (' ');
+ PSOUT (challenge);
+ }
+ CRLF;
+ PFLUSH (); /* dump output buffer */
+ autologouttime = time (0) + LOGINTIMEOUT;
+ /* command processing loop */
+ while ((state != UPDATE) && (state != LOGOUT)) {
+ idletime = time (0); /* get a command under timeout */
+ alarm ((state == TRANSACTION) ? TIMEOUT : LOGINTIMEOUT);
+ clearerr (stdin); /* clear stdin errors */
+ /* read command line */
+ while (!PSIN (tmp,MAILTMPLEN)) {
+ /* ignore if some interrupt */
+ if (ferror (stdin) && (errno == EINTR)) clearerr (stdin);
+ else {
+ char *e = ferror (stdin) ?
+ strerror (errno) : "Unexpected client disconnect";
+ alarm (0); /* disable all interrupts */
+ server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
+ sprintf (logout = tmp,"%.80s, while reading line",e);
+ goodbye = NIL;
+ rset (); /* try to gracefully close the stream */
+ if (state == TRANSACTION) mail_close (stream);
+ stream = NIL;
+ state = LOGOUT;
+ sayonara (1);
+ }
+ }
+ alarm (0); /* make sure timeout disabled */
+ idletime = 0; /* no longer idle */
+
+ if (!strchr (tmp,'\012')) /* find end of line */
+ PSOUT ("-ERR Command line too long\015\012");
+ else if (!(s = strtok (tmp," \015\012")))
+ PSOUT ("-ERR Null command\015\012");
+ else { /* dispatch based on command */
+ ucase (s); /* canonicalize case */
+ /* snarf argument */
+ t = strtok (NIL,"\015\012");
+ /* QUIT command always valid */
+ if (!strcmp (s,"QUIT")) state = UPDATE;
+ else if (!strcmp (s,"CAPA")) {
+ AUTHENTICATOR *auth;
+ PSOUT ("+OK Capability list follows:\015\012");
+ PSOUT ("TOP\015\012LOGIN-DELAY 180\015\012UIDL\015\012");
+ if (s = ssl_start_tls (NIL)) fs_give ((void **) &s);
+ else PSOUT ("STLS\015\012");
+ if (i = !mail_parameters (NIL,GET_DISABLEPLAINTEXT,NIL))
+ PSOUT ("USER\015\012");
+ /* display secure server authenticators */
+ for (auth = mail_lookup_auth (1), s = "SASL"; auth; auth = auth->next)
+ if (auth->server && !(auth->flags & AU_DISABLE) &&
+ !(auth->flags & AU_HIDE) && (i || (auth->flags & AU_SECURE))) {
+ if (s) {
+ PSOUT (s);
+ s = NIL;
+ }
+ PBOUT (' ');
+ PSOUT (auth->name);
+ }
+ PSOUT (s ? ".\015\012" : "\015\012.\015\012");
+ }
+
+ else switch (state) { /* else dispatch based on state */
+ case AUTHORIZATION: /* waiting to get logged in */
+ if (!strcmp (s,"AUTH")) {
+ if (t && *t) { /* mechanism given? */
+ if (host) fs_give ((void **) &host);
+ if (user) fs_give ((void **) &user);
+ if (pass) fs_give ((void **) &pass);
+ s = strtok (t," "); /* get mechanism name */
+ /* get initial response */
+ if (initial = strtok (NIL,"\015\012")) {
+ if ((*initial == '=') && !initial[1]) ++initial;
+ else if (!*initial) initial = NIL;
+ }
+ if (!(user = cpystr (mail_auth (s,responder,argc,argv)))) {
+ PSOUT ("-ERR Bad authentication\015\012");
+ syslog (LOG_INFO,"AUTHENTICATE %s failure host=%.80s",s,
+ tcp_clienthost ());
+ }
+ else if ((state = mbxopen ("INBOX")) == TRANSACTION)
+ syslog (LOG_INFO,"Auth user=%.80s host=%.80s nmsgs=%lu/%lu",
+ user,tcp_clienthost (),nmsgs,stream->nmsgs);
+ else syslog (LOG_INFO,"Auth user=%.80s host=%.80s no mailbox",
+ user,tcp_clienthost ());
+ }
+ else {
+ AUTHENTICATOR *auth;
+ PSOUT ("+OK Supported authentication mechanisms:\015\012");
+ i = !mail_parameters (NIL,GET_DISABLEPLAINTEXT,NIL);
+ for (auth = mail_lookup_auth (1); auth; auth = auth->next)
+ if (auth->server && !(auth->flags & AU_DISABLE) &&
+ !(auth->flags & AU_HIDE) &&
+ (i || (auth->flags & AU_SECURE))) {
+ PSOUT (auth->name);
+ CRLF;
+ }
+ PBOUT ('.');
+ CRLF;
+ }
+ }
+
+ else if (!strcmp (s,"APOP")) {
+ if (challenge[0]) { /* can do it if have an MD5 challenge */
+ if (host) fs_give ((void **) &host);
+ if (user) fs_give ((void **) &user);
+ if (pass) fs_give ((void **) &pass);
+ /* get user name */
+ if (!(t && *t && (s = strtok (t," ")) && (t = strtok(NIL,"\012"))))
+ PSOUT ("-ERR Missing APOP argument\015\012");
+ else if (!(user = apop_login (challenge,s,t,argc,argv)))
+ PSOUT ("-ERR Bad APOP\015\012");
+ else if ((state = mbxopen ("INBOX")) == TRANSACTION)
+ syslog (LOG_INFO,"APOP user=%.80s host=%.80s nmsgs=%lu/%lu",
+ user,tcp_clienthost (),nmsgs,stream->nmsgs);
+ else syslog (LOG_INFO,"APOP user=%.80s host=%.80s no mailbox",
+ user,tcp_clienthost ());
+ }
+ else PSOUT ("-ERR Not supported\015\012");
+ }
+ /* (chuckle) */
+ else if (!strcmp (s,"RPOP"))
+ PSOUT ("-ERR Nice try, bunkie\015\012");
+ else if (!strcmp (s,"STLS")) {
+ if (t = ssl_start_tls (pgmname)) {
+ PSOUT ("-ERR STLS failed: ");
+ PSOUT (t);
+ CRLF;
+ }
+ else PSOUT ("+OK STLS completed\015\012");
+ }
+ else if (!mail_parameters (NIL,GET_DISABLEPLAINTEXT,NIL) &&
+ !strcmp (s,"USER")) {
+ if (host) fs_give ((void **) &host);
+ if (user) fs_give ((void **) &user);
+ if (pass) fs_give ((void **) &pass);
+ if (t && *t) { /* if user name given */
+ /* skip leading whitespace (bogus clients!) */
+ while (*t == ' ') ++t;
+ /* remote user name? */
+ if (s = strchr (t,':')) {
+ *s++ = '\0'; /* tie off host name */
+ host = cpystr (t);/* copy host name */
+ user = cpystr (s);/* copy user name */
+ }
+ /* local user name */
+ else user = cpystr (t);
+ PSOUT ("+OK User name accepted, password please\015\012");
+ }
+ else PSOUT ("-ERR Missing username argument\015\012");
+ }
+ else if (!mail_parameters (NIL,GET_DISABLEPLAINTEXT,NIL) &&
+ user && *user && !strcmp (s,"PASS"))
+ state = pass_login (t,argc,argv);
+ else PSOUT ("-ERR Unknown AUTHORIZATION state command\015\012");
+ break;
+
+ case TRANSACTION: /* logged in */
+ if (!strcmp (s,"STAT")) {
+ for (i = 1,j = 0,k = 0; i <= nmsgs; i++)
+ /* message still exists? */
+ if (msg[i] && !(flags[i] & DELE)) {
+ j++; /* count one more undeleted message */
+ k += mail_elt (stream,msg[i])->rfc822_size + SLEN;
+ }
+ sprintf (tmp,"+OK %lu %lu\015\012",j,k);
+ PSOUT (tmp);
+ }
+ else if (!strcmp (s,"LIST")) {
+ if (t && *t) { /* argument do single message */
+ if ((i = strtoul (t,NIL,10)) && (i <= nmsgs) && msg[i] &&
+ !(flags[i] & DELE)) {
+ sprintf (tmp,"+OK %lu %lu\015\012",i,
+ mail_elt(stream,msg[i])->rfc822_size + SLEN);
+ PSOUT (tmp);
+ }
+ else PSOUT ("-ERR No such message\015\012");
+ }
+ else { /* entire mailbox */
+ PSOUT ("+OK Mailbox scan listing follows\015\012");
+ for (i = 1,j = 0,k = 0; i <= nmsgs; i++)
+ if (msg[i] && !(flags[i] & DELE)) {
+ sprintf (tmp,"%lu %lu\015\012",i,
+ mail_elt (stream,msg[i])->rfc822_size + SLEN);
+ PSOUT (tmp);
+ }
+ PBOUT ('.'); /* end of list */
+ CRLF;
+ }
+ }
+ else if (!strcmp (s,"UIDL")) {
+ if (t && *t) { /* argument do single message */
+ if ((i = strtoul (t,NIL,10)) && (i <= nmsgs) && msg[i] &&
+ !(flags[i] & DELE)) {
+ sprintf (tmp,"+OK %lu %08lx%08lx\015\012",i,stream->uid_validity,
+ mail_uid (stream,msg[i]));
+ PSOUT (tmp);
+ }
+ else PSOUT ("-ERR No such message\015\012");
+ }
+ else { /* entire mailbox */
+ PSOUT ("+OK Unique-ID listing follows\015\012");
+ for (i = 1,j = 0,k = 0; i <= nmsgs; i++)
+ if (msg[i] && !(flags[i] & DELE)) {
+ sprintf (tmp,"%lu %08lx%08lx\015\012",i,stream->uid_validity,
+ mail_uid (stream,msg[i]));
+ PSOUT (tmp);
+ }
+ PBOUT ('.'); /* end of list */
+ CRLF;
+ }
+ }
+
+ else if (!strcmp (s,"RETR")) {
+ if (t && *t) { /* must have an argument */
+ if ((i = strtoul (t,NIL,10)) && (i <= nmsgs) && msg[i] &&
+ !(flags[i] & DELE)) {
+ MESSAGECACHE *elt;
+ /* update highest message accessed */
+ if (i > last) last = i;
+ sprintf (tmp,"+OK %lu octets\015\012",
+ (elt = mail_elt (stream,msg[i]))->rfc822_size + SLEN);
+ PSOUT (tmp);
+ /* if not marked seen or noted to be marked */
+ if (!(elt->seen || (flags[i] & SEEN))) {
+ ++nseen; /* note that we need to mark it seen */
+ flags[i] |= SEEN;
+ }
+ /* get header */
+ t = mail_fetch_header (stream,msg[i],NIL,NIL,&k,FT_PEEK);
+ blat (t,-1,k,NIL);/* write up to trailing CRLF */
+ /* build status */
+ sprintf (tmp,STATUS,elt->seen ? "R" : " ",
+ elt->recent ? " " : "O");
+ if (k < 4) CRLF; /* don't write Status: if no header */
+ /* normal header ending with CRLF CRLF? */
+ else if (t[k-3] == '\012') {
+ PSOUT (tmp); /* write status */
+ CRLF; /* then write second CRLF */
+ }
+ else { /* abnormal - no blank line at end of header */
+ CRLF; /* write CRLF first then */
+ PSOUT (tmp);
+ }
+ /* output text */
+ t = mail_fetch_text (stream,msg[i],NIL,&k,
+ FT_RETURNSTRINGSTRUCT | FT_PEEK);
+ if (k) { /* only if there is a text body */
+ blat (t,-1,k,&stream->private.string);
+ CRLF; /* end of list */
+ }
+ PBOUT ('.');
+ CRLF;
+ }
+ else PSOUT ("-ERR No such message\015\012");
+ }
+ else PSOUT ("-ERR Missing message number argument\015\012");
+ }
+
+ else if (!strcmp (s,"DELE")) {
+ if (t && *t) { /* must have an argument */
+ if ((i = strtoul (t,NIL,10)) && (i <= nmsgs) && msg[i] &&
+ !(flags[i] & DELE)) {
+ /* update highest message accessed */
+ if (i > last) last = i;
+ flags[i] |= DELE; /* note that deletion is requested */
+ PSOUT ("+OK Message deleted\015\012");
+ ++ndele; /* one more message deleted */
+ }
+ else PSOUT ("-ERR No such message\015\012");
+ }
+ else PSOUT ("-ERR Missing message number argument\015\012");
+ }
+ else if (!strcmp (s,"NOOP"))
+ PSOUT ("+OK No-op to you too!\015\012");
+ else if (!strcmp (s,"LAST")) {
+ sprintf (tmp,"+OK %lu\015\012",last);
+ PSOUT (tmp);
+ }
+ else if (!strcmp (s,"RSET")) {
+ rset (); /* reset the mailbox */
+ PSOUT ("+OK Reset state\015\012");
+ }
+
+ else if (!strcmp (s,"TOP")) {
+ if (t && *t && (i =strtoul (t,&s,10)) && (i <= nmsgs) && msg[i] &&
+ !(flags[i] & DELE)) {
+ /* skip whitespace */
+ while (*s == ' ') s++;
+ /* make sure line count argument good */
+ if ((*s >= '0') && (*s <= '9')) {
+ MESSAGECACHE *elt = mail_elt (stream,msg[i]);
+ j = strtoul (s,NIL,10);
+ /* update highest message accessed */
+ if (i > last) last = i;
+ PSOUT ("+OK Top of message follows\015\012");
+ /* get header */
+ t = mail_fetch_header (stream,msg[i],NIL,NIL,&k,FT_PEEK);
+ blat (t,-1,k,NIL);/* write up to trailing CRLF */
+ /* build status */
+ sprintf (tmp,STATUS,elt->seen ? "R" : " ",
+ elt->recent ? " " : "O");
+ if (k < 4) CRLF; /* don't write Status: if no header */
+ /* normal header ending with CRLF CRLF? */
+ else if (t[k-3] == '\012') {
+ PSOUT (tmp); /* write status */
+ CRLF; /* then write second CRLF */
+ }
+ else { /* abnormal - no blank line at end of header */
+ CRLF; /* write CRLF first then */
+ PSOUT (tmp);
+ }
+ if (j) { /* want any text lines? */
+ /* output text */
+ t = mail_fetch_text (stream,msg[i],NIL,&k,
+ FT_PEEK | FT_RETURNSTRINGSTRUCT);
+ /* tie off final line if full text output */
+ if (k && (j -= blat (t,j,k,&stream->private.string))) CRLF;
+ }
+ PBOUT ('.'); /* end of list */
+ CRLF;
+ }
+ else PSOUT ("-ERR Bad line count argument\015\012");
+ }
+ else PSOUT ("-ERR Bad message number argument\015\012");
+ }
+
+ else if (!strcmp (s,"XTND"))
+ PSOUT ("-ERR Sorry I can't do that\015\012");
+ else PSOUT ("-ERR Unknown TRANSACTION state command\015\012");
+ break;
+ default:
+ PSOUT ("-ERR Server in unknown state\015\012");
+ break;
+ }
+ }
+ PFLUSH (); /* make sure output finished */
+ if (autologouttime) { /* have an autologout in effect? */
+ /* cancel if no longer waiting for login */
+ if (state != AUTHORIZATION) autologouttime = 0;
+ /* took too long to login */
+ else if (autologouttime < time (0)) {
+ goodbye = "-ERR Autologout\015\012";
+ logout = "Autologout";
+ state = LOGOUT; /* sayonara */
+ }
+ }
+ }
+
+ /* open and need to update? */
+ if (stream && (state == UPDATE)) {
+ if (nseen) { /* only bother if messages need marking seen */
+ *(s = tmp) = '\0'; /* clear sequence */
+ for (i = 1; i <= nmsgs; ++i) if (flags[i] & SEEN) {
+ for (j = i + 1, k = 0; (j <= nmsgs) && (flags[j] & SEEN); ++j) k = j;
+ if (k) sprintf (s,",%lu:%lu",i,k);
+ else sprintf (s,",%lu",i);
+ s += strlen (s); /* point to end of string */
+ if ((s - tmp) > (MAILTMPLEN - 30)) {
+ mail_setflag (stream,tmp + 1,"\\Seen");
+ *(s = tmp) = '\0'; /* restart sequence */
+ }
+ i = j; /* continue after the range */
+ }
+ if (tmp[0]) mail_setflag (stream,tmp + 1,"\\Seen");
+ }
+ if (ndele) { /* any messages to delete? */
+ *(s = tmp) = '\0'; /* clear sequence */
+ for (i = 1; i <= nmsgs; ++i) if (flags[i] & DELE) {
+ for (j = i + 1, k = 0; (j <= nmsgs) && (flags[j] & DELE); ++j) k = j;
+ if (k) sprintf (s,",%lu:%lu",i,k);
+ else sprintf (s,",%lu",i);
+ s += strlen (s); /* point to end of string */
+ if ((s - tmp) > (MAILTMPLEN - 30)) {
+ mail_setflag (stream,tmp + 1,"\\Deleted");
+ *(s = tmp) = '\0'; /* restart sequence */
+ }
+ i = j; /* continue after the range */
+ }
+ if (tmp[0]) mail_setflag (stream,tmp + 1,"\\Deleted");
+ mail_expunge (stream);
+ }
+ syslog (LOG_INFO,"Update user=%.80s host=%.80s nmsgs=%lu ndele=%lu nseen=%lu",
+ user,tcp_clienthost (),stream->nmsgs,ndele,nseen);
+ mail_close (stream);
+ }
+ sayonara (0);
+ return 0; /* stupid compilers */
+}
+
+
+/* Say goodbye
+ * Accepts: exit status
+ *
+ * Does not return
+ */
+
+void sayonara (int status)
+{
+ logouthook_t lgoh = (logouthook_t) mail_parameters (NIL,GET_LOGOUTHOOK,NIL);
+ if (goodbye) { /* have a goodbye message? */
+ PSOUT (goodbye);
+ PFLUSH (); /* make sure blatted */
+ }
+ syslog (LOG_INFO,"%s user=%.80s host=%.80s",logout,
+ user ? (char *) user : "???",tcp_clienthost ());
+ /* do logout hook if needed */
+ if (lgoh) (*lgoh) (mail_parameters (NIL,GET_LOGOUTDATA,NIL));
+ _exit (status); /* all done */
+}
+
+/* Clock interrupt
+ */
+
+void clkint ()
+{
+ alarm (0); /* disable all interrupts */
+ server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
+ goodbye = "-ERR Autologout; idle for too long\015\012";
+ logout = "Autologout";
+ if (critical) state = LOGOUT; /* badly hosed if in critical code */
+ else { /* try to gracefully close the stream */
+ if ((state == TRANSACTION) && !stream->lock) {
+ rset ();
+ mail_close (stream);
+ }
+ state = LOGOUT;
+ stream = NIL;
+ sayonara (1);
+ }
+}
+
+
+/* Kiss Of Death interrupt
+ */
+
+void kodint ()
+{
+ /* only if idle */
+ if (idletime && ((time (0) - idletime) > KODTIMEOUT)) {
+ alarm (0); /* disable all interrupts */
+ server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
+ goodbye = "-ERR Received Kiss of Death\015\012";
+ logout = "Killed (lost mailbox lock)";
+ if (critical) state =LOGOUT;/* must defer if in critical code */
+ else { /* try to gracefully close the stream */
+ if ((state == TRANSACTION) && !stream->lock) {
+ rset ();
+ mail_close (stream);
+ }
+ state = LOGOUT;
+ stream = NIL;
+ sayonara (1); /* die die die */
+ }
+ }
+}
+
+
+/* Hangup interrupt
+ */
+
+void hupint ()
+{
+ alarm (0); /* disable all interrupts */
+ server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
+ goodbye = NIL; /* nobody left to talk to */
+ logout = "Hangup";
+ if (critical) state = LOGOUT; /* must defer if in critical code */
+ else { /* try to gracefully close the stream */
+ if ((state == TRANSACTION) && !stream->lock) {
+ rset ();
+ mail_close (stream);
+ }
+ state = LOGOUT;
+ stream = NIL;
+ sayonara (1); /* die die die */
+ }
+}
+
+
+/* Termination interrupt
+ */
+
+void trmint ()
+{
+ alarm (0); /* disable all interrupts */
+ server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
+ goodbye = "-ERR Killed\015\012";
+ logout = "Killed";
+ if (critical) state = LOGOUT; /* must defer if in critical code */
+ /* Make no attempt at graceful closure since a shutdown may be in
+ * progress, and we won't have any time to do mail_close() actions.
+ */
+ else sayonara (1); /* die die die */
+}
+
+/* Parse PASS command
+ * Accepts: pointer to command argument
+ * Returns: new state
+ */
+
+int pass_login (char *t,int argc,char *argv[])
+{
+ char tmp[MAILTMPLEN];
+ /* flush old passowrd */
+ if (pass) fs_give ((void **) &pass);
+ if (!(t && *t)) { /* if no password given */
+ PSOUT ("-ERR Missing password argument\015\012");
+ return AUTHORIZATION;
+ }
+ pass = cpystr (t); /* copy password argument */
+ if (!host) { /* want remote mailbox? */
+ /* no, delimit user from possible admin */
+ if (t = strchr (user,'*')) *t++ ='\0';
+ /* attempt the login */
+ if (server_login (user,pass,t,argc,argv)) {
+ int ret = mbxopen ("INBOX");
+ if (ret == TRANSACTION) /* mailbox opened OK? */
+ syslog (LOG_INFO,"%sLogin user=%.80s host=%.80s nmsgs=%lu/%lu",
+ t ? "Admin " : "",user,tcp_clienthost (),nmsgs,stream->nmsgs);
+ else syslog (LOG_INFO,"%sLogin user=%.80s host=%.80s no mailbox",
+ t ? "Admin " : "",user,tcp_clienthost ());
+ return ret;
+ }
+ }
+#ifndef DISABLE_POP_PROXY
+ /* remote; build remote INBOX */
+ else if (anonymous_login (argc,argv)) {
+ syslog (LOG_INFO,"IMAP login to host=%.80s user=%.80s host=%.80s",host,
+ user,tcp_clienthost ());
+ sprintf (tmp,"{%.128s/user=%.128s}INBOX",host,user);
+ /* disable rimap just in case */
+ mail_parameters (NIL,SET_RSHTIMEOUT,0);
+ return mbxopen (tmp);
+ }
+#endif
+ /* vague error message to confuse crackers */
+ PSOUT ("-ERR Bad login\015\012");
+ return AUTHORIZATION;
+}
+
+/* Authentication responder
+ * Accepts: challenge
+ * length of challenge
+ * pointer to response length return location if non-NIL
+ * Returns: response
+ */
+
+#define RESPBUFLEN 8*MAILTMPLEN
+
+char *responder (void *challenge,unsigned long clen,unsigned long *rlen)
+{
+ unsigned long i,j;
+ unsigned char *t,resp[RESPBUFLEN];
+ char tmp[MAILTMPLEN];
+ if (initial) { /* initial response given? */
+ if (clen) return NIL; /* not permitted */
+ /* set up response */
+ t = (unsigned char *) initial;
+ initial = NIL; /* no more initial response */
+ return (char *) rfc822_base64 (t,strlen ((char *) t),rlen ? rlen : &i);
+ }
+ PSOUT ("+ ");
+ for (t = rfc822_binary (challenge,clen,&i),j = 0; j < i; j++)
+ if (t[j] > ' ') PBOUT (t[j]);
+ fs_give ((void **) &t);
+ CRLF;
+ PFLUSH (); /* dump output buffer */
+ resp[RESPBUFLEN-1] = '\0'; /* last buffer character is guaranteed NUL */
+ alarm (LOGINTIMEOUT); /* get a response under timeout */
+ clearerr (stdin); /* clear stdin errors */
+ /* read buffer */
+ while (!PSIN ((char *) resp,RESPBUFLEN)) {
+ /* ignore if some interrupt */
+ if (ferror (stdin) && (errno == EINTR)) clearerr (stdin);
+ else {
+ char *e = ferror (stdin) ?
+ strerror (errno) : "Command stream end of file";
+ alarm (0); /* disable all interrupts */
+ server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
+ sprintf (logout = tmp,"%.80s, while reading authentication",e);
+ goodbye = NIL;
+ state = LOGOUT;
+ sayonara (1);
+ }
+ }
+ if (!(t = (unsigned char *) strchr ((char *) resp,'\012'))) {
+ int c;
+ while ((c = PBIN ()) != '\012') if (c == EOF) {
+ /* ignore if some interrupt */
+ if (ferror (stdin) && (errno == EINTR)) clearerr (stdin);
+ else {
+ char *e = ferror (stdin) ?
+ strerror (errno) : "Command stream end of file";
+ alarm (0); /* disable all interrupts */
+ server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
+ sprintf (logout = tmp,"%.80s, while reading auth char",e);
+ goodbye = NIL;
+ state = LOGOUT;
+ sayonara (1);
+ }
+ }
+ return NIL;
+ }
+ alarm (0); /* make sure timeout disabled */
+ if (t[-1] == '\015') --t; /* remove CR */
+ *t = '\0'; /* tie off buffer */
+ return (resp[0] != '*') ?
+ (char *) rfc822_base64 (resp,t-resp,rlen ? rlen : &i) : NIL;
+}
+
+/* Select mailbox
+ * Accepts: mailbox name
+ * Returns: new state
+ */
+
+int mbxopen (char *mailbox)
+{
+ unsigned long i,j;
+ char tmp[MAILTMPLEN];
+ MESSAGECACHE *elt;
+ if (msg) fs_give ((void **) &msg);
+ /* open mailbox */
+ if (!(stream = mail_open (stream,mailbox,NIL)))
+ goodbye = "-ERR Unable to open user's INBOX\015\012";
+ else if (stream->rdonly) /* make sure not readonly */
+ goodbye = "-ERR Can't get lock. Mailbox in use\015\012";
+ else {
+ nmsgs = 0; /* no messages yet */
+ if (j = stream->nmsgs) { /* if mailbox non-empty */
+ sprintf (tmp,"1:%lu",j); /* fetch fast information for all messages */
+ mail_fetch_fast (stream,tmp,NIL);
+ }
+ /* create 1-origin tables */
+ msg = (long *) fs_get (++j * sizeof (long));
+ flags = (short *) fs_get (j * sizeof (short));
+ /* build map */
+ for (i = 1; i < j; ++i) if (!(elt = mail_elt (stream,i))->deleted) {
+ msg[++nmsgs] = i; /* note the presence of this message */
+ if (elt->seen) il = nmsgs;/* and set up initial LAST */
+ }
+ /* make sure unused map entries are zero */
+ for (i = nmsgs + 1; i < j; ++i) msg[i] = 0;
+ rset (); /* do implicit RSET */
+ sprintf (tmp,"+OK Mailbox open, %lu messages\015\012",nmsgs);
+ PSOUT (tmp);
+ return TRANSACTION;
+ }
+ syslog (LOG_INFO,"Error opening or locking INBOX user=%.80s host=%.80s",
+ user,tcp_clienthost ());
+ return UPDATE;
+}
+
+/* Blat a string with dot checking
+ * Accepts: string
+ * maximum number of lines if greater than zero
+ * maximum number of bytes to output
+ * alternative stringstruct
+ * Returns: number of lines output
+ *
+ * This routine is uglier and kludgier than it should be, just to be robust
+ * in the case of a message which doesn't end in a newline. Yes, this routine
+ * does truncate the last two bytes from the text. Since it is normally a
+ * newline and the main routine adds it back, it usually does not make a
+ * difference. But if it isn't, since the newline is required and the octet
+ * counts have to match, there's no choice but to truncate.
+ */
+
+long blat (char *text,long lines,unsigned long size,STRING *st)
+{
+ char c,d,e;
+ long ret = 0;
+ /* no-op if zero lines or empty string */
+ if (!(lines && (size-- > 2))) return 0;
+ if (text) {
+ c = *text++; d = *text++; /* collect first two bytes */
+ if (c == '.') PBOUT ('.'); /* double string-leading dot if necessary */
+ while (lines && --size) { /* copy loop */
+ e = *text++; /* get next byte */
+ PBOUT (c); /* output character */
+ if (c == '\012') { /* end of line? */
+ ret++; --lines; /* count another line */
+ /* double leading dot as necessary */
+ if (lines && size && (d == '.')) PBOUT ('.');
+ }
+ c = d; d = e; /* move to next character */
+ }
+ }
+ else {
+ c = SNX (st); d = SNX (st); /* collect first two bytes */
+ if (c == '.') PBOUT ('.'); /* double string-leading dot if necessary */
+ while (lines && --size) { /* copy loop */
+ e = SNX (st); /* get next byte */
+ PBOUT (c); /* output character */
+ if (c == '\012') { /* end of line? */
+ ret++; --lines; /* count another line */
+ /* double leading dot as necessary */
+ if (lines && size && (d == '.')) PBOUT ('.');
+ }
+ c = d; d = e; /* move to next character */
+ }
+ }
+ return ret;
+}
+
+/* Reset mailbox
+ */
+
+void rset ()
+{
+ /* clear all flags */
+ if (flags) memset ((void *) flags,0,(nmsgs + 1) * sizeof (short));
+ ndele = nseen = 0; /* no more deleted or seen messages */
+ last = il; /* restore previous LAST value */
+}
+
+/* Co-routines from MAIL library */
+
+
+/* Message matches a search
+ * Accepts: MAIL stream
+ * message number
+ */
+
+void mm_searched (MAILSTREAM *stream,unsigned long msgno)
+{
+ /* Never called */
+}
+
+
+/* Message exists (i.e. there are that many messages in the mailbox)
+ * Accepts: MAIL stream
+ * message number
+ */
+
+void mm_exists (MAILSTREAM *stream,unsigned long number)
+{
+ /* Can't use this mechanism. POP has no means of notifying the client of
+ new mail during the session. */
+}
+
+
+/* Message expunged
+ * Accepts: MAIL stream
+ * message number
+ */
+
+void mm_expunged (MAILSTREAM *stream,unsigned long number)
+{
+ unsigned long i = number + 1;
+ msg[number] = 0; /* I bet that this will annoy someone */
+ while (i <= nmsgs) --msg[i++];
+}
+
+
+/* Message flag status change
+ * Accepts: MAIL stream
+ * message number
+ */
+
+void mm_flags (MAILSTREAM *stream,unsigned long number)
+{
+ /* This isn't used */
+}
+
+
+/* Mailbox found
+ * Accepts: MAIL stream
+ * hierarchy delimiter
+ * mailbox name
+ * mailbox attributes
+ */
+
+void mm_list (MAILSTREAM *stream,int delimiter,char *name,long attributes)
+{
+ /* This isn't used */
+}
+
+
+/* Subscribe mailbox found
+ * Accepts: MAIL stream
+ * hierarchy delimiter
+ * mailbox name
+ * mailbox attributes
+ */
+
+void mm_lsub (MAILSTREAM *stream,int delimiter,char *name,long attributes)
+{
+ /* This isn't used */
+}
+
+
+/* Mailbox status
+ * Accepts: MAIL stream
+ * mailbox name
+ * mailbox status
+ */
+
+void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status)
+{
+ /* This isn't used */
+}
+
+/* Notification event
+ * Accepts: MAIL stream
+ * string to log
+ * error flag
+ */
+
+void mm_notify (MAILSTREAM *stream,char *string,long errflg)
+{
+ mm_log (string,errflg); /* just do mm_log action */
+}
+
+
+/* Log an event for the user to see
+ * Accepts: string to log
+ * error flag
+ */
+
+void mm_log (char *string,long errflg)
+{
+ switch (errflg) {
+ case NIL: /* information message */
+ case PARSE: /* parse glitch */
+ break; /* too many of these to log */
+ case WARN: /* warning */
+ syslog (LOG_DEBUG,"%s",string);
+ break;
+ case BYE: /* driver broke connection */
+ if (state != UPDATE) {
+ char tmp[MAILTMPLEN];
+ alarm (0); /* disable all interrupts */
+ server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
+ sprintf (logout = tmp,"Mailbox closed (%.80s)",string);
+ goodbye = NIL;
+ state = LOGOUT;
+ sayonara (1);
+ }
+ break;
+ case ERROR: /* error that broke command */
+ default: /* default should never happen */
+ syslog (LOG_NOTICE,"%s",string);
+ break;
+ }
+}
+
+
+/* Log an event to debugging telemetry
+ * Accepts: string to log
+ */
+
+void mm_dlog (char *string)
+{
+ /* Not doing anything here for now */
+}
+
+
+/* Get user name and password for this host
+ * Accepts: parse of network mailbox name
+ * where to return user name
+ * where to return password
+ * trial count
+ */
+
+void mm_login (NETMBX *mb,char *username,char *password,long trial)
+{
+ /* set user name */
+ strncpy (username,*mb->user ? mb->user : user,NETMAXUSER-1);
+ if (pass) {
+ strncpy (password,pass,255);/* and password */
+ fs_give ((void **) &pass);
+ }
+ else memset (password,0,256); /* no password to send, abort login */
+ username[NETMAXUSER] = password[255] = '\0';
+}
+
+/* About to enter critical code
+ * Accepts: stream
+ */
+
+void mm_critical (MAILSTREAM *stream)
+{
+ ++critical;
+}
+
+
+/* About to exit critical code
+ * Accepts: stream
+ */
+
+void mm_nocritical (MAILSTREAM *stream)
+{
+ --critical;
+}
+
+
+/* Disk error found
+ * Accepts: stream
+ * system error code
+ * flag indicating that mailbox may be clobbered
+ * Returns: abort flag
+ */
+
+long mm_diskerror (MAILSTREAM *stream,long errcode,long serious)
+{
+ if (serious) { /* try your damnest if clobberage likely */
+ syslog (LOG_ALERT,
+ "Retrying after disk error user=%.80s host=%.80s mbx=%.80s: %.80s",
+ user,tcp_clienthost (),
+ (stream && stream->mailbox) ? stream->mailbox : "???",
+ strerror (errcode));
+ alarm (0); /* make damn sure timeout disabled */
+ sleep (60); /* give it some time to clear up */
+ return NIL;
+ }
+ syslog (LOG_ALERT,"Fatal disk error user=%.80s host=%.80s mbx=%.80s: %.80s",
+ user,tcp_clienthost (),
+ (stream && stream->mailbox) ? stream->mailbox : "???",
+ strerror (errcode));
+ return T;
+}
+
+
+/* Log a fatal error event
+ * Accepts: string to log
+ */
+
+void mm_fatal (char *string)
+{
+ mm_log (string,ERROR); /* shouldn't happen normally */
+}
diff --git a/imap/src/ipopd/ipopd.8 b/imap/src/ipopd/ipopd.8
new file mode 100644
index 00000000..95a5b099
--- /dev/null
+++ b/imap/src/ipopd/ipopd.8
@@ -0,0 +1,75 @@
+.ig
+ * ========================================================================
+ * Copyright 1988-2006 University of Washington
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *
+ * ========================================================================
+..
+.TH IPOPD 8 "August 30, 2006"
+.UC 5
+.SH NAME
+IPOPd \- Post Office Protocol server
+.SH SYNOPSIS
+.B /usr/etc/ipop2d
+.PP
+.B /usr/etc/ipop3d
+.SH DESCRIPTION
+.I ipop2d
+and
+.I ipop3d
+are servers which support the
+.B POP2
+and
+.B POP3
+remote mail access protocols respectively.
+.I ipop2d
+and
+.I ipop3d
+can also be used by
+.B POP2
+and
+.B POP3
+clients respecitively to access mailboxes on
+.B IMAP
+servers by specifying a login user name in the form <host>:<user>
+e.g.,
+.B SERVER.WASHINGTON.EDU:SMITH.
+.PP
+These daemons contain CRAM-MD5 and APOP support. See the md5.txt
+documentation file for additional information.
+.PP
+.I ipop2d
+and
+.I ipop3d
+are invoked by the internet server (see
+.IR inetd (8)),
+normally for requests to connect to the
+.B POP
+port as indicated by the
+.I /etc/services
+file (see
+.IR services (5)).
+.SH "SEE ALSO"
+imapd(8)
+.SH BUGS
+The
+.B POP2
+and
+.B POP3
+protocols are intrinsically less flexible than
+.B IMAP
+and do not maintain `read' vs `unread' state on the server. As a result,
+most
+.B POP
+based software transfers all the mail from the server to the client and
+deletes it from the server. This necessarily locks the user into using only
+a single client.
+.PP
+.B POP3
+does not allow you to specify an alternate folder from the user's default.
diff --git a/imap/src/ipopd/makefile.nt b/imap/src/ipopd/makefile.nt
new file mode 100644
index 00000000..ef32819b
--- /dev/null
+++ b/imap/src/ipopd/makefile.nt
@@ -0,0 +1,57 @@
+# ========================================================================
+# Copyright 1988-2006 University of Washington
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+#
+# ========================================================================
+
+
+# Program: IPOPD Makefile for Windows 9x and Windows NT
+#
+# Author: Mark Crispin
+# Networks and Distributed Computing
+# Computing & Communications
+# University of Washington
+# Administration Building, AG-44
+# Seattle, WA 98195
+# Internet: MRC@CAC.Washington.EDU
+#
+# Date: 28 October 1990
+# Last Edited: 30 August 2006
+
+
+C = ..\c-client
+CCLIENTLIB = $C\cclient.lib
+LIBS = $(CCLIENTLIB) ws2_32.lib winmm.lib advapi32.lib
+OSCOMPAT = /DWIN32 /D_WIN32_WINNT=0x0400
+VSCOMPAT = /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE
+CFLAGS= -I$C /MT /W3 $(OSCOMPAT) $(VSCOMPAT) -nologo $(EXTRACFLAGS)
+
+
+ipopd: ipop2d ipop3d
+
+ipop2d: $(CCLIENTLIB) ipop2d.obj
+ LINK /NOLOGO ipop2d.obj $(LIBS)
+
+ipop3d: $(CCLIENTLIB) ipop3d.obj
+ LINK /NOLOGO ipop3d.obj $(LIBS)
+
+ipop2d.obj: $C\mail.h $C\misc.h $C\osdep.h
+
+ipop3d.obj: $C\mail.h $C\misc.h $C\osdep.h
+
+$(CCLIENTLIB):
+ @echo Make c-client first
+ false
+
+clean:
+ del *.obj *.exe *.lib *.exp || rem
+
+# A monument to a hack of long ago and far away...
+love:
+ @echo not war?
diff --git a/imap/src/ipopd/makefile.ntk b/imap/src/ipopd/makefile.ntk
new file mode 100644
index 00000000..4a90a7a0
--- /dev/null
+++ b/imap/src/ipopd/makefile.ntk
@@ -0,0 +1,58 @@
+# ========================================================================
+# Copyright 1988-2006 University of Washington
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+#
+# ========================================================================
+
+
+# Program: IPOPD Makefile for Windows 9x and Windows NT + Kerberos
+#
+# Author: Mark Crispin
+# Networks and Distributed Computing
+# Computing & Communications
+# University of Washington
+# Administration Building, AG-44
+# Seattle, WA 98195
+# Internet: MRC@CAC.Washington.EDU
+#
+# Date: 28 October 1990
+# Last Edited: 30 August 2006
+
+
+C = ..\c-client
+CCLIENTLIB = $C\cclient.lib
+K5 = \k5\lib
+K5LIB = $(K5)\comerr32.lib $(K5)\gssapi32.lib $(K5)\krb5_32.lib
+LIBS = $(CCLIENTLIB) $(K5LIB) ws2_32.lib winmm.lib advapi32.lib
+OSCOMPAT = /DWIN32 /D_WIN32_WINNT=0x0400
+VSCOMPAT = /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE
+CFLAGS= -I$C /MT /W3 $(OSCOMPAT) $(VSCOMPAT) -nologo $(EXTRACFLAGS)
+
+ipopd: ipop2d ipop3d
+
+ipop2d: $(CCLIENTLIB) ipop2d.obj
+ LINK /NOLOGO ipop2d.obj $(LIBS)
+
+ipop3d: $(CCLIENTLIB) ipop3d.obj
+ LINK /NOLOGO ipop3d.obj $(LIBS)
+
+ipop2d.obj: $C\mail.h $C\misc.h $C\osdep.h
+
+ipop3d.obj: $C\mail.h $C\misc.h $C\osdep.h
+
+$(CCLIENTLIB):
+ @echo Make c-client first
+ false
+
+clean:
+ del *.obj *.exe *.lib *.exp || rem
+
+# A monument to a hack of long ago and far away...
+love:
+ @echo not war?
diff --git a/imap/src/ipopd/makefile.w2k b/imap/src/ipopd/makefile.w2k
new file mode 100644
index 00000000..efa63c2f
--- /dev/null
+++ b/imap/src/ipopd/makefile.w2k
@@ -0,0 +1,56 @@
+# ========================================================================
+# Copyright 1988-2006 University of Washington
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+#
+# ========================================================================
+
+
+# Program: IPOPD Makefile for Windows 2000/XP
+#
+# Author: Mark Crispin
+# Networks and Distributed Computing
+# Computing & Communications
+# University of Washington
+# Administration Building, AG-44
+# Seattle, WA 98195
+# Internet: MRC@CAC.Washington.EDU
+#
+# Date: 28 October 1990
+# Last Edited: 30 August 2006
+
+
+C = ..\c-client
+CCLIENTLIB = $C\cclient.lib
+LIBS = $(CCLIENTLIB) ws2_32.lib winmm.lib advapi32.lib secur32.lib crypt32.lib
+OSCOMPAT = /DWIN32
+VSCOMPAT = /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE
+CFLAGS= -I$C /MT /W3 $(OSCOMPAT) $(VSCOMPAT) -nologo $(EXTRACFLAGS)
+
+ipopd: ipop2d ipop3d
+
+ipop2d: $(CCLIENTLIB) ipop2d.obj
+ LINK /NOLOGO ipop2d.obj $(LIBS)
+
+ipop3d: $(CCLIENTLIB) ipop3d.obj
+ LINK /NOLOGO ipop3d.obj $(LIBS)
+
+ipop2d.obj: $C\mail.h $C\misc.h $C\osdep.h
+
+ipop3d.obj: $C\mail.h $C\misc.h $C\osdep.h
+
+$(CCLIENTLIB):
+ @echo Make c-client first
+ false
+
+clean:
+ del *.obj *.exe *.lib *.exp || rem
+
+# A monument to a hack of long ago and far away...
+love:
+ @echo not war?