summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin v. Löwis <martin@v.loewis.de>2002-12-06 12:48:53 (GMT)
committerMartin v. Löwis <martin@v.loewis.de>2002-12-06 12:48:53 (GMT)
commit79acb9edfa893b5072350c82fd0645d023b13b03 (patch)
tree7b9417700c6942124614f4639bfbea8ff5c68b9e
parent468742878f53bb0a9061e6b167b3150f341fdf1c (diff)
downloadcpython-79acb9edfa893b5072350c82fd0645d023b13b03.zip
cpython-79acb9edfa893b5072350c82fd0645d023b13b03.tar.gz
cpython-79acb9edfa893b5072350c82fd0645d023b13b03.tar.bz2
Patch #614055: Support OpenVMS.
-rw-r--r--Include/pyerrors.h3
-rw-r--r--Misc/ACKS1
-rw-r--r--Misc/NEWS2
-rw-r--r--Modules/_hotshot.c3
-rw-r--r--Modules/getbuildinfo.c58
-rw-r--r--Modules/getpath.c4
-rw-r--r--Modules/main.c57
-rw-r--r--Modules/posixmodule.c266
-rw-r--r--Modules/pwdmodule.c8
-rw-r--r--Modules/socketmodule.c107
-rw-r--r--Objects/stringobject.c6
-rw-r--r--Python/exceptions.c13
-rw-r--r--Python/import.c7
13 files changed, 528 insertions, 7 deletions
diff --git a/Include/pyerrors.h b/Include/pyerrors.h
index 8685849..1adc6ec 100644
--- a/Include/pyerrors.h
+++ b/Include/pyerrors.h
@@ -62,6 +62,9 @@ PyAPI_DATA(PyObject *) PyExc_ZeroDivisionError;
#ifdef MS_WINDOWS
PyAPI_DATA(PyObject *) PyExc_WindowsError;
#endif
+#ifdef __VMS
+extern DL_IMPORT(PyObject *) PyExc_VMSError;
+#endif
PyAPI_DATA(PyObject *) PyExc_MemoryErrorInst;
diff --git a/Misc/ACKS b/Misc/ACKS
index 281aeb2..3ef4d8a 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -405,6 +405,7 @@ Geoff Philbrick
Adrian Phillips
Christopher J. Phoenix
Neale Pickett
+Jean-François Piéronne
Dan Pierson
Martijn Pieters
François Pinard
diff --git a/Misc/NEWS b/Misc/NEWS
index 91fe049..0e883bb 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -826,6 +826,8 @@ C API
New platforms
-------------
+- OpenVMS is now supported.
+
- AtheOS is now supported.
- the EMX runtime environment on OS/2 is now supported.
diff --git a/Modules/_hotshot.c b/Modules/_hotshot.c
index 37879b9..53130d6 100644
--- a/Modules/_hotshot.c
+++ b/Modules/_hotshot.c
@@ -947,7 +947,8 @@ calibrate(void)
}
#endif
}
-#if defined(MS_WINDOWS) || defined(macintosh) || defined(PYOS_OS2)
+#if defined(MS_WINDOWS) || defined(macintosh) || defined(PYOS_OS2) || \
+ defined(__VMS)
rusage_diff = -1;
#else
{
diff --git a/Modules/getbuildinfo.c b/Modules/getbuildinfo.c
index b59d9a7..23b57c5 100644
--- a/Modules/getbuildinfo.c
+++ b/Modules/getbuildinfo.c
@@ -28,12 +28,70 @@
#define BUILD 0
#endif
+#ifdef __VMS
+# ifdef __DECC
+# pragma extern_model save
+# pragma extern_model strict_refdef
+extern long ctl$gl_imghdrbf;
+# pragma extern_model restore
+# endif
+
+# ifdef __ALPHA
+# define EIHD$L_IMGIDOFF 24
+# define EIHI$Q_LINKTIME 8
+# define _IMGIDOFF EIHD$L_IMGIDOFF
+# define _LINKTIME EIHI$Q_LINKTIME
+# else
+# define IHD$W_IMGIDOFF 6
+# define IHI$Q_LINKTIME 56
+# define _IMGIDOFF IHD$W_IMGIDOFF
+# define _LINKTIME IHI$Q_LINKTIME
+# endif /* __VMS */
+
+long*
+vms__get_linktime (void)
+{
+ long* al_imghdrbf;
+ unsigned short* aw_imgidoff;
+ unsigned short w_imgidoff;
+ long* aq_linktime;
+ unsigned char* ab_ihi;
+
+ al_imghdrbf = &ctl$gl_imghdrbf;
+
+ al_imghdrbf = (long *)*al_imghdrbf;
+ al_imghdrbf = (long *)*al_imghdrbf;
+
+ aw_imgidoff = (unsigned short *)
+ ((unsigned char *)al_imghdrbf + _IMGIDOFF);
+
+ w_imgidoff = *aw_imgidoff;
+
+ ab_ihi = (unsigned char *)al_imghdrbf + w_imgidoff;
+
+ aq_linktime = (long *) (ab_ihi + _LINKTIME);
+
+ return aq_linktime;
+} /* vms__get_linktime (void) */
+extern void vms__cvt_v2u_time (long * aq_vmstime, time_t * al_unixtime);
+ /* input , output */
+#endif /* __VMS */
+
const char *
Py_GetBuildInfo(void)
{
static char buildinfo[50];
+#ifdef __VMS
+ time_t l_unixtime;
+
+ vms__cvt_v2u_time(vms__get_linktime (), &l_unixtime );
+
+ memset(buildinfo, 0, 40);
+ sprintf(buildinfo, "#%d, %.24s", BUILD, ctime (&l_unixtime));
+#else
PyOS_snprintf(buildinfo, sizeof(buildinfo),
"#%d, %.20s, %.9s", BUILD, DATE, TIME);
+#endif
return buildinfo;
}
diff --git a/Modules/getpath.c b/Modules/getpath.c
index 1841c76b..ee97271 100644
--- a/Modules/getpath.c
+++ b/Modules/getpath.c
@@ -92,8 +92,12 @@
*/
#ifndef VERSION
+#if defined(__VMS)
+#define VERSION "2_1"
+#else
#define VERSION "2.1"
#endif
+#endif
#ifndef VPATH
#define VPATH "."
diff --git a/Modules/main.c b/Modules/main.c
index d480fba..2005f0b 100644
--- a/Modules/main.c
+++ b/Modules/main.c
@@ -4,6 +4,11 @@
#include "osdefs.h"
#include "compile.h" /* For CO_FUTURE_DIVISION */
+#ifdef __VMS
+extern int PyVMS_init(int* pvi_argc, char*** pvi_argv);
+extern PyObject* pyvms_gr_empty_string;
+#endif
+
#if defined(MS_WINDOWS) || defined(__CYGWIN__)
#include <fcntl.h>
#endif
@@ -98,7 +103,18 @@ usage(int exitcode, char* program)
fprintf(f, usage_3);
fprintf(f, usage_4, DELIM, DELIM, PYTHONHOMEHELP);
}
+#if defined(__VMS)
+ if (exitcode == 0) {
+ /* suppress 'error' message */
+ exit(1);
+ }
+ else {
+ /* STS$M_INHIB_MSG + SS$_ABORT */
+ exit(0x1000002c);
+ }
+#else
exit(exitcode);
+#endif
/*NOTREACHED*/
}
@@ -145,7 +161,12 @@ Py_Main(int argc, char **argv)
if ((fp = fopen(filename, "r")) == NULL) {
fprintf(stderr, "%s: can't open file '%s'\n",
argv[0], filename);
+#if defined(__VMS)
+ /* STS$M_INHIB_MSG + SS$_ABORT */
+ exit(0x1000002c);
+#else
exit(2);
+#endif
}
}
/* Skip option-processing if we are an applet */
@@ -338,14 +359,50 @@ Py_Main(int argc, char **argv)
#endif /* !MS_WINDOWS */
/* Leave stderr alone - it should be unbuffered anyway. */
}
+#ifdef __VMS
+ else {
+ setvbuf (stdout, (char *)NULL, _IOLBF, BUFSIZ);
+ }
+#endif /* __VMS */
Py_SetProgramName(argv[0]);
+#ifdef __VMS
+ PyVMS_init(&argc, &argv);
+#endif
Py_Initialize();
+#ifdef __VMS
+ /* create an empty string object */
+ pyvms_gr_empty_string = Py_BuildValue("s#", Py_None, (unsigned int)0);
+#endif
+
if (Py_VerboseFlag ||
(command == NULL && filename == NULL && stdin_is_interactive))
+#ifndef __VMS
fprintf(stderr, "Python %s on %s\n%s\n",
Py_GetVersion(), Py_GetPlatform(), COPYRIGHT);
+#else
+ fprintf(stderr, "Python %s on %s %s (%s_float)\n%s\n",
+ Py_GetVersion(), Py_GetPlatform(),
+# ifdef __ALPHA
+ "Alpha",
+# else
+ "VAX",
+# endif
+# if __IEEE_FLOAT
+ "T",
+# else
+# if __D_FLOAT
+ "D",
+# else
+# if __G_FLOAT
+ "G",
+# endif /* __G_FLOAT */
+# endif /* __D_FLOAT */
+# endif /* __IEEE_FLOAT */
+ COPYRIGHT); /* << @@ defined above in this file */
+/* Py_GetCopyright()); */
+#endif /* __VMS */
if (command != NULL) {
/* Backup _PyOS_optind and force sys.argv[0] = '-c' */
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index fd7f69f..61fc02d 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -16,6 +16,33 @@
#include "Python.h"
#include "structseq.h"
+#if defined(__VMS)
+# include <ctype.h> /* tolower() */
+# include <descrip.h> /* string descriptors */
+# include <dvidef.h> /* DVI$_name */
+# include <file.h> /* -> O_RDWR */
+# include <jpidef.h> /* JPI$_name */
+# include <lib$routines.h> /* LIB$name */
+# include <ots$routines.h> /* OTS$name */
+# include <ssdef.h> /* SS$_name */
+# include <unixio.h>
+# include <unixlib.h>
+# include <stat.h>
+/* ----- */
+/* DECC on Alpha does redefine these already */
+# ifndef shell$from_vms
+# define shell$from_vms(_p1_,_p2_,_p3_) decc$from_vms(_p1_,_p2_,_p3_)
+# endif
+# ifndef shell$translate_vms
+# define shell$translate_vms(_p1_) decc$translate_vms(_p1_)
+# endif
+# ifndef shell$to_vms
+# define shell$to_vms(_p1_,_p2_,_p3_,_p4_,_p5_) \
+ decc$to_vms(_p1_,_p2_,_p3_,_p4_,_p5_)
+# endif
+# include <wait.h> /* define wait() */
+#endif /* defined(__VMS) */
+
PyDoc_STRVAR(posix__doc__,
"This module provides access to operating system functionality that is\n\
standardized by the C Standard and the POSIX standard (a thinly\n\
@@ -94,8 +121,8 @@ corresponding Unix manual entries for more information on calls.");
#define HAVE_SYSTEM 1
#define HAVE_CWAIT 1
#else
-#if defined(PYOS_OS2) && defined(PYCC_GCC)
-/* Everything needed is defined in PC/os2emx/pyconfig.h */
+#if defined(PYOS_OS2) && defined(PYCC_GCC) || defined(__VMS)
+/* Everything needed is defined in PC/os2emx/pyconfig.h or vms/pyconfig.h */
#else /* all other compilers */
/* Unix functions that the configure script doesn't check for */
#define HAVE_EXECV 1
@@ -304,6 +331,198 @@ static char **environ;
extern char **environ;
#endif /* !_MSC_VER */
+#if defined(__VMS)
+static char psxmod_gt_psxpath[1026];
+
+static int
+psxmod_from_vms_action (char *spec)
+{
+ (void)strcpy(psxmod_gt_psxpath, spec);
+ return 1;
+}
+
+/* Return a dictionary corresponding to the VMS 'environment table' */
+static char* at_home = "HOME";
+static char* at_path = "PATH";
+
+static char psxmod_t_command [] = "SYS$COMMAND";
+/* add some values to provide a similar environment like POSIX */
+void
+psmmod_add_posix_env(PyObject *d)
+{
+ /* -------------------- */
+ struct dsc$descriptor_s r_device_name;
+ long l_devbufsiz;
+ long l_tt_page;
+ long l_item_code;
+ long l_status;
+ PyObject *o;
+ struct dsc$descriptor_s r_resultant_string;
+ char t_resultant_string[13]; /* enough space for username (12)+ '\0' */
+ char *at_resultant_string;
+ short int w_resultant_length;
+
+ /* set up string descriptor */
+ r_device_name.dsc$w_length = strlen(psxmod_t_command);
+ r_device_name.dsc$b_dtype = DSC$K_DTYPE_T;
+ r_device_name.dsc$b_class = DSC$K_CLASS_S;
+ r_device_name.dsc$a_pointer = &psxmod_t_command[0];
+
+ /* -------------------- */
+ /* COLUMNS = $getdvi("SYS$COMMAND","DEVBUFSIZ") */
+ l_item_code = DVI$_DEVBUFSIZ;
+ l_status = lib$getdvi(&l_item_code,
+ 0, /* [channel] */
+ &r_device_name,
+ &l_devbufsiz, /* integer-value */
+ 0, /* resultant_string */
+ 0); /* resultant_length */
+ if (l_status == SS$_NORMAL) {
+ /* create a string object here to comply with POSIX */
+
+ /* set up string descriptor */
+ r_resultant_string.dsc$w_length =
+ (sizeof(t_resultant_string) - 1); /* ommit '\0' at end */
+ r_resultant_string.dsc$b_dtype = DSC$K_DTYPE_T;
+ r_resultant_string.dsc$b_class = DSC$K_CLASS_S;
+ r_resultant_string.dsc$a_pointer = &t_resultant_string[0];
+
+ /* Convert Signed Integer to Decimal Text */
+ l_status = ots$cvt_l_ti(&l_devbufsiz, &r_resultant_string, 1,
+ 4, 0);
+ if (l_status == SS$_NORMAL) {
+ /* terminate string for 'C'-style */
+ t_resultant_string[sizeof(t_resultant_string)-1] = '\0';
+ /* string appears as: ' value' -- skip ' ' */
+ at_resultant_string = &t_resultant_string[0];
+ while ((*at_resultant_string == ' ' ) &&
+ (*at_resultant_string != '\0')) {
+ at_resultant_string++; /* skip prefix spaces */
+ }
+
+ o = Py_BuildValue("s", at_resultant_string);
+ if (o != NULL) {
+ (void) PyDict_SetItemString(d, "COLUMNS", o);
+ Py_DECREF(o);
+ }
+ } /* (l_status = ots$cvt_l_ti() == SS$_NORMAL) */
+ } /* (l_status = lib$getdvi(DVI$_DEVBUFSIZ) == SS$_NORMAL) */
+ /* LINES = $getdvi("SYS$COMMAND","TT_PAGE") */
+ l_item_code = DVI$_TT_PAGE;
+ l_status = lib$getdvi(&l_item_code,
+ 0, /* [channel] */
+ &r_device_name,
+ &l_tt_page, /* integer-value */
+ 0, /* resultant_string */
+ 0); /* resultant_length */
+ if (l_status == SS$_NORMAL) {
+ /* create a string object here to comply with POSIX */
+
+ /* set up string descriptor */
+ r_resultant_string.dsc$w_length =
+ (sizeof(t_resultant_string) - 1); /* ommit '\0' at end */
+ r_resultant_string.dsc$b_dtype = DSC$K_DTYPE_T;
+ r_resultant_string.dsc$b_class = DSC$K_CLASS_S;
+ r_resultant_string.dsc$a_pointer = &t_resultant_string[0];
+
+ /* Convert Signed Integer to Decimal Text */
+ l_status = ots$cvt_l_ti(&l_tt_page, &r_resultant_string,
+ 1, 4, 0);
+ if (l_status == SS$_NORMAL) {
+ /* terminate string for 'C'-style */
+ t_resultant_string[sizeof(t_resultant_string)-1] = '\0';
+ /* string appears as: ' value' -- skip ' ' */
+ at_resultant_string = &t_resultant_string[0];
+ while ((*at_resultant_string == ' ' ) &&
+ (*at_resultant_string != '\0')) {
+ at_resultant_string++; /* skip prefix spaces */
+ }
+
+ o = Py_BuildValue("s", at_resultant_string);
+ if (o != NULL) {
+ (void)PyDict_SetItemString(d, "LINES", o);
+ Py_DECREF(o);
+ }
+ } /* (l_status = ots$cvt_l_ti() == SS$_NORMAL) */
+ } /* (l_status = lib$getdvi(DVI$_TT_PAGE) == SS$_NORMAL) */
+ /* else -- ignore error */
+
+ /* LOGNAME = $getjpi(0,"USERNAME") */
+ l_item_code = JPI$_USERNAME;
+
+ /* set up string descriptor */
+ r_resultant_string.dsc$w_length =
+ (sizeof(t_resultant_string) - 1); /* ommit '\0' at end */
+ r_resultant_string.dsc$b_dtype = DSC$K_DTYPE_T;
+ r_resultant_string.dsc$b_class = DSC$K_CLASS_S;
+ r_resultant_string.dsc$a_pointer = &t_resultant_string[0];
+
+ l_status = lib$getjpi(&l_item_code, 0, 0, 0,
+ &r_resultant_string, &w_resultant_length);
+ if (l_status == SS$_NORMAL){
+ t_resultant_string[w_resultant_length] = '\0';
+
+ /* remove any trailing spaces by replacing 1st one with '\0' */
+ at_resultant_string = &t_resultant_string[0];
+ while ((*at_resultant_string != ' ' ) &&
+ (*at_resultant_string != '\0')) {
+ /* lowercase for compatibility with POSIX */
+ *at_resultant_string = tolower(*at_resultant_string);
+ at_resultant_string++; /* skip non-blank */
+ }
+ *at_resultant_string = '\0'; /* terminate */
+
+ o = Py_BuildValue("s", &t_resultant_string[0]);
+ if (o != NULL) {
+ (void) PyDict_SetItemString(d, "LOGNAME", o);
+ (void) PyDict_SetItemString(d, "USERNAME", o);
+ Py_DECREF(o);
+ }
+ } /* (l_status == SS$_NORMAL) */
+
+ /* OS = "OpenVMS" */
+ o = PyString_FromString ("OpenVMS");
+ if (o != NULL) {
+ (void)PyDict_SetItemString(d, "OS", o);
+ Py_DECREF(o);
+ }
+}
+
+/* @@ posix env:
+COLUMNS=80 $ write sys$output f$getdvi("SYS$COMMAND","DEVBUFSIZ")
+LINES=47 $ write sys$output f$getdvi("SYS$COMMAND","TT_PAGE")
+LOGNAME=zessin $ write sys$output f$edit(f$getjpi(0,"username"), -
+ "collapse,lowercase")
+OS=OpenVMS
+PS1=HERE $
+
+TZ=CET-1:00CET DST,M3.5.0/2:00,M10.5.0/3:00
+ $ write sys$output f$trnlnm("POSIX$DEFAULT_TZ")
+ "CET-1:00CET DST-2:00,M3.5.0/2:00,M10.5.0/3:00"
+ $ write sys$output f$trnlnm("UCX$TZ")
+ "MET-1MET_DST-2,M3.5.0/2,M10.5.0/3"
+PAGER=more
+TERM=vt300_series
+SHELL=/bin/sh
+HOME=/dka100/user/zessin
+_=/bin/env
+
+>>> for v in os.environ.items():
+... print v
+...
+('HOME', '/user_here/zessin')
+('COLUMNS', '80')
+('LINES', '24')
+('PATH', '/python_disk/python/python-1_5_2/vms')
+('OS', 'OpenVMS')
+('USER', 'ZESSIN')
+('LOGNAME', 'zessin')
+('TERM', 'vt300-80')
+('USERNAME', 'zessin')
+>>>
+*/
+#endif /* __VMS */
+
static PyObject *
convertenviron(void)
{
@@ -330,7 +549,19 @@ convertenviron(void)
PyErr_Clear();
continue;
}
+#if defined(__VMS)
+ if ((strncmp(at_home, *e, sizeof(at_home)) == 0) ||
+ (strncmp(at_path, *e, sizeof(at_path)) == 0)) {
+ (void)shell$from_vms(p+1, psxmod_from_vms_action, 0);
+ /* 0 = no wildcard expansion */
+ v = PyString_FromString(psxmod_gt_psxpath);
+ }
+ else {
+ v = PyString_FromString(p+1);
+ }
+#else
v = PyString_FromString(p+1);
+#endif
if (v == NULL) {
PyErr_Clear();
Py_DECREF(k);
@@ -343,6 +574,9 @@ convertenviron(void)
Py_DECREF(k);
Py_DECREF(v);
}
+#if defined(__VMS)
+ psmmod_add_posix_env(d);
+#endif /* defined(__VMS) */
#if defined(PYOS_OS2)
{
APIRET rc;
@@ -895,7 +1129,11 @@ _pystat_fromstructstat(STRUCT_STAT st)
static PyObject *
posix_do_stat(PyObject *self, PyObject *args,
char *format,
+#ifdef __VMS
+ int (*statfunc)(const char *, STRUCT_STAT *, ...),
+#else
int (*statfunc)(const char *, STRUCT_STAT *),
+#endif
char *wformat,
int (*wstatfunc)(const Py_UNICODE *, STRUCT_STAT *))
{
@@ -1048,7 +1286,17 @@ posix_ttyname(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "i:ttyname", &id))
return NULL;
+#if defined(__VMS)
+ /* DECC V5.0 - only about FD= 0 @@ try getname()+$getdvi(dvi$_devnam) */
+ if (id == 0) {
+ ret = ttyname();
+ }
+ else {
+ ret = NULL;
+ }
+#else
ret = ttyname(id);
+#endif
if (ret == NULL)
return(posix_error());
return(PyString_FromString(ret));
@@ -1092,8 +1340,13 @@ posix_chdir(PyObject *self, PyObject *args)
#elif defined(PYOS_OS2) && defined(PYCC_GCC)
return posix_1str(args, "et:chdir", _chdir2, NULL, NULL);
#else
+#ifdef __VMS
+ return posix_1str(args, "et:chdir", (int (*)(const char *))chdir,
+ NULL, NULL);
+#else
return posix_1str(args, "et:chdir", chdir, NULL, NULL);
#endif
+#endif
}
#ifdef HAVE_FCHDIR
@@ -1247,8 +1500,13 @@ posix_getcwd(PyObject *self, PyObject *args)
#if defined(PYOS_OS2) && defined(PYCC_GCC)
res = _getcwd2(buf, sizeof buf);
#else
+#if defined(__VMS)
+ /* 0 = force Unix-style path if in the VMS DCL environment! */
+ res = getcwd(buf, sizeof buf, 0);
+#else
res = getcwd(buf, sizeof buf);
#endif
+#endif
Py_END_ALLOW_THREADS
if (res == NULL)
return posix_error();
@@ -5115,7 +5373,11 @@ posix_pipe(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, ":pipe"))
return NULL;
Py_BEGIN_ALLOW_THREADS
+#if defined(__VMS)
+ res = pipe(fds,0,2100); /* bigger mailbox quota than 512 */
+#else
res = pipe(fds);
+#endif
Py_END_ALLOW_THREADS
if (res != 0)
return posix_error();
diff --git a/Modules/pwdmodule.c b/Modules/pwdmodule.c
index 9134edc..7e3c3ae 100644
--- a/Modules/pwdmodule.c
+++ b/Modules/pwdmodule.c
@@ -67,10 +67,18 @@ mkpwent(struct passwd *p)
#define SETS(i,val) sets(v, i, val)
SETS(setIndex++, p->pw_name);
+#ifdef __VMS
+ SETS(setIndex++, "");
+#else
SETS(setIndex++, p->pw_passwd);
+#endif
SETI(setIndex++, p->pw_uid);
SETI(setIndex++, p->pw_gid);
+#ifdef __VMS
+ SETS(setIndex++, "");
+#else
SETS(setIndex++, p->pw_gecos);
+#endif
SETS(setIndex++, p->pw_dir);
SETS(setIndex++, p->pw_shell);
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index 2afa697..71685c5 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -148,6 +148,15 @@ shutdown(how) -- shut down traffic in one or both directions\n\
# include <ctype.h>
#endif
+#if defined(__VMS) && ! defined(_SOCKADDR_LEN)
+# ifdef getaddrinfo
+# undef getaddrinfo
+# endif
+# include "TCPIP_IOCTL_ROUTINE"
+#else
+# include <ioctl.h>
+#endif
+
#if defined(PYOS_OS2)
# define INCL_DOS
# define INCL_DOSERRORS
@@ -270,6 +279,11 @@ 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
+
/* XXX There's a problem here: *static* functions are not supposed to have
a Py prefix (or use CapitalizedWords). Later... */
@@ -485,7 +499,10 @@ internal_setblocking(PySocketSockObject *s, int block)
#if defined(PYOS_OS2) && !defined(PYCC_GCC)
block = !block;
ioctl(s->sock_fd, FIONBIO, (caddr_t)&block, sizeof(block));
-#else /* !PYOS_OS2 */
+#elif defined(__VMS)
+ block = !block;
+ ioctl(s->sock_fd, FIONBIO, (char *)&block);
+#else /* !PYOS_OS2 && !_VMS */
delay_flag = fcntl(s->sock_fd, F_GETFL, 0);
if (block)
delay_flag &= (~O_NONBLOCK);
@@ -1223,7 +1240,11 @@ sock_getsockopt(PySocketSockObject *s, PyObject *args)
return s->errorhandler();
return PyInt_FromLong(flag);
}
+#ifdef __VMS
+ if (buflen > 1024) {
+#else
if (buflen <= 0 || buflen > 1024) {
+#endif
PyErr_SetString(socket_error,
"getsockopt buflen out of range");
return NULL;
@@ -1560,9 +1581,23 @@ sock_makefile(PySocketSockObject *s, PyObject *args)
#endif
FILE *fp;
PyObject *f;
+#ifdef __VMS
+ char *mode_r = "r";
+ char *mode_w = "w";
+#endif
if (!PyArg_ParseTuple(args, "|si:makefile", &mode, &bufsize))
return NULL;
+#ifdef __VMS
+ if (strcmp(mode,"rb") == 0) {
+ mode = mode_r;
+ }
+ else {
+ if (strcmp(mode,"wb") == 0) {
+ mode = mode_w;
+ }
+ }
+#endif
#ifdef MS_WIN32
if (((fd = _open_osfhandle(s->sock_fd, _O_BINARY)) < 0) ||
((fd = dup(fd)) < 0) || ((fp = fdopen(fd, mode)) == NULL))
@@ -1601,6 +1636,10 @@ sock_recv(PySocketSockObject *s, PyObject *args)
{
int len, n, flags = 0;
PyObject *buf;
+#ifdef __VMS
+ int read_length;
+ char *read_buf;
+#endif
if (!PyArg_ParseTuple(args, "i|i:recv", &len, &flags))
return NULL;
@@ -1615,6 +1654,7 @@ sock_recv(PySocketSockObject *s, PyObject *args)
if (buf == NULL)
return NULL;
+#ifndef __VMS
Py_BEGIN_ALLOW_THREADS
internal_select(s, 0);
n = recv(s->sock_fd, PyString_AS_STRING(buf), len, flags);
@@ -1626,6 +1666,42 @@ sock_recv(PySocketSockObject *s, PyObject *args)
}
if (n != len)
_PyString_Resize(&buf, n);
+#else
+ read_buf = PyString_AsString(buf);
+ read_length = len;
+ while (read_length != 0) {
+ unsigned int segment;
+
+ segment = read_length /SEGMENT_SIZE;
+ if (segment != 0) {
+ segment = SEGMENT_SIZE;
+ }
+ else {
+ segment = read_length;
+ }
+
+ Py_BEGIN_ALLOW_THREADS
+ internal_select(s, 0);
+ n = recv(s->sock_fd, read_buf, segment, flags);
+ Py_END_ALLOW_THREADS
+
+ if (n < 0) {
+ Py_DECREF(buf);
+ return s->errorhandler();
+ }
+ if (n != read_length) {
+ read_buf += n;
+ break;
+ }
+
+ read_length -= segment;
+ read_buf += segment;
+ }
+ if (_PyString_Resize(&buf, (read_buf - PyString_AsString(buf))) < 0)
+ {
+ return NULL;
+ }
+#endif /* !__VMS */
return buf;
}
@@ -1707,10 +1783,14 @@ sock_send(PySocketSockObject *s, PyObject *args)
{
char *buf;
int len, n, flags = 0;
+#ifdef __VMS
+ int send_length;
+#endif
if (!PyArg_ParseTuple(args, "s#|i:send", &buf, &len, &flags))
return NULL;
+#ifndef __VMS
Py_BEGIN_ALLOW_THREADS
internal_select(s, 1);
n = send(s->sock_fd, buf, len, flags);
@@ -1718,6 +1798,31 @@ 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
+ internal_select(s, 1);
+ n = send(s->sock_fd, buf, segment, flags);
+ Py_END_ALLOW_THREADS
+ if (n < 0) {
+ return s->errorhandler();
+ }
+ send_length -= segment;
+ buf += segment;
+ } /* end while */
+#endif /* !__VMS */
return PyInt_FromLong((long)n);
}
diff --git a/Objects/stringobject.c b/Objects/stringobject.c
index c234b04..3a69aa9 100644
--- a/Objects/stringobject.c
+++ b/Objects/stringobject.c
@@ -765,7 +765,11 @@ string_print(PyStringObject *op, FILE *fp, int flags)
return ret;
}
if (flags & Py_PRINT_RAW) {
- fwrite(op->ob_sval, 1, (int) op->ob_size, fp);
+#ifdef __VMS
+ if (op->ob_size) fwrite(op->ob_sval, (int) op->ob_size, 1, fp);
+#else
+ fwrite(op->ob_sval, 1, (int) op->ob_size, fp);
+#endif
return 0;
}
diff --git a/Python/exceptions.c b/Python/exceptions.c
index 015d45a..16b6738 100644
--- a/Python/exceptions.c
+++ b/Python/exceptions.c
@@ -67,6 +67,7 @@ Exception\n\
| | +-- OSError\n\
| | |\n\
| | +-- WindowsError\n\
+ | | +-- VMSError\n\
| |\n\
| +-- EOFError\n\
| +-- RuntimeError\n\
@@ -643,6 +644,11 @@ PyDoc_STRVAR(OSError__doc__, "OS system call failed.");
PyDoc_STRVAR(WindowsError__doc__, "MS-Windows OS system call failed.");
#endif /* MS_WINDOWS */
+#ifdef __VMS
+static char
+VMSError__doc__[] = "OpenVMS OS system call failed.";
+#endif
+
PyDoc_STRVAR(EOFError__doc__, "Read beyond end of file.");
PyDoc_STRVAR(RuntimeError__doc__, "Unspecified run-time error.");
@@ -1599,6 +1605,9 @@ PyObject *PyExc_ZeroDivisionError;
#ifdef MS_WINDOWS
PyObject *PyExc_WindowsError;
#endif
+#ifdef __VMS
+PyObject *PyExc_VMSError;
+#endif
/* Pre-computed MemoryError instance. Best to create this as early as
* possibly and not wait until a MemoryError is actually raised!
@@ -1650,6 +1659,10 @@ static struct {
{"WindowsError", &PyExc_WindowsError, &PyExc_OSError,
WindowsError__doc__},
#endif /* MS_WINDOWS */
+#ifdef __VMS
+ {"VMSError", &PyExc_VMSError, &PyExc_OSError,
+ VMSError__doc__},
+#endif
{"EOFError", &PyExc_EOFError, 0, EOFError__doc__},
{"RuntimeError", &PyExc_RuntimeError, 0, RuntimeError__doc__},
{"NotImplementedError", &PyExc_NotImplementedError,
diff --git a/Python/import.c b/Python/import.c
index 4d0cdbb..d921d74 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -693,8 +693,11 @@ open_exclusive(char *filename)
#ifdef O_BINARY
|O_BINARY /* necessary for Windows */
#endif
-
- , 0666);
+#ifdef __VMS
+ , 0666, "ctxt=bin", "shr=nil");
+#else
+ , 0666);
+#endif
if (fd < 0)
return NULL;
return fdopen(fd, "wb");