From 79acb9edfa893b5072350c82fd0645d023b13b03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Fri, 6 Dec 2002 12:48:53 +0000 Subject: Patch #614055: Support OpenVMS. --- Include/pyerrors.h | 3 + Misc/ACKS | 1 + Misc/NEWS | 2 + Modules/_hotshot.c | 3 +- Modules/getbuildinfo.c | 58 +++++++++++ Modules/getpath.c | 4 + Modules/main.c | 57 +++++++++++ Modules/posixmodule.c | 266 ++++++++++++++++++++++++++++++++++++++++++++++++- Modules/pwdmodule.c | 8 ++ Modules/socketmodule.c | 107 +++++++++++++++++++- Objects/stringobject.c | 6 +- Python/exceptions.c | 13 +++ Python/import.c | 7 +- 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 #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 /* tolower() */ +# include /* string descriptors */ +# include /* DVI$_name */ +# include /* -> O_RDWR */ +# include /* JPI$_name */ +# include /* LIB$name */ +# include /* OTS$name */ +# include /* SS$_name */ +# include +# include +# include +/* ----- */ +/* 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 /* 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 #endif +#if defined(__VMS) && ! defined(_SOCKADDR_LEN) +# ifdef getaddrinfo +# undef getaddrinfo +# endif +# include "TCPIP_IOCTL_ROUTINE" +#else +# include +#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"); -- cgit v0.12