summaryrefslogtreecommitdiff
path: root/imap/src/osdep/vms
diff options
context:
space:
mode:
Diffstat (limited to 'imap/src/osdep/vms')
-rw-r--r--imap/src/osdep/vms/build.com99
-rw-r--r--imap/src/osdep/vms/clean.com26
-rw-r--r--imap/src/osdep/vms/dummy.h43
-rw-r--r--imap/src/osdep/vms/dummyvms.c295
-rw-r--r--imap/src/osdep/vms/env_vms.c174
-rw-r--r--imap/src/osdep/vms/env_vms.h60
-rw-r--r--imap/src/osdep/vms/fs_vms.c62
-rw-r--r--imap/src/osdep/vms/ftl_vms.c38
-rw-r--r--imap/src/osdep/vms/link.opt1
-rw-r--r--imap/src/osdep/vms/link_mnt.opt1
-rw-r--r--imap/src/osdep/vms/link_nlb.opt1
-rw-r--r--imap/src/osdep/vms/linkage.c37
-rw-r--r--imap/src/osdep/vms/linkage.h36
-rw-r--r--imap/src/osdep/vms/nl_vms.c92
-rw-r--r--imap/src/osdep/vms/os_vms.c76
-rw-r--r--imap/src/osdep/vms/os_vms.h52
-rw-r--r--imap/src/osdep/vms/pmatch.c89
-rw-r--r--imap/src/osdep/vms/tcp_vms.h52
-rw-r--r--imap/src/osdep/vms/tcp_vmsl.c378
-rw-r--r--imap/src/osdep/vms/tcp_vmsm.c479
-rw-r--r--imap/src/osdep/vms/tcp_vmsn.c222
21 files changed, 2313 insertions, 0 deletions
diff --git a/imap/src/osdep/vms/build.com b/imap/src/osdep/vms/build.com
new file mode 100644
index 00000000..aedbcc82
--- /dev/null
+++ b/imap/src/osdep/vms/build.com
@@ -0,0 +1,99 @@
+$! ========================================================================
+$! 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 build for VMS
+$!
+$! 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: 2 August 1994
+$! Last Edited: 30 August 2006
+$!
+$! Change this to your local timezone. This value is the number of minutes
+$! east of UTC (formerly known as GMT). Sample values: -300 (US east coast),
+$! -480 (US west coast), 540 (Japan), 60 (western Europe).
+$! VAX C's HELP information says that you should be able to use gmtime(), but
+$! it returns 0 for the struct. ftime(), you ask? It, too, returns 0 for a
+$! timezone. Nothing sucks like a VAX!
+$!
+$ CC_TIMEZONE=-480
+$!
+$! CC options
+$!
+$ CC_PREF = "/OPTIMIZE/INCLUDE=[]"
+$ CC_PREF = CC_PREF + "/DEFINE=net_getbuffer=NET_GETBUF"
+$ CC_PREF = CC_PREF + "/DEFINE=LOCALTIMEZONE='CC_TIMEZONE'"
+$!
+$! Determine TCP type
+$!
+$ TCP_TYPE = "VMSN" ! default to none
+$ IF F$LOCATE("MULTINET", P1) .LT. F$LENGTH(P1)
+$ THEN
+$ DEFINE SYS MULTINET_ROOT:[MULTINET.INCLUDE.SYS],sys$library
+$ DEFINE NETINET MULTINET_ROOT:[MULTINET.INCLUDE.NETINET]
+$ DEFINE ARPA MULTINET_ROOT:[MULTINET.INCLUDE.ARPA]
+$ TCP_TYPE = "VMSM" ! Multinet
+$ LINK_OPT = ",LINK_MNT/OPTION"
+$ ENDIF
+$ IF F$LOCATE("NETLIB", P1) .LT. F$LENGTH(P1)
+$ THEN
+$ DEFINE SYS SYS$LIBRARY: ! normal .H location
+$ DEFINE NETINET SYS$LIBRARY:
+$ DEFINE ARPA SYS$LIBRARY:
+$ LINK_OPT = ",LINK_NLB/OPTION"
+$ TCP_TYPE = "VMSL" ! NETLIB
+$ ENDIF
+$ IF TCP_TYPE .EQS. "VMSN"
+$ THEN
+$ DEFINE SYS SYS$LIBRARY: ! normal .H location
+$ DEFINE NETINET SYS$LIBRARY:
+$ DEFINE ARPA SYS$LIBRARY:
+$ LINK_OPT = ""
+$ ENDIF
+$!
+$ COPY TCP_'TCP_TYPE'.C TCP_VMS.C;
+$!
+$ COPY OS_VMS.H OSDEP.H;
+$ SET VERIFY
+$ CC'CC_PREF' MAIL
+$ CC'CC_PREF' IMAP4R1
+$ CC'CC_PREF' SMTP
+$ CC'CC_PREF' NNTP
+$ CC'CC_PREF' POP3
+$ CC'CC_PREF' DUMMYVMS
+$ CC'CC_PREF' RFC822
+$ CC'CC_PREF' MISC
+$ CC'CC_PREF' OS_VMS
+$ CC'CC_PREF' SMANAGER
+$ CC'CC_PREF' FLSTRING
+$ CC'CC_PREF' NEWSRC
+$ CC'CC_PREF' NETMSG
+$ CC'CC_PREF' UTF8
+$ CC'CC_PREF' UTF8AUX
+$ CC'CC_PREF' MTEST
+$ CC'CC_PREF' MAILUTIL
+$!
+$ LINK MTEST,OS_VMS,MAIL,IMAP4R1,SMTP,NNTP,POP3,DUMMYVMS,RFC822,MISC,UTF8,-
+ UTF8AUX,SMANAGER,FLSTRING,NEWSRC,NETMSG,-
+ SYS$INPUT:/OPTION'LINK_OPT',LINK/OPTION
+PSECT=_CTYPE_,NOWRT
+$ LINK MAILUTIL,OS_VMS,MAIL,IMAP4R1,SMTP,NNTP,POP3,DUMMYVMS,RFC822,MISC,UTF8,-
+ UTF8AUX,SMANAGER,FLSTRING,NEWSRC,NETMSG,-
+ SYS$INPUT:/OPTION'LINK_OPT',LINK/OPTION
+PSECT=_CTYPE_,NOWRT
+$ SET NOVERIFY
+$ EXIT
diff --git a/imap/src/osdep/vms/clean.com b/imap/src/osdep/vms/clean.com
new file mode 100644
index 00000000..98df0db5
--- /dev/null
+++ b/imap/src/osdep/vms/clean.com
@@ -0,0 +1,26 @@
+$! ========================================================================
+$! 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 cleanup for VMS
+$!
+$! 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: 14 June 1995
+$! Last Edited: 30 August 2006
+$!
+$ DELETE *.OBJ;*,OSDEP.*;*,TCP_VMS.C;*,MTEST.EXE;*,MAILUTIL.EXE;*
diff --git a/imap/src/osdep/vms/dummy.h b/imap/src/osdep/vms/dummy.h
new file mode 100644
index 00000000..32650e06
--- /dev/null
+++ b/imap/src/osdep/vms/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/vms/dummyvms.c b/imap/src/osdep/vms/dummyvms.c
new file mode 100644
index 00000000..cfcb45d0
--- /dev/null
+++ b/imap/src/osdep/vms/dummyvms.c
@@ -0,0 +1,295 @@
+/* ========================================================================
+ * 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 VMS
+ *
+ * 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 "mail.h"
+#include "osdep.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};
+
+/* Dummy validate mailbox
+ * Accepts: mailbox name
+ * Returns: our driver if name is valid, NIL otherwise
+ */
+
+DRIVER *dummy_valid (char *name)
+{
+ char tmp[MAILTMPLEN];
+ /* must be valid local mailbox */
+ return (name && *name && (*name != '{') && !compare_cstring (name,"INBOX")) ?
+ &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 NIL;
+}
+
+/* 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
+ * reference
+ * pattern to search
+ */
+
+void dummy_lsub (MAILSTREAM *stream,char *ref,char *pat)
+{
+ /* return silently */
+}
+
+/* Dummy create mailbox
+ * Accepts: mail stream
+ * mailbox name to create
+ * driver type to use
+ * 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
+ * append callback function
+ * data for callback
+ * 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/vms/env_vms.c b/imap/src/osdep/vms/env_vms.c
new file mode 100644
index 00000000..56b7a223
--- /dev/null
+++ b/imap/src/osdep/vms/env_vms.c
@@ -0,0 +1,174 @@
+/* ========================================================================
+ * 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: VMS 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: 2 August 1994
+ * Last Edited: 30 August 2006
+ */
+
+
+static char *myUserName = NIL; /* user name */
+static char *myLocalHost = NIL; /* local host name */
+static char *myHomeDir = NIL; /* home directory name */
+static char *myNewsrc = NIL; /* newsrc file name */
+
+#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 SET_USERNAME:
+ myUserName = cpystr ((char *) value);
+ case GET_USERNAME:
+ ret = (void *) myUserName;
+ 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;
+ }
+ return ret;
+}
+
+/* Write current time
+ * Accepts: destination string
+ * optional format of day-of-week prefix
+ * format of date and time
+ */
+
+static void do_date (char *date,char *prefix,char *fmt)
+{
+ time_t tn = time (0);
+ struct tm *t = localtime (&tn);
+ int zone = LOCALTIMEZONE + (t->tm_isdst ? 60 : 0);
+ 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);
+}
+
+
+/* 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");
+}
+
+
+/* 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");
+}
+
+/* Return my user name
+ * Returns: my user name
+ */
+
+char *myusername ()
+{
+ struct stat sbuf;
+ char tmp[MAILTMPLEN];
+
+ if (!myUserName) { /* get user name if don't have it yet */
+ myUserName = cpystr (cuserid (NIL));
+ myHomeDir = cpystr ("SYS$LOGIN");
+ }
+ return myUserName;
+}
+
+
+/* Return my home directory name
+ * Returns: my home directory name
+ */
+
+char *myhomedir ()
+{
+ if (!myHomeDir) myusername ();/* initialize if first time */
+ return myHomeDir;
+}
+
+
+/* Determine default prototype stream to user
+ * Accepts: type (NIL for create, T for append)
+ * Returns: default prototype stream
+ */
+
+MAILSTREAM *default_proto (long type)
+{
+ return NIL; /* no default prototype */
+}
+
+/* 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/vms/env_vms.h b/imap/src/osdep/vms/env_vms.h
new file mode 100644
index 00000000..59160a06
--- /dev/null
+++ b/imap/src/osdep/vms/env_vms.h
@@ -0,0 +1,60 @@
+/* ========================================================================
+ * 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: VMS 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: 2 August 1994
+ * Last Edited: 30 August 2006
+ */
+
+
+#define SUBSCRIPTIONFILE(t) sprintf (t,"%s\\SUBSCRIPTIONS.TXT",myhomedir ())
+#define SUBSCRIPTIONTEMP(t) sprintf (t,"%s\\SUBSCRIPTIONS.TMP",myhomedir ())
+
+/* Function prototypes */
+
+#include "env.h"
+
+char *myusername ();
+
+
+/* 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/vms/fs_vms.c b/imap/src/osdep/vms/fs_vms.c
new file mode 100644
index 00000000..03908328
--- /dev/null
+++ b/imap/src/osdep/vms/fs_vms.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/vms/ftl_vms.c b/imap/src/osdep/vms/ftl_vms.c
new file mode 100644
index 00000000..9e65ef55
--- /dev/null
+++ b/imap/src/osdep/vms/ftl_vms.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/vms/link.opt b/imap/src/osdep/vms/link.opt
new file mode 100644
index 00000000..0f454490
--- /dev/null
+++ b/imap/src/osdep/vms/link.opt
@@ -0,0 +1 @@
+SYS$SHARE:VAXCRTL/SHARE
diff --git a/imap/src/osdep/vms/link_mnt.opt b/imap/src/osdep/vms/link_mnt.opt
new file mode 100644
index 00000000..5eb99104
--- /dev/null
+++ b/imap/src/osdep/vms/link_mnt.opt
@@ -0,0 +1 @@
+MULTINET:MULTINET_SOCKET_LIBRARY/SHARE
diff --git a/imap/src/osdep/vms/link_nlb.opt b/imap/src/osdep/vms/link_nlb.opt
new file mode 100644
index 00000000..883d2859
--- /dev/null
+++ b/imap/src/osdep/vms/link_nlb.opt
@@ -0,0 +1 @@
+NETLIB_SHR/SHARE
diff --git a/imap/src/osdep/vms/linkage.c b/imap/src/osdep/vms/linkage.c
new file mode 100644
index 00000000..14490a0c
--- /dev/null
+++ b/imap/src/osdep/vms/linkage.c
@@ -0,0 +1,37 @@
+/* ========================================================================
+ * Copyright 1988-2007 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: Default driver linkage
+ *
+ * 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: 13 June 1995
+ * Last Edited: 23 May 2007
+ */
+
+ mail_link (&imapdriver); /* link in the imap driver */
+ mail_link (&nntpdriver); /* link in the nntp driver */
+ mail_link (&pop3driver); /* link in the pop3 driver */
+ mail_link (&dummydriver); /* link in the dummy driver */
+ auth_link (&auth_ext); /* link in the ext authenticator */
+ auth_link (&auth_md5); /* link in the md5 authenticator */
+ auth_link (&auth_pla); /* link in the plain authenticator */
+ auth_link (&auth_log); /* link in the log authenticator */
+ mail_versioncheck (CCLIENTVERSION); /* validate version */
diff --git a/imap/src/osdep/vms/linkage.h b/imap/src/osdep/vms/linkage.h
new file mode 100644
index 00000000..7e0eccfa
--- /dev/null
+++ b/imap/src/osdep/vms/linkage.h
@@ -0,0 +1,36 @@
+/* ========================================================================
+ * 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: Default driver linkage
+ *
+ * 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: 13 June 1995
+ * Last Edited: 30 August 2006
+ */
+
+extern DRIVER imapdriver;
+extern DRIVER nntpdriver;
+extern DRIVER pop3driver;
+extern DRIVER dummydriver;
+extern AUTHENTICATOR auth_ext;
+extern AUTHENTICATOR auth_log;
+extern AUTHENTICATOR auth_md5;
+extern AUTHENTICATOR auth_pla;
diff --git a/imap/src/osdep/vms/nl_vms.c b/imap/src/osdep/vms/nl_vms.c
new file mode 100644
index 00000000..b2d5616a
--- /dev/null
+++ b/imap/src/osdep/vms/nl_vms.c
@@ -0,0 +1,92 @@
+/* ========================================================================
+ * 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: UNIX/VMS 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)
+{
+ long i = srcl * 2,j;
+ unsigned char c,*d = src;
+ if (*dst) { /* candidate destination provided? */
+ /* count NLs if doesn't fit worst-case */
+ if (i > *dstl) for (i = j = srcl; j; --j) if (*d++ == '\012') i++;
+ /* still too small, must reset destination */
+ if (i > *dstl) fs_give ((void **) dst);
+ }
+ /* make a new buffer if needed */
+ if (!*dst) *dst = (char *) fs_get ((*dstl = i) + 1);
+ d = *dst; /* destination string */
+ if (srcl) do { /* main copy loop */
+ if ((c = *src++) < '\016') {
+ /* prepend CR to LF */
+ if (c == '\012') *d++ = '\015';
+ /* unlikely CR */
+ else if ((c == '\015') && (srcl > 1) && (*src == '\012')) {
+ *d++ = c; /* copy the CR */
+ c = *src++; /* grab the LF */
+ --srcl; /* adjust the count */
+ }
+ }
+ *d++ = c; /* copy character */
+ } while (--srcl);
+ *d = '\0'; /* tie off destination */
+ return d - *dst; /* return length */
+}
+
+/* Length of string after strcrlfcpy applied
+ * Accepts: source string
+ * Returns: length of string
+ */
+
+unsigned long strcrlflen (STRING *s)
+{
+ unsigned long pos = GETPOS (s);
+ unsigned long i = SIZE (s);
+ unsigned long j = i;
+ while (j--) switch (SNX (s)) {/* search for newlines */
+ case '\015': /* unlikely carriage return */
+ if (j && (CHR (s) == '\012')) {
+ SNX (s); /* eat the line feed */
+ j--;
+ }
+ break;
+ case '\012': /* line feed? */
+ i++;
+ default: /* ordinary chararacter */
+ break;
+ }
+ SETPOS (s,pos); /* restore old position */
+ return i;
+}
diff --git a/imap/src/osdep/vms/os_vms.c b/imap/src/osdep/vms/os_vms.c
new file mode 100644
index 00000000..cd333ba9
--- /dev/null
+++ b/imap/src/osdep/vms/os_vms.c
@@ -0,0 +1,76 @@
+/* ========================================================================
+ * 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 -- VMS 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: 2 August 1994
+ * Last Edited: 30 August 2006
+ */
+
+#include "tcp_vms.h" /* must be before osdep includes tcp.h */
+#include "mail.h"
+#include "osdep.h"
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <errno.h>
+extern int errno; /* just in case */
+#include "misc.h"
+
+
+#include "fs_vms.c"
+#include "ftl_vms.c"
+#include "nl_vms.c"
+#include "env_vms.c"
+#include "tcp_vms.c"
+
+#define server_login(user,pass,authuser,argc,argv) NIL
+#define authserver_login(user,authuser,argc,argv) NIL
+#define myusername() "" /* dummy definition to prevent build errors */
+#define MD5ENABLE ""
+
+#include "auth_md5.c"
+#include "auth_pla.c"
+#include "auth_log.c"
+
+
+/* Emulator for UNIX getpass() call
+ * Accepts: prompt
+ * Returns: password
+ */
+
+#define PWDLEN 128 /* used by Linux */
+
+char *getpass (const char *prompt)
+{
+ char *s;
+ static char pwd[PWDLEN];
+ fputs (prompt,stdout);
+ fgets (pwd,PWDLEN-1,stdin);
+ if (s = strchr (pwd,'\n')) *s = '\0';
+ return pwd;
+}
diff --git a/imap/src/osdep/vms/os_vms.h b/imap/src/osdep/vms/os_vms.h
new file mode 100644
index 00000000..1da72f13
--- /dev/null
+++ b/imap/src/osdep/vms/os_vms.h
@@ -0,0 +1,52 @@
+/* ========================================================================
+ * Copyright 1988-2007 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 -- VMS 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: 2 August 1994
+ * Last Edited: 30 January 2007
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unixio.h>
+#include <file.h>
+#include <stat.h>
+
+#define L_SET SEEK_SET
+#define L_INCR SEEK_CUR
+#define L_XTND SEEK_END
+
+#include "env_vms.h"
+#include "fs.h"
+#include "ftl.h"
+#include "nl.h"
+#include "tcp.h"
+
+#define gethostid clock
+#define random rand
+#define unlink delete
+
+char *getpass (const char *prompt);
+
+#define strtok_r(a,b,c) strtok(a,b)
diff --git a/imap/src/osdep/vms/pmatch.c b/imap/src/osdep/vms/pmatch.c
new file mode 100644
index 00000000..95a0bb86
--- /dev/null
+++ b/imap/src/osdep/vms/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/vms/tcp_vms.h b/imap/src/osdep/vms/tcp_vms.h
new file mode 100644
index 00000000..ff747016
--- /dev/null
+++ b/imap/src/osdep/vms/tcp_vms.h
@@ -0,0 +1,52 @@
+/* ========================================================================
+ * 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: VMS TCP/IP 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
+ */
+
+
+/* TCP input buffer */
+
+#define BUFLEN 8192
+
+
+/* TCP I/O stream */
+
+#define TCPSTREAM struct tcp_stream
+TCPSTREAM {
+ char *host; /* host name */
+ unsigned long port; /* port number */
+ char *localhost; /* local host name */
+ int tcpsi; /* input socket */
+ int tcpso; /* output socket */
+ int ictr; /* input counter */
+ char *iptr; /* input pointer */
+ char ibuf[BUFLEN]; /* input buffer */
+};
+
+
+/* Local function prototypes */
+
+long tcp_abort (TCPSTREAM *stream);
diff --git a/imap/src/osdep/vms/tcp_vmsl.c b/imap/src/osdep/vms/tcp_vmsl.c
new file mode 100644
index 00000000..692c9212
--- /dev/null
+++ b/imap/src/osdep/vms/tcp_vmsl.c
@@ -0,0 +1,378 @@
+/* ========================================================================
+ * 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: VMS TCP/IP routines for Netlib.
+ *
+ * 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: 2 August 1994
+ * Last Edited: 13 January 2008
+ */
+
+/* Thanks to Yehavi Bourvine at The Hebrew University of Jerusalem who
+ contributed the original VMS code */
+
+#include <descrip.h>
+
+static char *tcp_getline_work (TCPSTREAM *stream,unsigned long *size,
+ long *contd);
+
+/* TCP/IP manipulate parameters
+ * Accepts: function code
+ * function-dependent value
+ * Returns: function-dependent return value
+ */
+
+void *tcp_parameters (long function,void *value)
+{
+ return NIL;
+}
+
+
+/* TCP/IP open
+ * Accepts: host name
+ * contact service name
+ * contact port number
+ * Returns: TCP/IP stream if success else NIL
+ */
+
+TCPSTREAM *tcp_open (char *host,char *service,unsigned long port)
+{
+ TCPSTREAM *stream = NIL;
+ unsigned long sock;
+ int status;
+ char tmp[MAILTMPLEN];
+ /* hostname to connect to */
+ struct dsc$descriptor HostDesc = { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };
+ port &= 0xffff; /* erase flags */
+ /* assign a local socket */
+ if (!((status = net_assign (&sock)) & 0x1)) {
+ sprintf (tmp,"Unable to assign to net, status=%d",status);
+ mm_log (tmp,ERROR);
+ return NIL;
+ }
+ if (!((status = net_bind (&sock,1)) & 0x1)) {
+ sprintf (tmp,"Unable to create local socket, status=%d",status);
+ mm_log (tmp,ERROR);
+ return NIL;
+ }
+ /* open connection */
+ HostDesc.dsc$w_length = strlen (host);
+ HostDesc.dsc$a_pointer = host;
+ if (!((status = tcp_connect (&sock,&HostDesc,port)) & 0x1)) {
+ sprintf (tmp,"Can't connect to %.80s,%lu: %s",host,port,strerror (errno));
+ mm_log (tmp,ERROR);
+ return NIL;
+ }
+ /* create TCP/IP stream */
+ stream = (TCPSTREAM *) fs_get (sizeof (TCPSTREAM));
+ stream->host = cpystr (host); /* copy official host name */
+ /* copy local host name */
+ stream->localhost = cpystr (mylocalhost ());
+ stream->port = port; /* copy port number */
+ /* init sockets */
+ stream->tcpsi = stream->tcpso = sock;
+ stream->ictr = 0; /* init input counter */
+ return stream; /* return success */
+}
+
+/* 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;
+}
+
+/* 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 *buffer)
+{
+ unsigned long n;
+ char *bufptr = buffer;
+ while (size > 0) { /* until request satisfied */
+ if (!tcp_getdata (stream)) return NIL;
+ n = min (size,stream->ictr);/* number of bytes to transfer */
+ /* do the copy */
+ memcpy (bufptr,stream->iptr,n);
+ bufptr += n; /* update pointer */
+ stream->iptr +=n;
+ size -= n; /* update # of bytes to do */
+ stream->ictr -=n;
+ }
+ bufptr[0] = '\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)
+{
+ char tmp[MAILTMPLEN];
+ int i,status;
+ /* Note: the doc says we need here dynamic descriptor, but we need static
+ * one... */
+ struct dsc$descriptor BufDesc = {BUFLEN,DSC$K_DTYPE_T,DSC$K_CLASS_S,
+ stream->ibuf};
+ static short iosb[4];
+ if (stream->tcpsi < 0) return NIL;
+ while (stream->ictr < 1) { /* if nothing in the buffer */
+ if (!((status = tcp_receive(&(stream->tcpsi), &BufDesc, iosb)) & 0x1)) {
+ sprintf (tmp,"Error reading from TcpIp/NETLIB, status=%d",status);
+ mm_log (tmp,ERROR);
+ return tcp_abort (stream);
+ }
+ if (iosb[1] > BUFLEN) i = BUFLEN;
+ else i = iosb[1];
+ if (i < 1) return tcp_abort (stream);
+ stream->ictr = i; /* set new byte count */
+ stream->iptr = stream->ibuf;/* point at TCP buffer */
+ }
+ 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 status;
+ struct dsc$descriptor_s BufDesc = {strlen(string),DSC$K_DTYPE_T,
+ DSC$K_CLASS_S,string };
+ /* 2 = Do not add \r\n */
+ return ((status = tcp_send (&(stream->tcpso),&BufDesc,2)) & 0x1) ? T :
+ tcp_abort (stream);
+}
+
+/* TCP/IP close
+ * Accepts: TCP/IP stream
+ */
+
+void tcp_close (TCPSTREAM *stream)
+{
+ tcp_abort (stream); /* nuke the stream */
+ /* flush host names */
+ fs_give ((void **) &stream->host);
+ fs_give ((void **) &stream->localhost);
+ fs_give ((void **) &stream); /* flush the stream */
+}
+
+
+/* TCP/IP abort stream
+ * Accepts: TCP/IP stream
+ * Returns: NIL always
+ */
+
+long tcp_abort (TCPSTREAM *stream)
+{
+ if (stream->tcpsi >= 0) { /* no-op if no socket */
+ /* nuke the socket */
+ tcp_disconnect (&(stream->tcpsi));
+ stream->tcpsi = stream->tcpso = -1;
+ }
+ 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; /* return host name */
+}
+
+
+/* TCP/IP get remote host name
+ * Accepts: TCP/IP stream
+ * Returns: host name for this stream
+ */
+
+char *tcp_remotehost (TCPSTREAM *stream)
+{
+ return stream->host; /* return host name */
+}
+
+
+/* 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)
+{
+ return stream->localhost; /* return local host name */
+}
+
+/* Return my local host name
+ * Returns: my local host name
+ */
+
+char *mylocalhost ()
+{
+ int status;
+ char tmp[MAILTMPLEN];
+ if (!myLocalHost) { /* have local host yet? */
+ /* receives local host name */
+ struct dsc$descriptor LocalhostDesc = {0,DSC$K_DTYPE_T,DSC$K_CLASS_D,NULL};
+ if (!((status = net_get_hostname (&LocalhostDesc)) & 0x1)) {
+ sprintf (tmp,"Can't get local hostname, status=%d",status);
+ mm_log (tmp,ERROR);
+ return "UNKNOWN";
+ }
+ strncpy (tmp,LocalhostDesc.dsc$a_pointer,LocalhostDesc.dsc$w_length);
+ tmp[LocalhostDesc.dsc$w_length] = '\0';
+ str$free1_dx (&LocalhostDesc);
+ myLocalHost = cpystr (tmp);
+ }
+ return myLocalHost;
+}
+
+/* TCP/IP return canonical form of host name
+ * Accepts: host name
+ * Returns: canonical form of host name
+ */
+
+char *tcp_canonical (char *name)
+{
+ return name;
+}
+
+
+/* TCP/IP get client host name (server calls only)
+ * Returns: client host name
+ */
+
+char *tcp_clienthost ()
+{
+ return "UNKNOWN";
+}
diff --git a/imap/src/osdep/vms/tcp_vmsm.c b/imap/src/osdep/vms/tcp_vmsm.c
new file mode 100644
index 00000000..bc9d9ca7
--- /dev/null
+++ b/imap/src/osdep/vms/tcp_vmsm.c
@@ -0,0 +1,479 @@
+/* ========================================================================
+ * 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: VMS TCP/IP routines for Multinet
+ *
+ * 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: 2 August 1994
+ * Last Edited: 13 January 2008
+ */
+
+
+static tcptimeout_t tmoh = NIL; /* TCP timeout handler routine */
+static long ttmo_read = 0; /* TCP timeouts, in seconds */
+static long ttmo_write = 0;
+
+static char *tcp_getline_work (TCPSTREAM *stream,unsigned long *size,
+ long *contd);
+
+/* 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;
+ }
+ return ret;
+}
+
+/* TCP/IP open
+ * Accepts: host name
+ * contact service name
+ * contact port number
+ * Returns: TCP/IP stream if success else NIL
+ */
+
+TCPSTREAM *tcp_open (char *host,char *service,unsigned long port)
+{
+ TCPSTREAM *stream = NIL;
+ int sock;
+ char *s;
+ struct sockaddr_in sin;
+ struct hostent *host_name;
+ char hostname[MAILTMPLEN];
+ char tmp[MAILTMPLEN];
+ struct protoent *pt = getprotobyname ("tcp");
+ struct servent *sv = NIL;
+ port &= 0xffff; /* erase flags */
+ if (service) { /* service specified? */
+ if (*service == '*') { /* yes, special alt driver kludge? */
+ sv = getservbyname (service + 1,"tcp");
+ }
+ else sv = getservbyname (service,"tcp");
+ }
+ /* user service name port */
+ if (sv) port = ntohs (sin.sin_port = sv->s_port);
+ /* copy port number in network format */
+ else sin.sin_port = htons (port);
+ /* The domain literal form is used (rather than simply the dotted decimal
+ as with other Unix programs) because it has to be a valid "host name"
+ in mailsystem terminology. */
+ /* look like domain literal? */
+ if (host[0] == '[' && host[(strlen (host))-1] == ']') {
+ strcpy (hostname,host+1); /* yes, copy number part */
+ hostname[(strlen (hostname))-1] = '\0';
+ if ((sin.sin_addr.s_addr = inet_addr (hostname)) != -1) {
+ sin.sin_family = AF_INET; /* family is always Internet */
+ strcpy (hostname,host); /* hostname is user's argument */
+ }
+ else {
+ sprintf (tmp,"Bad format domain-literal: %.80s",host);
+ mm_log (tmp,ERROR);
+ return NIL;
+ }
+ }
+
+ else { /* lookup host name, note that brain-dead Unix
+ requires lowercase! */
+ strcpy (hostname,host); /* in case host is in write-protected memory */
+ if ((host_name = gethostbyname (lcase (hostname)))) {
+ /* copy address type */
+ sin.sin_family = host_name->h_addrtype;
+ /* copy host name */
+ strcpy (hostname,host_name->h_name);
+ /* copy host addresses */
+ memcpy (&sin.sin_addr,host_name->h_addr,host_name->h_length);
+ }
+ else {
+ sprintf (tmp,"No such host as %.80s",host);
+ mm_log (tmp,ERROR);
+ return NIL;
+ }
+ }
+ /* get a TCP stream */
+ if ((sock = socket (sin.sin_family,SOCK_STREAM,pt ? pt->p_proto : 0)) < 0) {
+ sprintf (tmp,"Unable to create TCP socket: %s",strerror (errno));
+ mm_log (tmp,ERROR);
+ return NIL;
+ }
+#if 0
+ /* Maybe this test is necessary. It depends upon how VMS implements
+ * fd_set. UNIX-style fd_set needs it; Windows-style does not.
+ */
+ else if (sock >= FD_SETSIZE) {/* unselectable sockets are useless */
+ sprintf (tmp,"Unable to create selectable TCP socket (%d >= %d)",
+ sock,FD_SETSIZE);
+ close (sock);
+ return NIL;
+ }
+#endif
+ /* open connection */
+ if (connect (sock,(struct sockaddr *)&sin,sizeof (sin)) < 0) {
+ sprintf (tmp,"Can't connect to %.80s,%d: %s",hostname,port,
+ strerror (errno));
+ mm_log (tmp,ERROR);
+ return NIL;
+ }
+ /* create TCP/IP stream */
+ stream = (TCPSTREAM *) fs_get (sizeof (TCPSTREAM));
+ /* copy official host name */
+ stream->host = cpystr (hostname);
+ /* get local name */
+ gethostname (tmp,MAILTMPLEN-1);
+ stream->localhost = cpystr ((host_name = gethostbyname (tmp)) ?
+ host_name->h_name : tmp);
+ /* init sockets */
+ stream->port = port; /* port number */
+ stream->tcpsi = stream->tcpso = sock;
+ stream->ictr = 0; /* init input counter */
+ return stream; /* return success */
+}
+
+/* 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;
+}
+
+/* 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 *buffer)
+{
+ unsigned long n;
+ char *bufptr = buffer;
+ while (size > 0) { /* until request satisfied */
+ if (!tcp_getdata (stream)) return NIL;
+ n = min (size,stream->ictr);/* number of bytes to transfer */
+ /* do the copy */
+ memcpy (bufptr,stream->iptr,n);
+ bufptr += n; /* update pointer */
+ stream->iptr +=n;
+ size -= n; /* update # of bytes to do */
+ stream->ictr -=n;
+ }
+ bufptr[0] = '\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)
+{
+ int i;
+ fd_set fds,efds;
+ struct timeval tmo;
+ time_t t = time (0);
+ if (stream->tcpsi < 0) return NIL;
+ while (stream->ictr < 1) { /* if nothing in the buffer */
+ time_t tl = time (0); /* start of request */
+ tmo.tv_sec = ttmo_read; /* read timeout */
+ tmo.tv_usec = 0;
+ FD_ZERO (&fds); /* initialize selection vector */
+ FD_ZERO (&efds); /* handle errors too */
+ FD_SET (stream->tcpsi,&fds);/* set bit in selection vector */
+ FD_SET(stream->tcpsi,&efds);/* set bit in error selection vector */
+ errno = NIL; /* block and read */
+ while (((i = select (getdtablesize (),&fds,0,&efds,ttmo_read ? &tmo:0))<0)
+ && (errno == EINTR));
+ if (!i) { /* timeout? */
+ time_t tc = time (0);
+ if (tmoh && ((*tmoh) (tc - t,tc - tl))) continue;
+ else return tcp_abort (stream);
+ }
+ else if (i < 0) return tcp_abort (stream);
+ while (((i = socket_read (stream->tcpsi,stream->ibuf,BUFLEN)) < 0) &&
+ (errno == EINTR));
+ if (i < 1) return tcp_abort (stream);
+ stream->iptr = stream->ibuf;/* point at TCP buffer */
+ stream->ictr = i; /* set new byte count */
+ }
+ 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;
+ fd_set fds;
+ struct timeval tmo;
+ time_t t = time (0);
+ if (stream->tcpso < 0) return NIL;
+ while (size > 0) { /* until request satisfied */
+ time_t tl = time (0); /* start of request */
+ tmo.tv_sec = ttmo_write; /* write timeout */
+ tmo.tv_usec = 0;
+ FD_ZERO (&fds); /* initialize selection vector */
+ FD_SET (stream->tcpso,&fds);/* set bit in selection vector */
+ errno = NIL; /* block and write */
+ while (((i = select (getdtablesize (),0,&fds,0,ttmo_write ? &tmo : 0)) < 0)
+ && (errno == EINTR));
+ if (!i) { /* timeout? */
+ time_t tc = time (0);
+ if (tmoh && ((*tmoh) (tc - t,tc - tl))) continue;
+ else return tcp_abort (stream);
+ }
+ else if (i < 0) return tcp_abort (stream);
+ while (((i = socket_write (stream->tcpso,string,size)) < 0) &&
+ (errno == EINTR));
+ if (i < 0) return tcp_abort (stream);
+ size -= i; /* how much we sent */
+ string += i;
+ }
+ return T; /* all done */
+}
+
+/* TCP/IP close
+ * Accepts: TCP/IP stream
+ */
+
+void tcp_close (TCPSTREAM *stream)
+{
+ tcp_abort (stream); /* nuke the stream */
+ /* flush host names */
+ fs_give ((void **) &stream->host);
+ fs_give ((void **) &stream->localhost);
+ fs_give ((void **) &stream); /* flush the stream */
+}
+
+
+/* TCP/IP abort stream
+ * Accepts: TCP/IP stream
+ * Returns: NIL always
+ */
+
+long tcp_abort (TCPSTREAM *stream)
+{
+ int i;
+ if (stream->tcpsi >= 0) { /* no-op if no socket */
+ /* nuke the socket */
+ socket_close (stream->tcpsi);
+ if (stream->tcpsi != stream->tcpso) socket_close (stream->tcpso);
+ stream->tcpsi = stream->tcpso = -1;
+ }
+ 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; /* return host name */
+}
+
+
+/* TCP/IP get remote host name
+ * Accepts: TCP/IP stream
+ * Returns: host name for this stream
+ */
+
+char *tcp_remotehost (TCPSTREAM *stream)
+{
+ return stream->host; /* return host name */
+}
+
+
+/* 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)
+{
+ return stream->localhost; /* return local host name */
+}
+
+/* Return my local host name
+ * Returns: my local host name
+ */
+
+char *mylocalhost ()
+{
+ char tmp[MAILTMPLEN];
+ struct hostent *hn;
+ if (!myLocalHost) { /* have local host yet? */
+ gethostname(tmp,MAILTMPLEN);/* get local host name */
+ myLocalHost = cpystr ((hn = gethostbyname (tmp)) ? hn->h_name : tmp);
+ }
+ return myLocalHost;
+}
+
+
+/* TCP/IP return canonical form of host name
+ * Accepts: host name
+ * Returns: canonical form of host name
+ */
+
+char *tcp_canonical (char *name)
+{
+ char host[MAILTMPLEN];
+ struct hostent *he;
+ /* look like domain literal? */
+ if (name[0] == '[' && name[strlen (name) - 1] == ']') return name;
+ /* note that Unix requires lowercase! */
+ else return (he = gethostbyname (lcase (strcpy (host,name)))) ?
+ he->h_name : name;
+}
+
+
+/* TCP/IP get client host name (server calls only)
+ * Returns: client host name
+ */
+
+char *tcp_clienthost ()
+{
+ return "UNKNOWN";
+}
diff --git a/imap/src/osdep/vms/tcp_vmsn.c b/imap/src/osdep/vms/tcp_vmsn.c
new file mode 100644
index 00000000..4648e48d
--- /dev/null
+++ b/imap/src/osdep/vms/tcp_vmsn.c
@@ -0,0 +1,222 @@
+/* ========================================================================
+ * 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 VMS TCP/IP routines for non-TCP/IP systems
+ *
+ * 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: 2 August 1994
+ * Last Edited: 30 August 2006
+ */
+
+/* TCP/IP manipulate parameters
+ * Accepts: function code
+ * function-dependent value
+ * Returns: function-dependent return value
+ */
+
+void *tcp_parameters (long function,void *value)
+{
+ return NIL;
+}
+
+
+/* TCP/IP open
+ * Accepts: host name
+ * contact service name
+ * contact port number
+ * Returns: TCP/IP stream if success else NIL
+ */
+
+TCPSTREAM *tcp_open (char *host,char *service,unsigned long port)
+{
+ char tmp[MAILTMPLEN];
+ port &= 0xffff; /* erase flags */
+ if (port) sprintf (tmp,"Can't connect to %.80s,%d: no TCP",host,port);
+ else sprintf (tmp,"Can't connect to %.80s,%s: no TCP",host,service);
+ mm_log (tmp,ERROR);
+ return NIL;
+}
+
+
+/* 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;
+}
+
+/* TCP/IP receive line
+ * Accepts: TCP/IP stream
+ * Returns: text line string or NIL if failure
+ */
+
+char *tcp_getline (TCPSTREAM *stream)
+{
+ return NIL;
+}
+
+
+/* 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 *buffer)
+{
+ return NIL;
+}
+
+
+/* TCP/IP receive data
+ * Accepts: TCP/IP stream
+ * Returns: T if success, NIL otherwise
+ */
+
+long tcp_getdata (TCPSTREAM *stream)
+{
+ return NIL;
+}
+
+/* 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 NIL;
+}
+
+
+/* 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)
+{
+ return NIL;
+}
+
+
+/* TCP/IP close
+ * Accepts: TCP/IP stream
+ */
+
+void tcp_close (TCPSTREAM *stream)
+{
+}
+
+
+/* TCP/IP abort stream
+ * Accepts: TCP/IP stream
+ * Returns: NIL always
+ */
+
+long tcp_abort (TCPSTREAM *stream)
+{
+ return NIL;
+}
+
+/* TCP/IP get host name
+ * Accepts: TCP/IP stream
+ * Returns: host name for this stream
+ */
+
+char *tcp_host (TCPSTREAM *stream)
+{
+ return NIL;
+}
+
+
+/* TCP/IP get remote host name
+ * Accepts: TCP/IP stream
+ * Returns: host name for this stream
+ */
+
+char *tcp_remotehost (TCPSTREAM *stream)
+{
+ return NIL;
+}
+
+
+/* TCP/IP get local host name
+ * Accepts: TCP/IP stream
+ * Returns: local host name
+ */
+
+char *tcp_localhost (TCPSTREAM *stream)
+{
+ return NIL;
+}
+
+
+/* TCP/IP return port for this stream
+ * Accepts: TCP/IP stream
+ * Returns: port number for this stream
+ */
+
+unsigned long tcp_port (TCPSTREAM *stream)
+{
+ return 0xffffffff; /* return port number */
+}
+
+
+/* Return my local host name
+ * Returns: my local host name
+ */
+
+char *mylocalhost ()
+{
+ /* have local host yet? */
+ if (!myLocalHost) myLocalHost = cpystr (getenv ("SYS$NODE"));
+ return myLocalHost;
+}
+
+/* TCP/IP return canonical form of host name
+ * Accepts: host name
+ * Returns: canonical form of host name
+ */
+
+char *tcp_canonical (char *name)
+{
+ return name;
+}
+
+
+/* TCP/IP get client host name (server calls only)
+ * Returns: client host name
+ */
+
+char *tcp_clienthost ()
+{
+ return "UNKNOWN";
+}