summaryrefslogtreecommitdiff
path: root/imap/src/osdep/wce
diff options
context:
space:
mode:
authorEduardo Chappa <echappa@gmx.com>2013-02-03 00:59:38 -0700
committerEduardo Chappa <echappa@gmx.com>2013-02-03 00:59:38 -0700
commit094ca96844842928810f14844413109fc6cdd890 (patch)
treee60efbb980f38ba9308ccb4fb2b77b87bbc115f3 /imap/src/osdep/wce
downloadalpine-094ca96844842928810f14844413109fc6cdd890.tar.xz
Initial Alpine Version
Diffstat (limited to 'imap/src/osdep/wce')
-rw-r--r--imap/src/osdep/wce/drivers.bat33
-rw-r--r--imap/src/osdep/wce/drivraux.bat30
-rw-r--r--imap/src/osdep/wce/dummy.h43
-rw-r--r--imap/src/osdep/wce/dummywce.c301
-rw-r--r--imap/src/osdep/wce/env_wce.c301
-rw-r--r--imap/src/osdep/wce/env_wce.h70
-rw-r--r--imap/src/osdep/wce/fs_wce.c62
-rw-r--r--imap/src/osdep/wce/ftl_wce.c38
-rw-r--r--imap/src/osdep/wce/makefile.wce96
-rw-r--r--imap/src/osdep/wce/mkautaux.bat31
-rw-r--r--imap/src/osdep/wce/mkauths.bat33
-rw-r--r--imap/src/osdep/wce/nl_wce.c61
-rw-r--r--imap/src/osdep/wce/os_wce.c45
-rw-r--r--imap/src/osdep/wce/os_wce.h53
-rw-r--r--imap/src/osdep/wce/pmatch.c89
-rw-r--r--imap/src/osdep/wce/setproto.bat29
-rw-r--r--imap/src/osdep/wce/tcp_wce.c818
-rw-r--r--imap/src/osdep/wce/tcp_wce.h46
18 files changed, 2179 insertions, 0 deletions
diff --git a/imap/src/osdep/wce/drivers.bat b/imap/src/osdep/wce/drivers.bat
new file mode 100644
index 00000000..0964f537
--- /dev/null
+++ b/imap/src/osdep/wce/drivers.bat
@@ -0,0 +1,33 @@
+@ECHO OFF
+REM ========================================================================
+REM Copyright 1988-2006 University of Washington
+REM
+REM Licensed under the Apache License, Version 2.0 (the "License");
+REM you may not use this file except in compliance with the License.
+REM You may obtain a copy of the License at
+REM
+REM http://www.apache.org/licenses/LICENSE-2.0
+REM
+REM
+REM ========================================================================
+
+REM Program: Driver Linkage Generator for DOS/NT
+REM
+REM Author: Mark Crispin
+REM Networks and Distributed Computing
+REM Computing & Communications
+REM University of Washington
+REM Administration Building, AG-44
+REM Seattle, WA 98195
+REM Internet: MRC@CAC.Washington.EDU
+REM
+REM Date: 11 October 1989
+REM Last Edited:30 August 2006
+
+REM Erase old driver linkage
+IF EXIST LINKAGE.* DEL LINKAGE.*
+
+REM Now define the new list
+FOR %%D IN (%1 %2 %3 %4 %5 %6 %7 %8 %9) DO CALL DRIVRAUX %%D
+
+EXIT 0
diff --git a/imap/src/osdep/wce/drivraux.bat b/imap/src/osdep/wce/drivraux.bat
new file mode 100644
index 00000000..30649a78
--- /dev/null
+++ b/imap/src/osdep/wce/drivraux.bat
@@ -0,0 +1,30 @@
+@ECHO OFF
+REM ========================================================================
+REM Copyright 1988-2006 University of Washington
+REM
+REM Licensed under the Apache License, Version 2.0 (the "License");
+REM you may not use this file except in compliance with the License.
+REM You may obtain a copy of the License at
+REM
+REM http://www.apache.org/licenses/LICENSE-2.0
+REM
+REM
+REM ========================================================================
+
+REM Program: Driver Linkage Generator auxillary for NT/Win9x
+REM
+REM Author: Mark Crispin
+REM Networks and Distributed Computing
+REM Computing & Communications
+REM University of Washington
+REM Administration Building, AG-44
+REM Seattle, WA 98195
+REM Internet: MRC@CAC.Washington.EDU
+REM
+REM Date: 11 October 1989
+REM Last Edited:30 August 2006
+
+ECHO extern DRIVER %1driver; >> LINKAGE.H
+REM Note the introduction of the caret to quote the ampersand in NT
+if "%OS%" == "Windows_NT" ECHO mail_link (^&%1driver); /* link in the %1 driver */ >> LINKAGE.C
+if "%OS%" == "" ECHO mail_link (&%1driver); /* link in the %1 driver */ >> LINKAGE.C
diff --git a/imap/src/osdep/wce/dummy.h b/imap/src/osdep/wce/dummy.h
new file mode 100644
index 00000000..32650e06
--- /dev/null
+++ b/imap/src/osdep/wce/dummy.h
@@ -0,0 +1,43 @@
+/* ========================================================================
+ * 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: Dummy routines
+ *
+ * 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: 9 May 1991
+ * Last Edited: 30 August 2006
+ */
+
+/* Exported function prototypes */
+
+void dummy_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents);
+void dummy_list (MAILSTREAM *stream,char *ref,char *pat);
+void dummy_lsub (MAILSTREAM *stream,char *ref,char *pat);
+long scan_contents (DRIVER *dtb,char *name,char *contents,
+ unsigned long csiz,unsigned long fsiz);
+long dummy_scan_contents (char *name,char *contents,unsigned long csiz,
+ unsigned long fsiz);
+long dummy_create (MAILSTREAM *stream,char *mailbox);
+long dummy_create_path (MAILSTREAM *stream,char *path,long dirmode);
+long dummy_delete (MAILSTREAM *stream,char *mailbox);
+long dummy_rename (MAILSTREAM *stream,char *old,char *newname);
+char *dummy_file (char *dst,char *name);
+long dummy_canonicalize (char *tmp,char *ref,char *pat);
diff --git a/imap/src/osdep/wce/dummywce.c b/imap/src/osdep/wce/dummywce.c
new file mode 100644
index 00000000..2440be27
--- /dev/null
+++ b/imap/src/osdep/wce/dummywce.c
@@ -0,0 +1,301 @@
+/* ========================================================================
+ * 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: Dummy routines for WCE
+ *
+ * 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: 24 May 1993
+ * Last Edited: 30 August 2006
+ */
+
+
+#include <ctype.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <direct.h>
+#include "mail.h"
+#include "osdep.h"
+#include <sys\stat.h>
+#include <dos.h>
+#include "dummy.h"
+#include "misc.h"
+
+/* Function prototypes */
+
+DRIVER *dummy_valid (char *name);
+void *dummy_parameters (long function,void *value);
+MAILSTREAM *dummy_open (MAILSTREAM *stream);
+void dummy_close (MAILSTREAM *stream,long options);
+long dummy_ping (MAILSTREAM *stream);
+void dummy_check (MAILSTREAM *stream);
+long dummy_expunge (MAILSTREAM *stream,char *sequence,long options);
+long dummy_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options);
+long dummy_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data);
+
+/* Dummy routines */
+
+
+/* Driver dispatch used by MAIL */
+
+DRIVER dummydriver = {
+ "dummy", /* driver name */
+ DR_LOCAL|DR_MAIL, /* driver flags */
+ (DRIVER *) NIL, /* next driver */
+ dummy_valid, /* mailbox is valid for us */
+ dummy_parameters, /* manipulate parameters */
+ dummy_scan, /* scan mailboxes */
+ dummy_list, /* list mailboxes */
+ dummy_lsub, /* list subscribed mailboxes */
+ NIL, /* subscribe to mailbox */
+ NIL, /* unsubscribe from mailbox */
+ dummy_create, /* create mailbox */
+ dummy_delete, /* delete mailbox */
+ dummy_rename, /* rename mailbox */
+ mail_status_default, /* status of mailbox */
+ dummy_open, /* open mailbox */
+ dummy_close, /* close mailbox */
+ NIL, /* fetch message "fast" attributes */
+ NIL, /* fetch message flags */
+ NIL, /* fetch overview */
+ NIL, /* fetch message structure */
+ NIL, /* fetch header */
+ NIL, /* fetch text */
+ NIL, /* fetch message data */
+ NIL, /* unique identifier */
+ NIL, /* message number from UID */
+ NIL, /* modify flags */
+ NIL, /* per-message modify flags */
+ NIL, /* search for message based on criteria */
+ NIL, /* sort messages */
+ NIL, /* thread messages */
+ dummy_ping, /* ping mailbox to see if still alive */
+ dummy_check, /* check for new messages */
+ dummy_expunge, /* expunge deleted messages */
+ dummy_copy, /* copy messages to another mailbox */
+ dummy_append, /* append string message to mailbox */
+ NIL /* garbage collect stream */
+};
+
+
+ /* prototype stream */
+MAILSTREAM dummyproto = {&dummydriver};
+
+ /* driver parameters */
+static char *file_extension = NIL;
+
+/* Dummy validate mailbox
+ * Accepts: mailbox name
+ * Returns: our driver if name is valid, NIL otherwise
+ */
+
+DRIVER *dummy_valid (char *name)
+{
+ char *s,tmp[MAILTMPLEN];
+ struct stat sbuf;
+ /* must be valid local mailbox */
+ return (name && *name && (*name != '{') &&
+ (s = mailboxfile (tmp,name)) && (!*s || !stat (s,&sbuf))) ?
+ &dummydriver : NIL;
+}
+
+
+/* Dummy manipulate driver parameters
+ * Accepts: function code
+ * function-dependent value
+ * Returns: function-dependent return value
+ */
+
+void *dummy_parameters (long function,void *value)
+{
+ return value;
+}
+
+/* Dummy scan mailboxes
+ * Accepts: mail stream
+ * reference
+ * pattern to search
+ * string to scan
+ */
+
+void dummy_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents)
+{
+ /* return silently */
+}
+
+/* Dummy list mailboxes
+ * Accepts: mail stream
+ * reference
+ * pattern to search
+ */
+
+void dummy_list (MAILSTREAM *stream,char *ref,char *pat)
+{
+ /* return silently */
+}
+
+
+/* Dummy list subscribed mailboxes
+ * Accepts: mail stream
+ * pattern to search
+ */
+
+void dummy_lsub (MAILSTREAM *stream,char *ref,char *pat)
+{
+ /* return silently */
+}
+
+/* Dummy create mailbox
+ * Accepts: mail stream
+ * mailbox name to create
+ * Returns: T on success, NIL on failure
+ */
+
+long dummy_create (MAILSTREAM *stream,char *mailbox)
+{
+ return NIL; /* always fails */
+}
+
+
+/* Dummy delete mailbox
+ * Accepts: mail stream
+ * mailbox name to delete
+ * Returns: T on success, NIL on failure
+ */
+
+long dummy_delete (MAILSTREAM *stream,char *mailbox)
+{
+ return NIL; /* always fails */
+}
+
+
+/* Mail rename mailbox
+ * Accepts: mail stream
+ * old mailbox name
+ * new mailbox name
+ * Returns: T on success, NIL on failure
+ */
+
+long dummy_rename (MAILSTREAM *stream,char *old,char *newname)
+{
+ return NIL; /* always fails */
+}
+
+/* Dummy open
+ * Accepts: stream to open
+ * Returns: stream on success, NIL on failure
+ */
+
+MAILSTREAM *dummy_open (MAILSTREAM *stream)
+{
+ char tmp[MAILTMPLEN];
+ /* OP_PROTOTYPE call or silence */
+ if (!stream || stream->silent) return NIL;
+ if (compare_cstring (stream->mailbox,"INBOX")) {
+ sprintf (tmp,"Not a mailbox: %s",stream->mailbox);
+ mm_log (tmp,ERROR);
+ return NIL; /* always fails */
+ }
+ if (!stream->silent) { /* only if silence not requested */
+ mail_exists (stream,0); /* say there are 0 messages */
+ mail_recent (stream,0);
+ stream->uid_validity = time (0);
+ }
+ stream->inbox = T; /* note that it's an INBOX */
+ return stream; /* return success */
+}
+
+
+/* Dummy close
+ * Accepts: MAIL stream
+ * options
+ */
+
+void dummy_close (MAILSTREAM *stream,long options)
+{
+ /* return silently */
+}
+
+/* Dummy ping mailbox
+ * Accepts: MAIL stream
+ * Returns: T if stream alive, else NIL
+ * No-op for readonly files, since read/writer can expunge it from under us!
+ */
+
+long dummy_ping (MAILSTREAM *stream)
+{
+ return T;
+}
+
+
+/* Dummy check mailbox
+ * Accepts: MAIL stream
+ * No-op for readonly files, since read/writer can expunge it from under us!
+ */
+
+void dummy_check (MAILSTREAM *stream)
+{
+ dummy_ping (stream); /* invoke ping */
+}
+
+
+/* Dummy expunge mailbox
+ * Accepts: MAIL stream
+ * sequence to expunge if non-NIL
+ * expunge options
+ * Returns: T, always
+ */
+
+long dummy_expunge (MAILSTREAM *stream,char *sequence,long options)
+{
+ return LONGT;
+}
+
+/* Dummy copy message(s)
+ * Accepts: MAIL stream
+ * sequence
+ * destination mailbox
+ * options
+ * Returns: T if copy successful, else NIL
+ */
+
+long dummy_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options)
+{
+ if ((options & CP_UID) ? mail_uid_sequence (stream,sequence) :
+ mail_sequence (stream,sequence)) fatal ("Impossible dummy_copy");
+ return NIL;
+}
+
+
+/* Dummy append message string
+ * Accepts: mail stream
+ * destination mailbox
+ * stringstruct of message to append
+ * Returns: T on success, NIL on failure
+ */
+
+long dummy_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data)
+{
+ char tmp[MAILTMPLEN];
+ sprintf (tmp,"Can't append to %s",mailbox);
+ mm_log (tmp,ERROR); /* pass up error */
+ return NIL; /* always fails */
+}
diff --git a/imap/src/osdep/wce/env_wce.c b/imap/src/osdep/wce/env_wce.c
new file mode 100644
index 00000000..ea2dbd98
--- /dev/null
+++ b/imap/src/osdep/wce/env_wce.c
@@ -0,0 +1,301 @@
+/* ========================================================================
+ * 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: WCE environment routines
+ *
+ * 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: 1 August 1988
+ * Last Edited: 30 August 2006
+ */
+
+
+static char *myUserName = NIL; /* user name */
+static char *myLocalHost = NIL; /* local host name */
+static char *myClientHost = NIL;/* client host name */
+static char *myServerHost = NIL;/* server host name */
+static char *myHomeDir = NIL; /* home directory name */
+static char *myNewsrc = NIL; /* newsrc file name */
+static char *sysInbox = NIL; /* system inbox name */
+static long list_max_level = 5; /* maximum level of list recursion */
+static short no822tztext = NIL; /* disable RFC [2]822 timezone text */
+ /* home namespace */
+static NAMESPACE nshome = {"",'\\',NIL,NIL};
+ /* namespace list */
+static NAMESPACE *nslist[3] = {&nshome,NIL,NIL};
+static long alarm_countdown = 0;/* alarm count down */
+static void (*alarm_rang) (); /* alarm interrupt function */
+static unsigned int rndm = 0; /* initial `random' number */
+
+
+/* Dummy definitions to prevent errors */
+
+#define server_login(user,pass,authuser,argc,argv) NIL
+#define authserver_login(user,authuser,argc,argv) NIL
+#define myusername() ""
+#define MD5ENABLE "\\.nosuch.."
+
+#include "pmatch.c" /* include wildcard pattern matcher */
+
+/* Environment manipulate parameters
+ * Accepts: function code
+ * function-dependent value
+ * Returns: function-dependent return value
+ */
+
+void *env_parameters (long function,void *value)
+{
+ void *ret = NIL;
+ switch ((int) function) {
+ case GET_NAMESPACE:
+ ret = (void *) nslist;
+ break;
+ case SET_HOMEDIR:
+ myHomeDir = cpystr ((char *) value);
+ case GET_HOMEDIR:
+ ret = (void *) myHomeDir;
+ break;
+ case SET_LOCALHOST:
+ myLocalHost = cpystr ((char *) value);
+ case GET_LOCALHOST:
+ ret = (void *) myLocalHost;
+ break;
+ case SET_NEWSRC:
+ if (myNewsrc) fs_give ((void **) &myNewsrc);
+ myNewsrc = cpystr ((char *) value);
+ case GET_NEWSRC:
+ if (!myNewsrc) { /* set news file name if not defined */
+ char tmp[MAILTMPLEN];
+ sprintf (tmp,"%s\\NEWSRC",myhomedir ());
+ myNewsrc = cpystr (tmp);
+ }
+ ret = (void *) myNewsrc;
+ break;
+ case SET_SYSINBOX:
+ if (sysInbox) fs_give ((void **) &sysInbox);
+ sysInbox = cpystr ((char *) value);
+ case GET_SYSINBOX:
+ ret = (void *) sysInbox;
+ break;
+ case SET_LISTMAXLEVEL:
+ list_max_level = (long) value;
+ case GET_LISTMAXLEVEL:
+ ret = (void *) list_max_level;
+ break;
+ case SET_DISABLE822TZTEXT:
+ no822tztext = value ? T : NIL;
+ case GET_DISABLE822TZTEXT:
+ ret = (void *) (no822tztext ? VOIDT : NIL);
+ break;
+ }
+ return ret;
+}
+
+/* Write current time
+ * Accepts: destination string
+ * optional format of day-of-week prefix
+ * format of date and time
+ * flag whether to append symbolic timezone
+ */
+
+static void do_date (char *date,char *prefix,char *fmt,int suffix)
+{
+ time_t tn = time (0);
+ struct tm *t = gmtime (&tn);
+ int zone = t->tm_hour * 60 + t->tm_min;
+ int julian = t->tm_yday;
+ t = localtime (&tn); /* get local time now */
+ /* minus UTC minutes since midnight */
+ zone = t->tm_hour * 60 + t->tm_min - zone;
+ /* julian can be one of:
+ * 36x local time is December 31, UTC is January 1, offset -24 hours
+ * 1 local time is 1 day ahead of UTC, offset +24 hours
+ * 0 local time is same day as UTC, no offset
+ * -1 local time is 1 day behind UTC, offset -24 hours
+ * -36x local time is January 1, UTC is December 31, offset +24 hours
+ */
+ if (julian = t->tm_yday -julian)
+ zone += ((julian < 0) == (abs (julian) == 1)) ? -24*60 : 24*60;
+ if (prefix) { /* want day of week? */
+ sprintf (date,prefix,days[t->tm_wday]);
+ date += strlen (date); /* make next sprintf append */
+ }
+ /* output the date */
+ sprintf (date,fmt,t->tm_mday,months[t->tm_mon],t->tm_year+1900,
+ t->tm_hour,t->tm_min,t->tm_sec,zone/60,abs (zone) % 60);
+ if (suffix) { /* append timezone suffix if desired */
+ char *tz;
+ tzset (); /* get timezone from TZ environment stuff */
+ tz = tzname[daylight ? (((struct tm *) t)->tm_isdst > 0) : 0];
+ if (tz && tz[0]) sprintf (date + strlen (date)," (%s)",tz);
+ }
+}
+
+
+/* Write current time in RFC 822 format
+ * Accepts: destination string
+ */
+
+void rfc822_date (char *date)
+{
+ do_date (date,"%s, ","%d %s %d %02d:%02d:%02d %+03d%02d",
+ no822tztext ? NIL : T);
+}
+
+
+/* Write current time in internal format
+ * Accepts: destination string
+ */
+
+void internal_date (char *date)
+{
+ do_date (date,NIL,"%02d-%s-%d %02d:%02d:%02d %+03d%02d",NIL);
+}
+
+/* Return random number
+ */
+
+long random ()
+{
+ if (!rndm) srand (rndm = (unsigned) time (0L));
+ return (long) rand ();
+}
+
+/* Return default drive
+ * Returns: default drive
+ */
+
+static char *defaultDrive (void)
+{
+ char *s;
+ return ((s = getenv ("SystemDrive")) && *s) ? s : "C:";
+}
+
+
+/* Return home drive from environment variables
+ * Returns: home drive
+ */
+
+static char *homeDrive (void)
+{
+ char *s;
+ return ((s = getenv ("HOMEDRIVE")) && *s) ? s : defaultDrive ();
+}
+
+
+/* Return home path from environment variables
+ * Accepts: path to write into
+ * Returns: home path or NIL if it can't be determined
+ */
+
+static char *homePath (char *path)
+{
+ int i;
+ char *s;
+ if (!((s = getenv ("HOMEPATH")) && (i = strlen (s)))) return NIL;
+ if (((s[i-1] == '\\') || (s[i-1] == '/'))) s[i-1] = '\0';
+ sprintf (path,"%s%s",homeDrive (),s);
+ return path;
+}
+
+/* Return my home directory name
+ * Returns: my home directory name
+ */
+
+char *myhomedir ()
+{
+ char tmp[MAILTMPLEN];
+ /* initialize if first time */
+ if (!myHomeDir) myHomeDir = homePath (tmp);
+ return myHomeDir ? myHomeDir : homeDrive ();
+}
+
+/* Return system standard INBOX
+ * Accepts: buffer string
+ */
+
+char *sysinbox ()
+{
+ char tmp[MAILTMPLEN];
+ if (!sysInbox) { /* initialize if first time */
+ sprintf (tmp,"%s\\INBOX",myhomedir ());
+ sysInbox = cpystr (tmp); /* system inbox is from mail spool */
+ }
+ return sysInbox;
+}
+
+
+/* Return mailbox file name
+ * Accepts: destination buffer
+ * mailbox name
+ * Returns: file name
+ */
+
+char *mailboxfile (char *dst,char *name)
+{
+ char *dir = myhomedir ();
+ *dst = '\0'; /* default to empty string */
+ if (((name[0] == 'I') || (name[0] == 'i')) &&
+ ((name[1] == 'N') || (name[1] == 'n')) &&
+ ((name[2] == 'B') || (name[2] == 'b')) &&
+ ((name[3] == 'O') || (name[3] == 'o')) &&
+ ((name[4] == 'X') || (name[4] == 'x')) && !name[5]) name = NIL;
+ /* reject namespace names or names with / */
+ if (name && ((*name == '#') || strchr (name,'/'))) return NIL;
+ else if (!name) return dst; /* driver selects the INBOX name */
+ /* absolute path name? */
+ else if ((*name == '\\') || (name[1] == ':')) return strcpy (dst,name);
+ /* build resulting name */
+ sprintf (dst,"%s\\%s",dir,name);
+ return dst; /* return it */
+}
+
+
+/* Determine default prototype stream to user
+ * Accepts: type (NIL for create, T for append)
+ * Returns: default prototype stream
+ */
+
+MAILSTREAM *default_proto (long type)
+{
+ extern MAILSTREAM CREATEPROTO,APPENDPROTO;
+ return type ? &APPENDPROTO : &CREATEPROTO;
+}
+
+/* Emulator for BSD syslog() routine
+ * Accepts: priority
+ * message
+ * parameters
+ */
+
+void syslog (int priority,const char *message,...)
+{
+}
+
+
+/* Emulator for BSD openlog() routine
+ * Accepts: identity
+ * options
+ * facility
+ */
+
+void openlog (const char *ident,int logopt,int facility)
+{
+}
diff --git a/imap/src/osdep/wce/env_wce.h b/imap/src/osdep/wce/env_wce.h
new file mode 100644
index 00000000..e3c6c7f0
--- /dev/null
+++ b/imap/src/osdep/wce/env_wce.h
@@ -0,0 +1,70 @@
+/* ========================================================================
+ * 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: WCE environment routines
+ *
+ * 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: 1 August 1988
+ * Last Edited: 30 August 2006
+ */
+
+
+#define SUBSCRIPTIONFILE(t) sprintf (t,"%s\\MAILBOX.LST",myhomedir ())
+#define SUBSCRIPTIONTEMP(t) sprintf (t,"%s\\MAILBOX.TMP",myhomedir ())
+
+#define L_SET SEEK_SET
+
+/* Function prototypes */
+
+#include "env.h"
+
+static char *defaultDrive (void);
+static char *homeDrive (void);
+static char *homePath (char *path);
+char *sysinbox ();
+long random ();
+unsigned long unix_crlfcpy (char **dst,unsigned long *dstl,char *src,
+ unsigned long srcl);
+unsigned long unix_crlflen (STRING *s);
+#define getpid random
+
+
+/* syslog() emulation */
+
+#define LOG_MAIL (2<<3) /* mail system */
+#define LOG_DAEMON (3<<3) /* system daemons */
+#define LOG_AUTH (4<<3) /* security/authorization messages */
+#define LOG_EMERG 0 /* system is unusable */
+#define LOG_ALERT 1 /* action must be taken immediately */
+#define LOG_CRIT 2 /* critical conditions */
+#define LOG_ERR 3 /* error conditions */
+#define LOG_WARNING 4 /* warning conditions */
+#define LOG_NOTICE 5 /* normal but signification condition */
+#define LOG_INFO 6 /* informational */
+#define LOG_DEBUG 7 /* debug-level messages */
+#define LOG_PID 0x01 /* log the pid with each message */
+#define LOG_CONS 0x02 /* log on the console if errors in sending */
+#define LOG_ODELAY 0x04 /* delay open until syslog() is called */
+#define LOG_NDELAY 0x08 /* don't delay open */
+#define LOG_NOWAIT 0x10 /* if forking to log on console, don't wait() */
+
+void openlog (const char *ident,int logopt,int facility);
+void syslog (int priority,const char *message,...);
diff --git a/imap/src/osdep/wce/fs_wce.c b/imap/src/osdep/wce/fs_wce.c
new file mode 100644
index 00000000..03908328
--- /dev/null
+++ b/imap/src/osdep/wce/fs_wce.c
@@ -0,0 +1,62 @@
+/* ========================================================================
+ * 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: Free storage management routines
+ *
+ * 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: 1 August 1988
+ * Last Edited: 30 August 2006
+ */
+
+/* Get a block of free storage
+ * Accepts: size of desired block
+ * Returns: free storage block
+ */
+
+void *fs_get (size_t size)
+{
+ void *block = malloc (size ? size : (size_t) 1);
+ if (!block) fatal ("Out of memory");
+ return (block);
+}
+
+
+/* Resize a block of free storage
+ * Accepts: ** pointer to current block
+ * new size
+ */
+
+void fs_resize (void **block,size_t size)
+{
+ if (!(*block = realloc (*block,size ? size : (size_t) 1)))
+ fatal ("Can't resize memory");
+}
+
+
+/* Return a block of free storage
+ * Accepts: ** pointer to free storage block
+ */
+
+void fs_give (void **block)
+{
+ free (*block);
+ *block = NIL;
+}
diff --git a/imap/src/osdep/wce/ftl_wce.c b/imap/src/osdep/wce/ftl_wce.c
new file mode 100644
index 00000000..9e65ef55
--- /dev/null
+++ b/imap/src/osdep/wce/ftl_wce.c
@@ -0,0 +1,38 @@
+/* ========================================================================
+ * 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: DOS/VMS/TOPS-20 crash management routines
+ *
+ * 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: 1 August 1988
+ * Last Edited: 30 August 2006
+ */
+
+
+/* Report a fatal error
+ * Accepts: string to output
+ */
+
+void fatal (char *string)
+{
+ mm_fatal (string); /* pass up the string */
+ abort (); /* die horribly */
+}
diff --git a/imap/src/osdep/wce/makefile.wce b/imap/src/osdep/wce/makefile.wce
new file mode 100644
index 00000000..cdf8198d
--- /dev/null
+++ b/imap/src/osdep/wce/makefile.wce
@@ -0,0 +1,96 @@
+# ========================================================================
+# 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: Portable C client makefile -- WCE version
+#
+# 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: 11 May 1989
+# Last Edited: 30 August 2006
+
+
+EXTRAAUTHENTICATORS=
+DEFAULTAUTHENTICATORS=ext md5 pla log
+EXTRADRIVERS =
+DRIVERS = imap nntp pop3
+DEFAULTDRIVER = dummy
+CFLAGS= /MT /W3 /D_SH3_ -nologo $(EXTRACFLAGS)
+CC = shcl
+CCLIENTLIB= cclient.lib
+
+all: $(CCLIENTLIB)
+
+.c.obj:
+ $(CC) -c $(CFLAGS) $*.c
+
+osdep.h: os_wce.h
+ copy os_wce.h osdep.h
+ drivers $(EXTRADRIVERS) $(DRIVERS) dummy
+ setproto $(DEFAULTDRIVER) $(DEFAULTDRIVER)
+ mkauths $(EXTRAAUTHENTICATORS) $(DEFAULTAUTHENTICATORS)
+
+mail.obj: mail.h misc.h osdep.h mail.c
+
+misc.obj: mail.h misc.h misc.c
+
+flstring.obj: mail.h misc.h osdep.h flstring.h flstring.c
+
+netmsg.obj: mail.h misc.h netmsg.h osdep.h netmsg.c
+
+newsrc.obj: mail.h misc.h newsrc.h osdep.h newsrc.c
+
+rfc822.obj: mail.h rfc822.h misc.h rfc822.c
+
+smanager.obj: mail.h misc.h smanager.c
+
+utf8.obj: mail.h misc.h osdep.h utf8.h
+
+utf8aux.obj: mail.h misc.h osdep.h utf8.h
+
+imap4r1.obj: mail.h imap4r1.h misc.h osdep.h imap4r1.c
+
+nntp.obj: mail.h nntp.h smtp.h rfc822.h misc.h osdep.h nntp.c
+
+pop3.obj: mail.h pop3.h rfc822.h misc.h osdep.h pop3.c
+
+smtp.obj: mail.h smtp.h rfc822.h misc.h osdep.h smtp.c
+
+os_wce.obj: mail.h osdep.h env_wce.h fs.h ftl.h nl.h tcp.h tcp_wce.h \
+ os_wce.c fs_wce.c ftl_wce.c nl_wce.c env_wce.c tcp_wce.c \
+ auth_md5.c auth_log.c pmatch.c
+
+dummywce.obj: mail.h dummy.h misc.h osdep.h dummywce.c
+
+$(CCLIENTLIB): mail.obj misc.obj flstring.obj netmsg.obj \
+ newsrc.obj rfc822.obj smanager.obj utf8.obj utf8aux.obj \
+ imap4r1.obj nntp.obj pop3.obj smtp.obj os_wce.obj \
+ dummywce.obj
+ erase $(CCLIENTLIB)
+ LIB /NOLOGO /OUT:cclient.lib \
+ mail.obj misc.obj flstring.obj netmsg.obj \
+ newsrc.obj rfc822.obj smanager.obj utf8.obj utf8aux.obj \
+ imap4r1.obj nntp.obj pop3.obj smtp.obj os_wce.obj \
+ dummywce.obj
+
+clean:
+ del *.lib *.obj linkage.* osdep.* auths.c *.exe *.exp || rem
+
+# A monument to a hack of long ago and far away...
+
+love:
+ @echo not war?
diff --git a/imap/src/osdep/wce/mkautaux.bat b/imap/src/osdep/wce/mkautaux.bat
new file mode 100644
index 00000000..c65022d2
--- /dev/null
+++ b/imap/src/osdep/wce/mkautaux.bat
@@ -0,0 +1,31 @@
+@ECHO OFF
+REM ========================================================================
+REM Copyright 1988-2006 University of Washington
+REM
+REM Licensed under the Apache License, Version 2.0 (the "License");
+REM you may not use this file except in compliance with the License.
+REM You may obtain a copy of the License at
+REM
+REM http://www.apache.org/licenses/LICENSE-2.0
+REM
+REM
+REM ========================================================================
+
+REM Program: Authenticator Linkage Generator auxillary for NT/Win9x
+REM
+REM Author: Mark Crispin
+REM Networks and Distributed Computing
+REM Computing & Communications
+REM University of Washington
+REM Administration Building, AG-44
+REM Seattle, WA 98195
+REM Internet: MRC@CAC.Washington.EDU
+REM
+REM Date: 6 December 1995
+REM Last Edited:30 August 2006
+
+ECHO extern AUTHENTICATOR auth_%1; >> LINKAGE.H
+REM Note the introduction of the caret to quote the ampersand in NT
+if "%OS%" == "Windows_NT" ECHO auth_link (^&auth_%1); /* link in the %1 authenticator */ >> LINKAGE.C
+if "%OS%" == "" ECHO auth_link (&auth_%1); /* link in the %1 authenticator */ >> LINKAGE.C
+ECHO #include "auth_%1.c" >> AUTHS.C
diff --git a/imap/src/osdep/wce/mkauths.bat b/imap/src/osdep/wce/mkauths.bat
new file mode 100644
index 00000000..d8c5e360
--- /dev/null
+++ b/imap/src/osdep/wce/mkauths.bat
@@ -0,0 +1,33 @@
+@ECHO OFF
+REM ========================================================================
+REM Copyright 1988-2006 University of Washington
+REM
+REM Licensed under the Apache License, Version 2.0 (the "License");
+REM you may not use this file except in compliance with the License.
+REM You may obtain a copy of the License at
+REM
+REM http://www.apache.org/licenses/LICENSE-2.0
+REM
+REM
+REM ========================================================================
+
+REM Program: Authenticator Linkage Generator for DOS and Windows
+REM
+REM Author: Mark Crispin
+REM Networks and Distributed Computing
+REM Computing & Communications
+REM University of Washington
+REM Administration Building, AG-44
+REM Seattle, WA 98195
+REM Internet: MRC@CAC.Washington.EDU
+REM
+REM Date: 6 December 1995
+REM Last Edited:30 August 2006
+
+REM Erase old authenticators list
+IF EXIST AUTHS.C DEL AUTHS.C
+
+REM Now define the new list
+FOR %%D IN (%1 %2 %3 %4 %5 %6 %7 %8 %9) DO CALL MKAUTAUX %%D
+
+EXIT 0
diff --git a/imap/src/osdep/wce/nl_wce.c b/imap/src/osdep/wce/nl_wce.c
new file mode 100644
index 00000000..47cb7f0a
--- /dev/null
+++ b/imap/src/osdep/wce/nl_wce.c
@@ -0,0 +1,61 @@
+/* ========================================================================
+ * 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: Windows/TOPS-20 newline routines
+ *
+ * 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: 1 August 1988
+ * Last Edited: 30 August 2006
+ */
+
+/* Copy string with CRLF newlines
+ * Accepts: destination string
+ * pointer to size of destination string buffer
+ * source string
+ * length of source string
+ * Returns: length of copied string
+ */
+
+unsigned long strcrlfcpy (unsigned char **dst,unsigned long *dstl,
+ unsigned char *src,unsigned long srcl)
+{
+ /* flush destination buffer if too small */
+ if (*dst && (srcl > *dstl)) fs_give ((void **) dst);
+ if (!*dst) { /* make a new buffer if needed */
+ *dst = (char *) fs_get ((size_t) (*dstl = srcl) + 1);
+ if (dstl) *dstl = srcl; /* return new buffer length to main program */
+ }
+ /* copy strings */
+ if (srcl) memcpy (*dst,src,(size_t) srcl);
+ *(*dst + srcl) = '\0'; /* tie off destination */
+ return srcl; /* return length */
+}
+
+
+/* Length of string after strcrlfcpy applied
+ * Accepts: source string
+ * Returns: length of string
+ */
+
+unsigned long strcrlflen (STRING *s)
+{
+ return SIZE (s); /* no-brainer on DOS! */
+}
diff --git a/imap/src/osdep/wce/os_wce.c b/imap/src/osdep/wce/os_wce.c
new file mode 100644
index 00000000..7cf3ffe7
--- /dev/null
+++ b/imap/src/osdep/wce/os_wce.c
@@ -0,0 +1,45 @@
+/* ========================================================================
+ * 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: Operating-system dependent routines -- WCE version
+ *
+ * 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: 11 April 1989
+ * Last Edited: 30 August 2006
+ */
+
+#include "tcp_wce.h" /* must be before osdep includes tcp.h */
+#include "mail.h"
+#include "osdep.h"
+#include <winsock.h>
+#include <stdio.h>
+#include <time.h>
+#include <sys\timeb.h>
+#include <fcntl.h>
+#include <sys\stat.h>
+#include "misc.h"
+
+#include "fs_wce.c"
+#include "ftl_wce.c"
+#include "nl_wce.c"
+#include "env_wce.c"
+#include "tcp_wce.c"
+#include "auths.c"
diff --git a/imap/src/osdep/wce/os_wce.h b/imap/src/osdep/wce/os_wce.h
new file mode 100644
index 00000000..45bd76a1
--- /dev/null
+++ b/imap/src/osdep/wce/os_wce.h
@@ -0,0 +1,53 @@
+/* ========================================================================
+ * 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: Operating-system dependent routines -- WCE version
+ *
+ * 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: 11 May 1989
+ * Last Edited: 30 August 2006
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+ /* missing in string.h */
+_CRTIMP char * __cdecl strpbrk (const char *, const char *);
+_CRTIMP char * __cdecl strrchr(const char *, int);
+#include <sys\types.h>
+#undef ERROR
+#include <windows.h>
+#undef ERROR
+#define ERROR (long) 2 /* must match mail.h */
+#include <time.h>
+#include <io.h>
+
+#define gethostid clock
+#define WSA_VERSION ((1 << 8) | 1)
+
+#include "env_wce.h"
+#include "fs.h"
+#include "ftl.h"
+#include "nl.h"
+#include "tcp.h"
+
+#undef noErr
+#undef MAC
diff --git a/imap/src/osdep/wce/pmatch.c b/imap/src/osdep/wce/pmatch.c
new file mode 100644
index 00000000..95a0bb86
--- /dev/null
+++ b/imap/src/osdep/wce/pmatch.c
@@ -0,0 +1,89 @@
+/* ========================================================================
+ * 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: IMAP Wildcard Matching Routines (case-independent)
+ *
+ * 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: 15 June 2000
+ * Last Edited: 30 August 2006
+ */
+
+/* Wildcard pattern match
+ * Accepts: base string
+ * pattern string
+ * delimiter character
+ * Returns: T if pattern matches base, else NIL
+ */
+
+long pmatch_full (unsigned char *s,unsigned char *pat,unsigned char delim)
+{
+ switch (*pat) {
+ case '%': /* non-recursive */
+ /* % at end, OK if no inferiors */
+ if (!pat[1]) return (delim && strchr (s,delim)) ? NIL : T;
+ /* scan remainder of string until delimiter */
+ do if (pmatch_full (s,pat+1,delim)) return T;
+ while ((*s != delim) && *s++);
+ break;
+ case '*': /* match 0 or more characters */
+ if (!pat[1]) return T; /* * at end, unconditional match */
+ /* scan remainder of string */
+ do if (pmatch_full (s,pat+1,delim)) return T;
+ while (*s++);
+ break;
+ case '\0': /* end of pattern */
+ return *s ? NIL : T; /* success if also end of base */
+ default: /* match this character */
+ return compare_uchar (*pat,*s) ? NIL : pmatch_full (s+1,pat+1,delim);
+ }
+ return NIL;
+}
+
+/* Directory pattern match
+ * Accepts: base string
+ * pattern string
+ * delimiter character
+ * Returns: T if base is a matching directory of pattern, else NIL
+ */
+
+long dmatch (unsigned char *s,unsigned char *pat,unsigned char delim)
+{
+ switch (*pat) {
+ case '%': /* non-recursive */
+ if (!*s) return T; /* end of base means have a subset match */
+ if (!*++pat) return NIL; /* % at end, no inferiors permitted */
+ /* scan remainder of string until delimiter */
+ do if (dmatch (s,pat,delim)) return T;
+ while ((*s != delim) && *s++);
+ if (*s && !s[1]) return T; /* ends with delimiter, must be subset */
+ return dmatch (s,pat,delim);/* do new scan */
+ case '*': /* match 0 or more characters */
+ return T; /* unconditional match */
+ case '\0': /* end of pattern */
+ break;
+ default: /* match this character */
+ if (*s) return compare_uchar (*pat,*s) ? NIL : dmatch (s+1,pat+1,delim);
+ /* end of base, return if at delimiter */
+ else if (*pat == delim) return T;
+ break;
+ }
+ return NIL;
+}
diff --git a/imap/src/osdep/wce/setproto.bat b/imap/src/osdep/wce/setproto.bat
new file mode 100644
index 00000000..ce7cb1ef
--- /dev/null
+++ b/imap/src/osdep/wce/setproto.bat
@@ -0,0 +1,29 @@
+@ECHO OFF
+REM ========================================================================
+REM Copyright 1988-2006 University of Washington
+REM
+REM Licensed under the Apache License, Version 2.0 (the "License");
+REM you may not use this file except in compliance with the License.
+REM You may obtain a copy of the License at
+REM
+REM http://www.apache.org/licenses/LICENSE-2.0
+REM
+REM
+REM ========================================================================
+
+REM Program: Set default prototype for DOS/NT
+REM
+REM Author: Mark Crispin
+REM Networks and Distributed Computing
+REM Computing & Communications
+REM University of Washington
+REM Administration Building, AG-44
+REM Seattle, WA 98195
+REM Internet: MRC@CAC.Washington.EDU
+REM
+REM Date: 9 October 1995
+REM Last Edited: 30 August 2006
+
+REM Set the default drivers
+ECHO #define CREATEPROTO %1proto >> LINKAGE.H
+ECHO #define APPENDPROTO %2proto >> LINKAGE.H
diff --git a/imap/src/osdep/wce/tcp_wce.c b/imap/src/osdep/wce/tcp_wce.c
new file mode 100644
index 00000000..90e206a9
--- /dev/null
+++ b/imap/src/osdep/wce/tcp_wce.c
@@ -0,0 +1,818 @@
+/* ========================================================================
+ * 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: Winsock TCP/IP routines
+ *
+ * Author: Mark Crispin from Mike Seibel's Winsock code
+ * Networks and Distributed Computing
+ * Computing & Communications
+ * University of Washington
+ * Administration Building, AG-44
+ * Seattle, WA 98195
+ * Internet: MRC@CAC.Washington.EDU
+ *
+ * Date: 11 April 1989
+ * Last Edited: 13 January 2008
+ */
+
+
+#define TCPMAXSEND 32768
+
+/* Private functions */
+
+int tcp_socket_open (struct sockaddr_in *sin,char *tmp,char *hst,
+ unsigned long port);
+static char *tcp_getline_work (TCPSTREAM *stream,unsigned long *size,
+ long *contd);
+long tcp_abort (TCPSTREAM *stream);
+long tcp_close_socket (SOCKET *sock);
+char *tcp_name (struct sockaddr_in *sin,long flag);
+char *tcp_name_valid (char *s);
+
+
+/* Private data */
+
+int wsa_initted = 0; /* init ? */
+static int wsa_sock_open = 0; /* keep track of open sockets */
+static tcptimeout_t tmoh = NIL; /* TCP timeout handler routine */
+static long ttmo_read = 0; /* TCP timeouts, in seconds */
+static long ttmo_write = 0;
+static long allowreversedns = T;/* allow reverse DNS lookup */
+static long tcpdebug = NIL; /* extra TCP debugging telemetry */
+
+/* TCP/IP manipulate parameters
+ * Accepts: function code
+ * function-dependent value
+ * Returns: function-dependent return value
+ */
+
+void *tcp_parameters (long function,void *value)
+{
+ void *ret = NIL;
+ switch ((int) function) {
+ case SET_TIMEOUT:
+ tmoh = (tcptimeout_t) value;
+ case GET_TIMEOUT:
+ ret = (void *) tmoh;
+ break;
+ case SET_READTIMEOUT:
+ ttmo_read = (long) value;
+ case GET_READTIMEOUT:
+ ret = (void *) ttmo_read;
+ break;
+ case SET_WRITETIMEOUT:
+ ttmo_write = (long) value;
+ case GET_WRITETIMEOUT:
+ ret = (void *) ttmo_write;
+ break;
+ case SET_ALLOWREVERSEDNS:
+ allowreversedns = (long) value;
+ case GET_ALLOWREVERSEDNS:
+ ret = (void *) allowreversedns;
+ break;
+ case SET_TCPDEBUG:
+ tcpdebug = (long) value;
+ case GET_TCPDEBUG:
+ ret = (void *) tcpdebug;
+ break;
+ }
+ return ret;
+}
+
+/* TCP/IP open
+ * Accepts: host name
+ * contact service name
+ * contact port number and optional silent flag
+ * Returns: TCP/IP stream if success else NIL
+ */
+
+TCPSTREAM *tcp_open (char *host,char *service,unsigned long port)
+{
+ TCPSTREAM *stream = NIL;
+ int i;
+ SOCKET sock = INVALID_SOCKET;
+ int silent = (port & NET_SILENT) ? T : NIL;
+ char *s;
+ struct sockaddr_in sin;
+ struct hostent *he;
+ char hostname[MAILTMPLEN];
+ char tmp[MAILTMPLEN];
+ struct servent *sv = NIL;
+ blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL);
+ if (!wsa_initted++) { /* init Windows Sockets */
+ WSADATA wsock;
+ if (i = (int) WSAStartup (WSA_VERSION,&wsock)) {
+ wsa_initted = 0; /* in case we try again */
+ sprintf (tmp,"Unable to start Windows Sockets (%d)",i);
+ mm_log (tmp,ERROR);
+ return NIL;
+ }
+ }
+ port &= 0xffff; /* erase flags */
+ /* lookup service */
+ if (service && (sv = getservbyname (service,"tcp")))
+ port = ntohs (sin.sin_port = sv->s_port);
+ /* copy port number in network format */
+ else sin.sin_port = htons ((u_short) port);
+ /* The domain literal form is used (rather than simply the dotted decimal
+ as with other Windows programs) because it has to be a valid "host name"
+ in mailsystem terminology. */
+ sin.sin_family = AF_INET; /* family is always Internet */
+ /* look like domain literal? */
+ if (host[0] == '[' && host[(strlen (host))-1] == ']') {
+ strcpy (tmp,host+1); /* yes, copy number part */
+ tmp[strlen (tmp)-1] = '\0';
+ if ((sin.sin_addr.s_addr = inet_addr (tmp)) == INADDR_NONE) {
+ sprintf (tmp,"Bad format domain-literal: %.80s",host);
+ mm_log (tmp,ERROR);
+ return NIL;
+ }
+ else {
+ sin.sin_family = AF_INET; /* family is always Internet */
+ strcpy (hostname,host);
+ (*bn) (BLOCK_TCPOPEN,NIL);
+ sock = tcp_socket_open (&sin,tmp,hostname,port);
+ (*bn) (BLOCK_NONE,NIL);
+ }
+ }
+
+ else { /* lookup host name */
+ if (tcpdebug) {
+ sprintf (tmp,"DNS resolution %.80s",host);
+ mm_log (tmp,TCPDEBUG);
+ }
+ (*bn) (BLOCK_DNSLOOKUP,NIL);/* look up name */
+ if (!(he = gethostbyname (lcase (strcpy (tmp,host)))))
+ sprintf (tmp,"Host not found (#%d): %s",WSAGetLastError(),host);
+ (*bn) (BLOCK_NONE,NIL);
+ if (he) { /* DNS resolution won? */
+ if (tcpdebug) mm_log ("DNS resolution done",TCPDEBUG);
+ /* copy address type */
+ sin.sin_family = he->h_addrtype;
+ /* copy host name */
+ strcpy (hostname,he->h_name);
+ wsa_sock_open++; /* prevent tcp_close_socket() from freeing in
+ loop */
+ for (i = 0; (sock == INVALID_SOCKET) && (s = he->h_addr_list[i]); i++) {
+ if (i && !silent) mm_log (tmp,WARN);
+ memcpy (&sin.sin_addr,s,he->h_length);
+ (*bn) (BLOCK_TCPOPEN,NIL);
+ sock = tcp_socket_open (&sin,tmp,hostname,port);
+ (*bn) (BLOCK_NONE,NIL);
+ }
+ wsa_sock_open--; /* undo protection */
+ }
+ }
+ if (sock == INVALID_SOCKET) { /* error? */
+ if (!silent) mm_log (tmp,ERROR);
+ tcp_close_socket (&sock); /* do possible cleanup action */
+ }
+ else { /* got a socket, create TCP/IP stream */
+ stream = (TCPSTREAM *) memset (fs_get (sizeof (TCPSTREAM)),0,
+ sizeof (TCPSTREAM));
+ stream->port = port; /* port number */
+ /* init socket */
+ stream->tcpsi = stream->tcpso = sock;
+ stream->ictr = 0; /* init input counter */
+ /* copy official host name */
+ stream->host = cpystr (hostname);
+ if (tcpdebug) mm_log ("Stream open and ready for read",TCPDEBUG);
+ }
+ return stream; /* return success */
+}
+
+/* Open a TCP socket
+ * Accepts: Internet socket address block
+ * scratch buffer
+ * host name for error message
+ * port number for error message
+ * Returns: socket if success, else -1 with error string in scratch buffer
+ */
+
+int tcp_socket_open (struct sockaddr_in *sin,char *tmp,char *hst,
+ unsigned long port)
+{
+ int sock;
+ char *s;
+ sprintf (tmp,"Trying IP address [%s]",inet_ntoa (sin->sin_addr));
+ mm_log (tmp,NIL);
+ /* get a TCP stream */
+ if ((sock = socket (sin->sin_family,SOCK_STREAM,0)) == INVALID_SOCKET) {
+ sprintf (tmp,"Unable to create TCP socket (%d)",WSAGetLastError());
+ return -1;
+ }
+ wsa_sock_open++; /* count this socket as open */
+ /* open connection */
+ if (connect (sock,(struct sockaddr *) sin,sizeof (struct sockaddr_in)) ==
+ SOCKET_ERROR) {
+ switch (WSAGetLastError ()){/* analyze error */
+ case WSAECONNREFUSED:
+ s = "Refused";
+ break;
+ case WSAENOBUFS:
+ s = "Insufficient system resources";
+ break;
+ case WSAETIMEDOUT:
+ s = "Timed out";
+ break;
+ case WSAEHOSTUNREACH:
+ s = "Host unreachable";
+ break;
+ default:
+ s = "Unknown error";
+ break;
+ }
+ sprintf (tmp,"Can't connect to %.80s,%ld: %s (%d)",hst,port,s,
+ WSAGetLastError ());
+ tcp_close_socket (&sock); /* flush socket */
+ sock = INVALID_SOCKET;
+ }
+ return sock; /* return the socket */
+}
+
+/* TCP/IP authenticated open
+ * Accepts: NETMBX specifier
+ * service name
+ * returned user name buffer
+ * Returns: TCP/IP stream if success else NIL
+ */
+
+TCPSTREAM *tcp_aopen (NETMBX *mb,char *service,char *usrbuf)
+{
+ return NIL; /* always NIL on Windows */
+}
+
+/* TCP receive line
+ * Accepts: TCP stream
+ * Returns: text line string or NIL if failure
+ */
+
+char *tcp_getline (TCPSTREAM *stream)
+{
+ unsigned long n,contd;
+ char *ret = tcp_getline_work (stream,&n,&contd);
+ if (ret && contd) { /* got a line needing continuation? */
+ STRINGLIST *stl = mail_newstringlist ();
+ STRINGLIST *stc = stl;
+ do { /* collect additional lines */
+ stc->text.data = (unsigned char *) ret;
+ stc->text.size = n;
+ stc = stc->next = mail_newstringlist ();
+ ret = tcp_getline_work (stream,&n,&contd);
+ } while (ret && contd);
+ if (ret) { /* stash final part of line on list */
+ stc->text.data = (unsigned char *) ret;
+ stc->text.size = n;
+ /* determine how large a buffer we need */
+ for (n = 0, stc = stl; stc; stc = stc->next) n += stc->text.size;
+ ret = fs_get (n + 1); /* copy parts into buffer */
+ for (n = 0, stc = stl; stc; n += stc->text.size, stc = stc->next)
+ memcpy (ret + n,stc->text.data,stc->text.size);
+ ret[n] = '\0';
+ }
+ mail_free_stringlist (&stl);/* either way, done with list */
+ }
+ return ret;
+}
+
+/* TCP receive line or partial line
+ * Accepts: TCP stream
+ * pointer to return size
+ * pointer to return continuation flag
+ * Returns: text line string, size and continuation flag, or NIL if failure
+ */
+
+static char *tcp_getline_work (TCPSTREAM *stream,unsigned long *size,
+ long *contd)
+{
+ unsigned long n;
+ char *s,*ret,c,d;
+ *contd = NIL; /* assume no continuation */
+ /* make sure have data */
+ if (!tcp_getdata (stream)) return NIL;
+ for (s = stream->iptr, n = 0, c = '\0'; stream->ictr--; n++, c = d) {
+ d = *stream->iptr++; /* slurp another character */
+ if ((c == '\015') && (d == '\012')) {
+ ret = (char *) fs_get (n--);
+ memcpy (ret,s,*size = n); /* copy into a free storage string */
+ ret[n] = '\0'; /* tie off string with null */
+ return ret;
+ }
+ }
+ /* copy partial string from buffer */
+ memcpy ((ret = (char *) fs_get (n)),s,*size = n);
+ /* get more data from the net */
+ if (!tcp_getdata (stream)) fs_give ((void **) &ret);
+ /* special case of newline broken by buffer */
+ else if ((c == '\015') && (*stream->iptr == '\012')) {
+ stream->iptr++; /* eat the line feed */
+ stream->ictr--;
+ ret[*size = --n] = '\0'; /* tie off string with null */
+ }
+ else *contd = LONGT; /* continuation needed */
+ return ret;
+}
+
+/* TCP/IP receive buffer
+ * Accepts: TCP/IP stream
+ * size in bytes
+ * buffer to read into
+ * Returns: T if success, NIL otherwise
+ */
+
+long tcp_getbuffer (TCPSTREAM *stream,unsigned long size,char *s)
+{
+ unsigned long n;
+ /* make sure socket still alive */
+ if (stream->tcpsi == INVALID_SOCKET) return NIL;
+ /* can transfer bytes from buffer? */
+ if (n = min (size,stream->ictr)) {
+ memcpy (s,stream->iptr,n); /* yes, slurp as much as we can from it */
+ s += n; /* update pointer */
+ stream->iptr +=n;
+ size -= n; /* update # of bytes to do */
+ stream->ictr -=n;
+ }
+ if (size) {
+ int i;
+ fd_set fds;
+ struct timeval tmo;
+ time_t tc,t = time (0);
+ blocknotify_t bn=(blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL);
+ (*bn) (BLOCK_TCPREAD,NIL);
+ while (size > 0) { /* until request satisfied */
+ time_t tl = time (0);
+ if (tcpdebug) mm_log ("Reading TCP buffer",TCPDEBUG);
+ FD_ZERO (&fds); /* initialize selection vector */
+ FD_SET (stream->tcpsi,&fds);/* set bit in selection vector */
+ tmo.tv_sec = ttmo_read;
+ tmo.tv_usec = 0;
+ /* block and read */
+ switch ((stream->tcpsi == stream->tcpso) ?
+ select (stream->tcpsi+1,&fds,0,0,
+ ttmo_read ? &tmo : (struct timeval *) 0) : 1) {
+ case SOCKET_ERROR: /* error */
+ if (WSAGetLastError () != WSAEINTR) return tcp_abort (stream);
+ break;
+ case 0: /* timeout */
+ tc = time (0);
+ if (tmoh && ((*tmoh) (tc - t,tc - tl))) break;
+ return tcp_abort (stream);
+ default:
+ if (stream->tcpsi == stream->tcpso)
+ while (((i = recv (stream->tcpsi,s,(int) min (maxposint,size),0)) ==
+ SOCKET_ERROR) && (WSAGetLastError () == WSAEINTR));
+ else while (((i = read (stream->tcpsi,s,(int) min (maxposint,size))) <
+ 0) && (errno == EINTR));
+ switch (i) {
+ case SOCKET_ERROR: /* error */
+ case 0: /* no data read */
+ return tcp_abort (stream);
+ default:
+ s += i; /* point at new place to write */
+ size -= i; /* reduce byte count */
+ if (tcpdebug) mm_log ("Successfully read TCP buffer",TCPDEBUG);
+ }
+ }
+ }
+ (*bn) (BLOCK_NONE,NIL);
+ }
+ *s = '\0'; /* tie off string */
+ return T;
+}
+
+/* TCP/IP receive data
+ * Accepts: TCP/IP stream
+ * Returns: T if success, NIL otherwise
+ */
+
+long tcp_getdata (TCPSTREAM *stream)
+{
+ struct timeval tmo;
+ int i;
+ fd_set fds;
+ time_t tc,t = time (0);
+ blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL);
+ FD_ZERO (&fds); /* initialize selection vector */
+ if (stream->tcpsi == INVALID_SOCKET) return NIL;
+ (*bn) (BLOCK_TCPREAD,NIL);
+ tmo.tv_sec = ttmo_read;
+ tmo.tv_usec = 0;
+ while (stream->ictr < 1) { /* if nothing in the buffer */
+ time_t tl = time (0);
+ if (tcpdebug) mm_log ("Reading TCP data",TCPDEBUG);
+ FD_SET (stream->tcpsi,&fds);/* set bit in selection vector */
+ /* block and read */
+ switch ((stream->tcpsi == stream->tcpso) ?
+ select (stream->tcpsi+1,&fds,0,0,
+ ttmo_read ? &tmo : (struct timeval *) 0) : 1) {
+ case SOCKET_ERROR: /* error */
+ if (WSAGetLastError () != WSAEINTR) return tcp_abort (stream);
+ break;
+ case 0: /* timeout */
+ tc = time (0);
+ if (tmoh && ((*tmoh) (tc - t,tc - tl))) break;
+ return tcp_abort (stream);
+ default:
+ if (stream->tcpsi == stream->tcpso)
+ while (((i = recv (stream->tcpsi,stream->ibuf,BUFLEN,0)) ==
+ SOCKET_ERROR) && (WSAGetLastError () == WSAEINTR));
+ else while (((i = read (stream->tcpsi,stream->ibuf,BUFLEN)) < 0) &&
+ (errno == EINTR));
+ switch (i) {
+ case SOCKET_ERROR: /* error */
+ case 0: /* no data read */
+ return tcp_abort (stream);
+ default:
+ stream->ictr = i; /* set new byte count */
+ /* point at TCP buffer */
+ stream->iptr = stream->ibuf;
+ if (tcpdebug) mm_log ("Successfully read TCP data",TCPDEBUG);
+ }
+ }
+ }
+ (*bn) (BLOCK_NONE,NIL);
+ return T;
+}
+
+/* TCP/IP send string as record
+ * Accepts: TCP/IP stream
+ * string pointer
+ * Returns: T if success else NIL
+ */
+
+long tcp_soutr (TCPSTREAM *stream,char *string)
+{
+ return tcp_sout (stream,string,(unsigned long) strlen (string));
+}
+
+
+/* TCP/IP send string
+ * Accepts: TCP/IP stream
+ * string pointer
+ * byte count
+ * Returns: T if success else NIL
+ */
+
+long tcp_sout (TCPSTREAM *stream,char *string,unsigned long size)
+{
+ int i;
+ struct timeval tmo;
+ fd_set fds;
+ time_t tc,t = time (0);
+ blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL);
+ tmo.tv_sec = ttmo_write;
+ tmo.tv_usec = 0;
+ FD_ZERO (&fds); /* initialize selection vector */
+ if (stream->tcpso == INVALID_SOCKET) return NIL;
+ (*bn) (BLOCK_TCPWRITE,NIL);
+ while (size > 0) { /* until request satisfied */
+ time_t tl = time (0);
+ if (tcpdebug) mm_log ("Writing to TCP",TCPDEBUG);
+ FD_SET (stream->tcpso,&fds);/* set bit in selection vector */
+ /* block and write */
+ switch ((stream->tcpsi == stream->tcpso) ?
+ select (stream->tcpso+1,NULL,&fds,NULL,
+ tmo.tv_sec ? &tmo : (struct timeval *) 0) : 1) {
+ case SOCKET_ERROR: /* error */
+ if (WSAGetLastError () != WSAEINTR) return tcp_abort (stream);
+ break;
+ case 0: /* timeout */
+ tc = time (0);
+ if (tmoh && ((*tmoh) (tc - t,tc - tl))) break;
+ return tcp_abort (stream);
+ default:
+ if (stream->tcpsi == stream->tcpso)
+ while (((i = send (stream->tcpso,string,
+ (int) min (size,TCPMAXSEND),0)) == SOCKET_ERROR) &&
+ (WSAGetLastError () == WSAEINTR));
+ else while (((i = write (stream->tcpso,string,
+ min (size,TCPMAXSEND))) < 0) &&
+ (errno == EINTR));
+ if (i == SOCKET_ERROR) return tcp_abort (stream);
+ size -= i; /* count this size */
+ if (tcpdebug) mm_log ("successfully wrote to TCP",TCPDEBUG);
+ string += i;
+ }
+ }
+ (*bn) (BLOCK_NONE,NIL);
+ return T; /* all done */
+}
+
+
+/* TCP/IP close
+ * Accepts: TCP/IP stream
+ */
+
+void tcp_close (TCPSTREAM *stream)
+{
+ tcp_abort (stream); /* nuke the sockets */
+ /* flush host names */
+ if (stream->host) fs_give ((void **) &stream->host);
+ if (stream->remotehost) fs_give ((void **) &stream->remotehost);
+ if (stream->localhost) fs_give ((void **) &stream->localhost);
+ fs_give ((void **) &stream); /* flush the stream */
+}
+
+
+/* TCP/IP abort sockets
+ * Accepts: TCP/IP stream
+ * Returns: NIL, always
+ */
+
+long tcp_abort (TCPSTREAM *stream)
+{
+ if (stream->tcpsi != stream->tcpso) tcp_close_socket (&stream->tcpso);
+ else stream->tcpso = INVALID_SOCKET;
+ return tcp_close_socket (&stream->tcpsi);
+}
+
+
+/* TCP/IP abort stream
+ * Accepts: WinSock socket
+ * Returns: NIL, always
+ */
+
+long tcp_close_socket (SOCKET *sock)
+{
+ blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL);
+ /* something to close? */
+ if (sock && (*sock != INVALID_SOCKET)) {
+ (*bn) (BLOCK_TCPCLOSE,NIL);
+ closesocket (*sock); /* WinSock socket close */
+ *sock = INVALID_SOCKET;
+ (*bn) (BLOCK_NONE,NIL);
+ wsa_sock_open--; /* drop this socket */
+ }
+ /* no more open streams? */
+ if (wsa_initted && !wsa_sock_open) {
+ mm_log ("Winsock cleanup",NIL);
+ wsa_initted = 0; /* no more sockets, so... */
+ WSACleanup (); /* free up resources until needed */
+ }
+ return NIL;
+}
+
+/* TCP/IP get host name
+ * Accepts: TCP/IP stream
+ * Returns: host name for this stream
+ */
+
+char *tcp_host (TCPSTREAM *stream)
+{
+ return stream->host; /* use tcp_remotehost() if want guarantees */
+}
+
+
+/* TCP/IP get remote host name
+ * Accepts: TCP/IP stream
+ * Returns: host name for this stream
+ */
+
+char *tcp_remotehost (TCPSTREAM *stream)
+{
+ if (!stream->remotehost) {
+ struct sockaddr_in sin;
+ int sinlen = sizeof (struct sockaddr_in);
+ stream->remotehost = /* get socket's peer name */
+ ((getpeername (stream->tcpsi,(struct sockaddr *) &sin,&sinlen) ==
+ SOCKET_ERROR) || (sinlen <= 0)) ?
+ cpystr (stream->host) : tcp_name (&sin,NIL);
+ }
+ return stream->remotehost;
+}
+
+
+/* TCP/IP return port for this stream
+ * Accepts: TCP/IP stream
+ * Returns: port number for this stream
+ */
+
+unsigned long tcp_port (TCPSTREAM *stream)
+{
+ return stream->port; /* return port number */
+}
+
+
+/* TCP/IP get local host name
+ * Accepts: TCP/IP stream
+ * Returns: local host name
+ */
+
+char *tcp_localhost (TCPSTREAM *stream)
+{
+ if (!stream->localhost) {
+ struct sockaddr_in sin;
+ int sinlen = sizeof (struct sockaddr_in);
+ stream->localhost = /* get socket's name */
+ ((stream->port & 0xffff000) ||
+ ((getsockname (stream->tcpsi,(struct sockaddr *) &sin,&sinlen) ==
+ SOCKET_ERROR) || (sinlen <= 0))) ?
+ cpystr (mylocalhost ()) : tcp_name (&sin,NIL);
+ }
+ return stream->localhost; /* return local host name */
+}
+
+/* TCP/IP get client host address (server calls only)
+ * Returns: client host address
+ */
+
+char *tcp_clientaddr ()
+{
+ if (!myClientAddr) {
+ struct sockaddr_in sin;
+ int sinlen = sizeof (struct sockaddr_in);
+ myClientAddr = /* get stdin's peer name */
+ ((getpeername (0,(struct sockaddr *) &sin,&sinlen) == SOCKET_ERROR) ||
+ (sinlen <= 0)) ? cpystr ("UNKNOWN") : cpystr (inet_ntoa (sin.sin_addr));
+ }
+ return myClientAddr;
+}
+
+
+/* TCP/IP get client host name (server calls only)
+ * Returns: client host name
+ */
+
+char *tcp_clienthost ()
+{
+ if (!myClientHost) {
+ struct sockaddr_in sin;
+ int sinlen = sizeof (struct sockaddr_in);
+ myClientHost = /* get stdin's peer name */
+ ((getpeername (0,(struct sockaddr *) &sin,&sinlen) == SOCKET_ERROR) ||
+ (sinlen <= 0)) ? cpystr ("UNKNOWN") : tcp_name (&sin,T);
+ }
+ return myClientHost;
+}
+
+/* TCP/IP get server host address (server calls only)
+ * Returns: server host address
+ */
+
+char *tcp_serveraddr ()
+{
+ if (!myServerAddr) {
+ struct sockaddr_in sin;
+ int sinlen = sizeof (struct sockaddr_in);
+ myServerAddr = /* get stdin's peer name */
+ ((getsockname (0,(struct sockaddr *) &sin,&sinlen) == SOCKET_ERROR) ||
+ (sinlen <= 0)) ? cpystr ("UNKNOWN") : cpystr (inet_ntoa (sin.sin_addr));
+ }
+ return myServerAddr;
+}
+
+
+/* TCP/IP get server host name (server calls only)
+ * Returns: server host name
+ */
+
+static long myServerPort = -1;
+
+char *tcp_serverhost ()
+{
+ if (!myServerHost) {
+ struct sockaddr_in sin;
+ int sinlen = sizeof (struct sockaddr_in);
+ if (!wsa_initted++) { /* init Windows Sockets */
+ WSADATA wsock;
+ if (WSAStartup (WSA_VERSION,&wsock)) {
+ wsa_initted = 0;
+ return "random-pc"; /* try again later? */
+ }
+ }
+ /* get stdin's name */
+ if ((getsockname (0,(struct sockaddr *) &sin,&sinlen) == SOCKET_ERROR) ||
+ (sinlen <= 0)) myServerHost = cpystr (mylocalhost ());
+ else {
+ myServerHost = tcp_name (&sin,NIL);
+ myServerPort = ntohs (sin.sin_port);
+ }
+ }
+ return myServerHost;
+}
+
+
+/* TCP/IP get server port number (server calls only)
+ * Returns: server port number
+ */
+
+long tcp_serverport ()
+{
+ if (!myServerHost) tcp_serverhost ();
+ return myServerPort;
+}
+
+/* TCP/IP return canonical form of host name
+ * Accepts: host name
+ * Returns: canonical form of host name
+ */
+
+char *tcp_canonical (char *name)
+{
+ char *ret,host[MAILTMPLEN];
+ struct hostent *he;
+ blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL);
+ /* look like domain literal? */
+ if (name[0] == '[' && name[strlen (name) - 1] == ']') return name;
+ (*bn) (BLOCK_DNSLOOKUP,NIL);
+ if (tcpdebug) {
+ sprintf (host,"DNS canonicalization %.80s",name);
+ mm_log (host,TCPDEBUG);
+ }
+ /* note that NT requires lowercase! */
+ ret = (he = gethostbyname (lcase (strcpy (host,name)))) ? he->h_name : name;
+ (*bn) (BLOCK_NONE,NIL);
+ if (tcpdebug) mm_log ("DNS canonicalization done",TCPDEBUG);
+ return ret;
+}
+
+
+/* TCP/IP return name from socket
+ * Accepts: socket
+ * verbose flag
+ * Returns: cpystr name
+ */
+
+char *tcp_name (struct sockaddr_in *sin,long flag)
+{
+ char *ret,*t,adr[MAILTMPLEN],tmp[MAILTMPLEN];
+ sprintf (ret = adr,"[%.80s]",inet_ntoa (sin->sin_addr));
+ if (allowreversedns) {
+ struct hostent *he;
+ blocknotify_t bn = (blocknotify_t)mail_parameters(NIL,GET_BLOCKNOTIFY,NIL);
+ void *data;
+ if (tcpdebug) {
+ sprintf (tmp,"Reverse DNS resolution %s",adr);
+ mm_log (tmp,TCPDEBUG);
+ }
+ (*bn) (BLOCK_DNSLOOKUP,NIL);/* quell alarms */
+ data = (*bn) (BLOCK_SENSITIVE,NIL);
+ /* translate address to name */
+ if (t = tcp_name_valid ((he = gethostbyaddr ((char *) &sin->sin_addr,
+ sizeof (struct in_addr),
+ sin->sin_family)) ?
+ (char *) he->h_name : NIL)) {
+ /* produce verbose form if needed */
+ if (flag) sprintf (ret = tmp,"%s %s",t,adr);
+ else ret = t;
+ }
+ (*bn) (BLOCK_NONSENSITIVE,data);
+ (*bn) (BLOCK_NONE,NIL); /* alarms OK now */
+ if (tcpdebug) mm_log ("Reverse DNS resolution done",TCPDEBUG);
+ }
+ return cpystr (ret);
+}
+
+/* Return my local host name
+ * Returns: my local host name
+ */
+
+char *mylocalhost (void)
+{
+ if (!myLocalHost) {
+ char tmp[MAILTMPLEN];
+ if (!wsa_initted++) { /* init Windows Sockets */
+ WSADATA wsock;
+ if (WSAStartup (WSA_VERSION,&wsock)) {
+ wsa_initted = 0;
+ return "random-pc"; /* try again later? */
+ }
+ }
+ myLocalHost = cpystr ((gethostname (tmp,MAILTMPLEN-1) == SOCKET_ERROR) ?
+ "random-pc" : tcp_canonical (tmp));
+ }
+ return myLocalHost;
+}
+
+
+/* Validate name
+ * Accepts: domain name
+ * Returns: T if valid, NIL otherwise
+ */
+
+char *tcp_name_valid (char *s)
+{
+ int c;
+ char *ret,*tail;
+ /* must be non-empty and not too long */
+ if ((ret = (s && *s) ? s : NIL) && (tail = ret + NETMAXHOST)) {
+ /* must be alnum, dot, or hyphen */
+ while ((c = *s++) && (s <= tail) &&
+ (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) ||
+ ((c >= '0') && (c <= '9')) || (c == '-') || (c == '.')));
+ if (c) ret = NIL;
+ }
+ return ret;
+}
diff --git a/imap/src/osdep/wce/tcp_wce.h b/imap/src/osdep/wce/tcp_wce.h
new file mode 100644
index 00000000..4019af10
--- /dev/null
+++ b/imap/src/osdep/wce/tcp_wce.h
@@ -0,0 +1,46 @@
+/* ========================================================================
+ * 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: Winsock TCP/IP routines
+ *
+ * Author: Mike Seibel from Unix version by Mark Crispin
+ * Computing & Communications
+ * University of Washington
+ * Administration Building, AG-44
+ * Seattle, WA 98195
+ * Internet: MRC@CAC.Washington.EDU
+ *
+ * Date: 11 April 1989
+ * Last Edited: 30 August 2006
+ */
+
+/* TCP input buffer -- must be large enough to prevent overflow */
+
+#define BUFLEN 8192
+
+
+/* TCP I/O stream (must be before osdep.h is included) */
+
+#define TCPSTREAM struct tcp_stream
+TCPSTREAM {
+ char *host; /* host name */
+ char *remotehost; /* remote host name */
+ unsigned long port; /* port number */
+ char *localhost; /* local host name */
+ int tcpsi; /* input tcp socket */
+ int tcpso; /* output tcp socket */
+ long ictr; /* input counter */
+ char *iptr; /* input pointer */
+ char ibuf[BUFLEN]; /* input buffer */
+};