Patch #1516912: improve Modules support for OpenVMS.
diff --git a/Modules/bz2module.c b/Modules/bz2module.c
index 8f4e1d8..5800bff 100644
--- a/Modules/bz2module.c
+++ b/Modules/bz2module.c
@@ -1311,7 +1311,11 @@
 				break;
 
 			case 'U':
+#ifdef __VMS
+				self->f_univ_newline = 0;
+#else
 				self->f_univ_newline = 1;
+#endif
 				break;
 
 			default:
diff --git a/Modules/cryptmodule.c b/Modules/cryptmodule.c
index 050a356..6377f84 100644
--- a/Modules/cryptmodule.c
+++ b/Modules/cryptmodule.c
@@ -5,6 +5,9 @@
 
 #include <sys/types.h>
 
+#ifdef __VMS
+#include <openssl/des.h>
+#endif
 
 /* Module crypt */
 
@@ -12,7 +15,9 @@
 static PyObject *crypt_crypt(PyObject *self, PyObject *args)
 {
 	char *word, *salt; 
+#ifndef __VMS
 	extern char * crypt(const char *, const char *);
+#endif
 
 	if (!PyArg_ParseTuple(args, "ss:crypt", &word, &salt)) {
 		return NULL;
diff --git a/Modules/dlmodule.c b/Modules/dlmodule.c
index 899ad86..5622ed9 100644
--- a/Modules/dlmodule.c
+++ b/Modules/dlmodule.c
@@ -5,6 +5,10 @@
 
 #include <dlfcn.h>
 
+#ifdef __VMS
+#include <unistd.h>
+#endif
+
 #ifndef RTLD_LAZY
 #define RTLD_LAZY 1
 #endif
@@ -186,6 +190,24 @@
 		PyErr_SetString(Dlerror, dlerror());
 		return NULL;
 	}
+#ifdef __VMS
+	/*   Under OpenVMS dlopen doesn't do any check, just save the name
+	 * for later use, so we have to check if the file is readable,
+	 * the name can be a logical or a file from SYS$SHARE.
+	 */
+	if (access(name, R_OK)) {
+		char fname[strlen(name) + 20];
+		strcpy(fname, "SYS$SHARE:");
+		strcat(fname, name);
+		strcat(fname, ".EXE");
+		if (access(fname, R_OK)) {
+			dlclose(handle);
+			PyErr_SetString(Dlerror,
+				"File not found or protection violation");
+			return NULL;
+		}
+	}
+#endif
 	return newdlobject(handle);
 }
 
diff --git a/Modules/fpectlmodule.c b/Modules/fpectlmodule.c
index c6d4f77..74354ba 100644
--- a/Modules/fpectlmodule.c
+++ b/Modules/fpectlmodule.c
@@ -70,6 +70,10 @@
 
 #if defined(__FreeBSD__)
 #  include <ieeefp.h>
+#elif defined(__VMS)
+#define __NEW_STARLET
+#include <starlet.h>
+#include <ieeedef.h>
 #endif
 
 #ifndef WANT_SIGFPE_HANDLER
@@ -190,6 +194,19 @@
 
 /*-- DEC ALPHA VMS --------------------------------------------------------*/
 #elif defined(__ALPHA) && defined(__VMS)
+	IEEE clrmsk;
+	IEEE setmsk;
+	clrmsk.ieee$q_flags =
+		IEEE$M_TRAP_ENABLE_UNF |  IEEE$M_TRAP_ENABLE_INE |
+		 IEEE$M_MAP_UMZ;
+	setmsk.ieee$q_flags =
+		IEEE$M_TRAP_ENABLE_INV | IEEE$M_TRAP_ENABLE_DZE |
+		IEEE$M_TRAP_ENABLE_OVF;
+	sys$ieee_set_fp_control(&clrmsk, &setmsk, 0);
+	PyOS_setsig(SIGFPE, handler);
+
+/*-- HP IA64 VMS --------------------------------------------------------*/
+#elif defined(__ia64) && defined(__VMS)
     PyOS_setsig(SIGFPE, handler);
 
 /*-- Cray Unicos ----------------------------------------------------------*/
@@ -244,6 +261,14 @@
 #ifdef __FreeBSD__
     fpresetsticky(fpgetsticky());
     fpsetmask(0);
+#elif defined(__VMS)
+	IEEE clrmsk;
+	 clrmsk.ieee$q_flags =
+		IEEE$M_TRAP_ENABLE_UNF |  IEEE$M_TRAP_ENABLE_INE |
+		IEEE$M_MAP_UMZ | IEEE$M_TRAP_ENABLE_INV |
+		IEEE$M_TRAP_ENABLE_DZE | IEEE$M_TRAP_ENABLE_OVF |
+		IEEE$M_INHERIT;
+	sys$ieee_set_fp_control(&clrmsk, 0, 0);
 #else
     fputs("Operation not implemented\n", stderr);
 #endif
diff --git a/Modules/getpath.c b/Modules/getpath.c
index 8eba730..78bfaf9 100644
--- a/Modules/getpath.c
+++ b/Modules/getpath.c
@@ -97,19 +97,19 @@
 
 
 #ifndef VERSION
-#if defined(__VMS)
-#define VERSION "2_1"
-#else
 #define VERSION "2.1"
 #endif
-#endif
 
 #ifndef VPATH
 #define VPATH "."
 #endif
 
 #ifndef PREFIX
-#define PREFIX "/usr/local"
+#  ifdef __VMS
+#    define PREFIX ""
+#  else
+#    define PREFIX "/usr/local"
+#  endif
 #endif
 
 #ifndef EXEC_PREFIX
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index d8cf40e..e118237 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -7882,6 +7882,42 @@
 }
 #endif
 
+#ifdef __VMS
+/* Use openssl random routine */
+#include <openssl/rand.h>
+PyDoc_STRVAR(vms_urandom__doc__,
+"urandom(n) -> str\n\n\
+Return a string of n random bytes suitable for cryptographic use.");
+
+static PyObject*
+vms_urandom(PyObject *self, PyObject *args)
+{
+	int howMany;
+	PyObject* result;
+
+	/* Read arguments */
+	if (! PyArg_ParseTuple(args, "i:urandom", &howMany))
+		return NULL;
+	if (howMany < 0)
+		return PyErr_Format(PyExc_ValueError,
+				    "negative argument not allowed");
+
+	/* Allocate bytes */
+	result = PyString_FromStringAndSize(NULL, howMany);
+	if (result != NULL) {
+		/* Get random data */
+		if (RAND_pseudo_bytes((unsigned char*)
+				      PyString_AS_STRING(result),
+				      howMany) < 0) {
+			Py_DECREF(result);
+			return PyErr_Format(PyExc_ValueError,
+					    "RAND_pseudo_bytes");
+		}
+	}
+	return result;
+}
+#endif
+
 static PyMethodDef posix_methods[] = {
 	{"access",	posix_access, METH_VARARGS, posix_access__doc__},
 #ifdef HAVE_TTYNAME
@@ -8175,6 +8211,9 @@
  #ifdef MS_WINDOWS
  	{"urandom", win32_urandom, METH_VARARGS, win32_urandom__doc__},
  #endif
+ #ifdef __VMS
+ 	{"urandom", vms_urandom, METH_VARARGS, vms_urandom__doc__},
+ #endif
 	{NULL,		NULL}		 /* Sentinel */
 };
 
diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c
index ef67888..9eaae84 100644
--- a/Modules/selectmodule.c
+++ b/Modules/selectmodule.c
@@ -46,14 +46,14 @@
 #endif
 
 #ifdef MS_WINDOWS
-#include <winsock.h>
+#  include <winsock.h>
 #else
-#ifdef __BEOS__
-#include <net/socket.h>
-#define SOCKET int
-#else
-#define SOCKET int
-#endif
+#  define SOCKET int
+#  ifdef __BEOS__
+#    include <net/socket.h>
+#  elif defined(__VMS)
+#    include <socket.h>
+#  endif
 #endif
 
 
@@ -668,7 +668,7 @@
 that are ready.\n\
 \n\
 *** IMPORTANT NOTICE ***\n\
-On Windows, only sockets are supported; on Unix, all file descriptors.");
+On Windows and OpenVMS, only sockets are supported; on Unix, all file descriptors.");
 
 static PyMethodDef select_methods[] = {
     {"select",	select_select, METH_VARARGS, select_doc},
@@ -682,7 +682,7 @@
 "This module supports asynchronous I/O on multiple file descriptors.\n\
 \n\
 *** IMPORTANT NOTICE ***\n\
-On Windows, only sockets are supported; on Unix, all file descriptors.");
+On Windows and OpenVMS, only sockets are supported; on Unix, all file descriptors.");
 
 PyMODINIT_FUNC
 initselect(void)
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index 2d3fc56..11b184e 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -161,7 +161,8 @@
    (this includes the getaddrinfo emulation) protect access with a lock. */
 #if defined(WITH_THREAD) && (defined(__APPLE__) || \
     (defined(__FreeBSD__) && __FreeBSD_version+0 < 503000) || \
-    defined(__OpenBSD__) || defined(__NetBSD__) || !defined(HAVE_GETADDRINFO))
+    defined(__OpenBSD__) || defined(__NetBSD__) || \
+    defined(__VMS) || !defined(HAVE_GETADDRINFO))
 #define USE_GETADDRINFO_LOCK
 #endif
 
@@ -186,15 +187,8 @@
 #endif
 
 #if defined(__VMS)
-#if ! defined(_SOCKADDR_LEN)
-#   ifdef getaddrinfo
-#      undef getaddrinfo
-#   endif
-#  include "TCPIP_IOCTL_ROUTINE"
-#else
 #  include <ioctl.h>
 #endif
-#endif
 
 #if defined(PYOS_OS2)
 # define  INCL_DOS
@@ -363,11 +357,6 @@
 #define SOCKETCLOSE close
 #endif
 
-#ifdef __VMS
-/* TCP/IP Services for VMS uses a maximum send/revc buffer length of 65535 */
-#define SEGMENT_SIZE 65535
-#endif
-
 #if defined(HAVE_BLUETOOTH_H) || defined(HAVE_BLUETOOTH_BLUETOOTH_H)
 #define USE_BLUETOOTH 1
 #if defined(__FreeBSD__)
@@ -386,6 +375,11 @@
 #endif
 #endif
 
+#ifdef __VMS
+/* TCP/IP Services for VMS uses a maximum send/recv buffer length */
+#define SEGMENT_SIZE (32 * 1024 -1)
+#endif
+
 /*
  * Constants for getnameinfo()
  */
@@ -620,6 +614,30 @@
 	return NULL;
 }
 
+#ifdef __VMS
+/* Function to send in segments */
+static int
+sendsegmented(int sock_fd, char *buf, int len, int flags)
+{
+	int n = 0;
+	int remaining = len;
+
+	while (remaining > 0) {
+		unsigned int segment;
+
+		segment = (remaining >= SEGMENT_SIZE ? SEGMENT_SIZE : remaining);
+		n = send(sock_fd, buf, segment, flags);
+		if (n < 0) {
+			return n;
+		}
+		remaining -= segment;
+		buf += segment;
+	} /* end while */
+
+	return len;
+}
+#endif
+
 /* Function to perform the setting of socket blocking mode
    internally. block = (1 | 0). */
 static int
@@ -644,8 +662,8 @@
 	ioctl(s->sock_fd, FIONBIO, (caddr_t)&block, sizeof(block));
 #elif defined(__VMS)
 	block = !block;
-	ioctl(s->sock_fd, FIONBIO, (char *)&block);
-#else  /* !PYOS_OS2 && !_VMS */
+	ioctl(s->sock_fd, FIONBIO, (unsigned int *)&block);
+#else  /* !PYOS_OS2 && !__VMS */
 	delay_flag = fcntl(s->sock_fd, F_GETFL, 0);
 	if (block)
 		delay_flag &= (~O_NONBLOCK);
@@ -1725,6 +1743,8 @@
 		return PyInt_FromLong(flag);
 	}
 #ifdef __VMS
+	/* socklen_t is unsigned so no negative test is needed,
+	   test buflen == 0 is previously done */
 	if (buflen > 1024) {
 #else
 	if (buflen <= 0 || buflen > 1024) {
@@ -2498,9 +2518,6 @@
 {
 	char *buf;
 	int len, n = 0, flags = 0, timeout;
-#ifdef __VMS
-	int send_length;
-#endif
 
 	if (!PyArg_ParseTuple(args, "s#|i:send", &buf, &len, &flags))
 		return NULL;
@@ -2508,11 +2525,14 @@
 	if (!IS_SELECTABLE(s))
 		return select_error();
 
-#ifndef __VMS
 	Py_BEGIN_ALLOW_THREADS
 	timeout = internal_select(s, 1);
 	if (!timeout)
+#ifdef __VMS
+		n = sendsegmented(s->sock_fd, buf, len, flags);
+#else
 		n = send(s->sock_fd, buf, len, flags);
+#endif
 	Py_END_ALLOW_THREADS
 
 	if (timeout) {
@@ -2521,36 +2541,6 @@
 	}
 	if (n < 0)
 		return s->errorhandler();
-#else
-	/* Divide packet into smaller segments for	*/
-	/*  TCP/IP Services for OpenVMS			*/
-	send_length = len;
-	while (send_length != 0) {
-		unsigned int segment;
-
-		segment = send_length / SEGMENT_SIZE;
-		if (segment != 0) {
-			segment = SEGMENT_SIZE;
-		}
-		else {
-			segment = send_length;
-		}
-		Py_BEGIN_ALLOW_THREADS
-		timeout = internal_select(s, 1);
-		if (!timeout)
-			n = send(s->sock_fd, buf, segment, flags);
-		Py_END_ALLOW_THREADS
-		if (timeout) {
-			PyErr_SetString(socket_timeout, "timed out");
-			return NULL;
-		}
-		if (n < 0) {
-			return s->errorhandler();
-		}
-		send_length -= segment;
-		buf += segment;
-	} /* end while */
-#endif /* !__VMS */
 	return PyInt_FromLong((long)n);
 }
 
@@ -2581,7 +2571,11 @@
 		timeout = internal_select(s, 1);
 		if (timeout)
 			break;
+#ifdef __VMS
+		n = sendsegmented(s->sock_fd, buf, len, flags);
+#else
 		n = send(s->sock_fd, buf, len, flags);
+#endif
 		if (n < 0)
 			break;
 		buf += n;