]> granicus.if.org Git - python/commitdiff
Patch #614055: Support OpenVMS.
authorMartin v. Löwis <martin@v.loewis.de>
Fri, 6 Dec 2002 12:48:53 +0000 (12:48 +0000)
committerMartin v. Löwis <martin@v.loewis.de>
Fri, 6 Dec 2002 12:48:53 +0000 (12:48 +0000)
13 files changed:
Include/pyerrors.h
Misc/ACKS
Misc/NEWS
Modules/_hotshot.c
Modules/getbuildinfo.c
Modules/getpath.c
Modules/main.c
Modules/posixmodule.c
Modules/pwdmodule.c
Modules/socketmodule.c
Objects/stringobject.c
Python/exceptions.c
Python/import.c

index 868584991d7210acbba7434e2eb8033461feaec6..1adc6eca6c5b577a94c954f95852ecff7a0584ce 100644 (file)
@@ -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;
 
index 281aeb2c76264d2b57169563ee3764700dafa00a..3ef4d8ae80789f5a6a2b493fcc8647fc8e6ee023 100644 (file)
--- 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
index 91fe049d2c1070fadb1ff2baa9317d1d229dd25c..0e883bbc8ebb9355a4ed6b478ade78be90fa54b4 100644 (file)
--- 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.
index 37879b94ab32d272b2a78685961abd0a482a528a..53130d65a5bb4c769c7fd688c0aaf90a58be0036 100644 (file)
@@ -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
     {
index b59d9a770dd486c56c6c07c590bba57a78f0eee1..23b57c559d95a367bca0044661ef0ac1809bdc29 100644 (file)
 #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;
 }
index 1841c76bcce421e308db6de5ce18a7f7e2b1f724..ee972713f457ff370e4a0f075651246b76e42731 100644 (file)
  */
 
 #ifndef VERSION
+#if defined(__VMS)
+#define VERSION "2_1"
+#else
 #define VERSION "2.1"
 #endif
+#endif
 
 #ifndef VPATH
 #define VPATH "."
index d480fba62efb086b68094b55767ea6a1f67170eb..2005f0bb8789a0a5b0e9a6e0de29bb1c821e2bf8 100644 (file)
@@ -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' */
index fd7f69f6b1f2debb76d99f7e658c7b23e484242b..61fc02d2b28c0c6acee75f172dc93a9b66e9a36b 100644 (file)
 #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));
@@ -1091,9 +1339,14 @@ posix_chdir(PyObject *self, PyObject *args)
        return posix_1str(args, "et:chdir", chdir, "U:chdir", _wchdir);
 #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
@@ -1246,8 +1499,13 @@ posix_getcwd(PyObject *self, PyObject *args)
        Py_BEGIN_ALLOW_THREADS
 #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)
@@ -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();
index 9134edc1b17965e7a50bb26e0671ec2e95ecaee4..7e3c3ae170ae88e212aab1d1a0f7e900cd9d8fb3 100644 (file)
@@ -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);
 
index 2afa69769eeb0bef93c0fa262000cd16844798b8..71685c5144a01480055d054648c87a44ae08bc84 100644 (file)
@@ -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);
 }
 
index c234b0443baa713f5c02625447e5bf67fc66fe12..3a69aa9efa591262d6f81a416473596ff9b03781 100644 (file)
@@ -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;
        }
 
index 015d45a7586584d50375d81699727cef061a4f38..16b67384cd98a321ab32023b340d48a8855e0139 100644 (file)
@@ -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,
index 4d0cdbb9f91f9a27113fa63c9fba720b2876d1b8..d921d74405343e083367a918e658be26cc39be2c 100644 (file)
@@ -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");