From 2a30cd0ef0673710a1a4e188b50c11026c403b2a Mon Sep 17 00:00:00 2001 From: Neal Norwitz Date: Mon, 10 Jul 2006 01:18:57 +0000 Subject: [PATCH] Patch #1516912: improve Modules support for OpenVMS. --- Misc/NEWS | 2 + Modules/bz2module.c | 4 ++ Modules/cryptmodule.c | 5 +++ Modules/dlmodule.c | 22 ++++++++++ Modules/fpectlmodule.c | 25 ++++++++++++ Modules/getpath.c | 10 ++--- Modules/posixmodule.c | 39 ++++++++++++++++++ Modules/selectmodule.c | 18 ++++----- Modules/socketmodule.c | 92 ++++++++++++++++++++---------------------- 9 files changed, 154 insertions(+), 63 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS index 33ca2b6db35..a3f2b723f0f 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -108,6 +108,8 @@ Extension Modules - Bug #1296433: parsing XML with a non-default encoding and a CharacterDataHandler could crash the interpreter in pyexpat. +- Patch #1516912: improve Modules support for OpenVMS. + Build ----- diff --git a/Modules/bz2module.c b/Modules/bz2module.c index 8f4e1d88f7f..5800bff86e9 100644 --- a/Modules/bz2module.c +++ b/Modules/bz2module.c @@ -1311,7 +1311,11 @@ BZ2File_init(BZ2FileObject *self, PyObject *args, PyObject *kwargs) 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 050a3569122..6377f8430be 100644 --- a/Modules/cryptmodule.c +++ b/Modules/cryptmodule.c @@ -5,6 +5,9 @@ #include +#ifdef __VMS +#include +#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 899ad866cfc..5622ed9e738 100644 --- a/Modules/dlmodule.c +++ b/Modules/dlmodule.c @@ -5,6 +5,10 @@ #include +#ifdef __VMS +#include +#endif + #ifndef RTLD_LAZY #define RTLD_LAZY 1 #endif @@ -186,6 +190,24 @@ dl_open(PyObject *self, PyObject *args) 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 c6d4f77c231..74354bac52d 100644 --- a/Modules/fpectlmodule.c +++ b/Modules/fpectlmodule.c @@ -70,6 +70,10 @@ extern "C" { #if defined(__FreeBSD__) # include +#elif defined(__VMS) +#define __NEW_STARLET +#include +#include #endif #ifndef WANT_SIGFPE_HANDLER @@ -190,6 +194,19 @@ static void fpe_reset(Sigfunc *handler) /*-- 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 @@ static PyObject *turnoff_sigfpe(PyObject *self,PyObject *args) #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 8eba730ccfe..78bfaf97658 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 d8cf40ed7c0..e1182378eeb 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -7882,6 +7882,42 @@ win32_urandom(PyObject *self, PyObject *args) } #endif +#ifdef __VMS +/* Use openssl random routine */ +#include +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 @@ -8174,6 +8210,9 @@ static PyMethodDef posix_methods[] = { #endif #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 ef678881222..9eaae8488c9 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -46,14 +46,14 @@ extern void bzero(void *, int); #endif #ifdef MS_WINDOWS -#include +# include #else -#ifdef __BEOS__ -#include -#define SOCKET int -#else -#define SOCKET int -#endif +# define SOCKET int +# ifdef __BEOS__ +# include +# elif defined(__VMS) +# include +# endif #endif @@ -668,7 +668,7 @@ arguments; each contains the subset of the corresponding file descriptors\n\ 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 @@ PyDoc_STRVAR(module_doc, "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 2d3fc564c56..11b184ed0a5 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -161,7 +161,8 @@ shutdown(how) -- shut down traffic in one or both directions\n\ (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 @@ shutdown(how) -- shut down traffic in one or both directions\n\ #endif #if defined(__VMS) -#if ! defined(_SOCKADDR_LEN) -# ifdef getaddrinfo -# undef getaddrinfo -# endif -# include "TCPIP_IOCTL_ROUTINE" -#else # include #endif -#endif #if defined(PYOS_OS2) # define INCL_DOS @@ -363,11 +357,6 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); #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 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); #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 @@ set_gaierror(int error) 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 @@ internal_setblocking(PySocketSockObject *s, int block) 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 @@ sock_getsockopt(PySocketSockObject *s, PyObject *args) 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 @@ sock_send(PySocketSockObject *s, PyObject *args) { 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 @@ sock_send(PySocketSockObject *s, PyObject *args) 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 @@ sock_send(PySocketSockObject *s, PyObject *args) } 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 @@ sock_sendall(PySocketSockObject *s, PyObject *args) 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;