This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Install the ptardiff utility that comes with Archive::Tar
[perl5.git] / vms / vms.c
index ecdfea6..6c8208a 100644 (file)
--- a/vms/vms.c
+++ b/vms/vms.c
 #ifndef __VAX
 #ifndef VMS_MAXRSS
 #ifdef NAML$C_MAXRSS
-#define VMS_MAXRSS NAML$C_MAXRSS+1
+#define VMS_MAXRSS (NAML$C_MAXRSS+1)
 #ifndef VMS_LONGNAME_SUPPORT
 #define VMS_LONGNAME_SUPPORT 1
 #endif /* VMS_LONGNAME_SUPPORT */
-#endif /* NAM$L_C_MAXRSS */
+#endif /* NAML$C_MAXRSS */
 #endif /* VMS_MAXRSS */
 #endif
 
@@ -76,7 +76,7 @@
 /* end of temporary hack until support is complete */
 
 #ifndef VMS_MAXRSS
-#define VMS_MAXRSS NAM$C_MAXRSS
+#define VMS_MAXRSS (NAM$C_MAXRSS + 1)
 #endif
 
 #if  __CRTL_VER < 70301000 && __CRTL_VER >= 70300000
@@ -426,7 +426,7 @@ Perl_vmstrnenv(const char *lnm, char *eqv, unsigned long int idx,
                    (uplnm[4] == 'I' && !strcmp(uplnm,"SYS$INPUT"))   ||
                    (uplnm[4] == 'E' && !strcmp(uplnm,"SYS$ERROR"))   ||
                    (uplnm[4] == 'C' && !strcmp(uplnm,"SYS$COMMAND")) )  ) {
-              memcpy(eqv,eqv+4,eqvlen-4);
+              memmove(eqv,eqv+4,eqvlen-4);
               eqvlen -= 4;
             }
             cp2 += eqvlen;
@@ -1821,7 +1821,7 @@ int unix_status;
   fac_sp = vms_status & STS$M_FAC_SP;
   msg_no = vms_status & (STS$M_MSG_NO | STS$M_SEVERITY);
 
-  if ((facility == 0) || (fac_sp == 0)  && (child_flag == 0)) {
+  if (((facility == 0) || (fac_sp == 0))  && (child_flag == 0)) {
     switch(msg_no) {
     case SS$_NORMAL:
        unix_status = 0;
@@ -2025,7 +2025,7 @@ int test_unix_status;
     case EACCES: return SS$_FILACCERR;
     case EFAULT: return SS$_ACCVIO;
     /* case ENOTBLK */
-    case EBUSY: SS$_DEVOFFLINE;
+    case EBUSY: return SS$_DEVOFFLINE;
     case EEXIST: return RMS$_FEX;
     /* case EXDEV */
     case ENODEV: return SS$_NOSUCHDEV;
@@ -2292,14 +2292,14 @@ pipe_exit_routine(pTHX)
 
     while (info) {
       int need_eof;
-      _ckvmssts(sys$setast(0));
+      _ckvmssts_noperl(sys$setast(0));
       if (info->in && !info->in->shut_on_empty) {
-        _ckvmssts(sys$qio(0,info->in->chan_in,IO$_WRITEOF,0,0,0,
+        _ckvmssts_noperl(sys$qio(0,info->in->chan_in,IO$_WRITEOF,0,0,0,
                           0, 0, 0, 0, 0, 0));
         info->waiting = 1;
         did_stuff = 1;
       }
-      _ckvmssts(sys$setast(1));
+      _ckvmssts_noperl(sys$setast(1));
       info = info->next;
     }
 
@@ -2310,11 +2310,11 @@ pipe_exit_routine(pTHX)
 
         info = open_pipes;
         while (info) {
-          _ckvmssts(sys$setast(0));
+          _ckvmssts_noperl(sys$setast(0));
           if (info->waiting && info->done) 
                 info->waiting = 0;
           nwait += info->waiting;
-          _ckvmssts(sys$setast(1));
+          _ckvmssts_noperl(sys$setast(1));
           info = info->next;
         }
         if (!nwait) break;
@@ -2324,13 +2324,13 @@ pipe_exit_routine(pTHX)
     did_stuff = 0;
     info = open_pipes;
     while (info) {
-      _ckvmssts(sys$setast(0));
+      _ckvmssts_noperl(sys$setast(0));
       if (!info->done) { /* Tap them gently on the shoulder . . .*/
         sts = sys$forcex(&info->pid,0,&abort);
-        if (!(sts&1) && sts != SS$_NONEXPR) _ckvmssts(sts); 
+        if (!(sts&1) && sts != SS$_NONEXPR) _ckvmssts_noperl(sts); 
         did_stuff = 1;
       }
-      _ckvmssts(sys$setast(1));
+      _ckvmssts_noperl(sys$setast(1));
       info = info->next;
     }
 
@@ -2341,11 +2341,11 @@ pipe_exit_routine(pTHX)
 
         info = open_pipes;
         while (info) {
-          _ckvmssts(sys$setast(0));
+          _ckvmssts_noperl(sys$setast(0));
           if (info->waiting && info->done) 
                 info->waiting = 0;
           nwait += info->waiting;
-          _ckvmssts(sys$setast(1));
+          _ckvmssts_noperl(sys$setast(1));
           info = info->next;
         }
         if (!nwait) break;
@@ -2354,12 +2354,12 @@ pipe_exit_routine(pTHX)
 
     info = open_pipes;
     while (info) {
-      _ckvmssts(sys$setast(0));
+      _ckvmssts_noperl(sys$setast(0));
       if (!info->done) {  /* We tried to be nice . . . */
         sts = sys$delprc(&info->pid,0);
-        if (!(sts&1) && sts != SS$_NONEXPR) _ckvmssts(sts); 
+        if (!(sts&1) && sts != SS$_NONEXPR) _ckvmssts_noperl(sts); 
       }
-      _ckvmssts(sys$setast(1));
+      _ckvmssts_noperl(sys$setast(1));
       info = info->next;
     }
 
@@ -2493,7 +2493,7 @@ popen_translate(pTHX_ char *logical, char *result)
 */
     ifi  = 0;
     if (result[0] == 0x1b && result[1] == 0x00) {
-        memcpy(&ifi,result+2,2);
+        memmove(&ifi,result+2,2);
         strcpy(result,result+4);
     }
     return ifi;     /* this is the RMS internal file id */
@@ -2525,7 +2525,8 @@ pipe_tochild_setup(pTHX_ char *rmbx, char *wmbx)
     unsigned int dviitm = DVI$_DEVBUFSIZ;
     int j, n;
 
-    Newx(p, 1, Pipe);
+    n = sizeof(Pipe);
+    _ckvmssts(lib$get_vm(&n, &p));
 
     create_mbx(aTHX_ &p->chan_in , &d_mbx1);
     create_mbx(aTHX_ &p->chan_out, &d_mbx2);
@@ -2695,12 +2696,14 @@ pipe_infromchild_setup(pTHX_ char *rmbx, char *wmbx)
                                       DSC$K_CLASS_S, mbx2};
     unsigned int dviitm = DVI$_DEVBUFSIZ;
 
-    Newx(p, 1, Pipe);
+    int n = sizeof(Pipe);
+    _ckvmssts(lib$get_vm(&n, &p));
     create_mbx(aTHX_ &p->chan_in , &d_mbx1);
     create_mbx(aTHX_ &p->chan_out, &d_mbx2);
 
     _ckvmssts(lib$getdvi(&dviitm, &p->chan_in, 0, &p->bufsize));
-    Newx(p->buf, p->bufsize, char);
+    n = p->bufsize * sizeof(char);
+    _ckvmssts(lib$get_vm(&n, &p->buf));
     p->shut_on_empty = FALSE;
     p->info   = 0;
     p->type   = 0;
@@ -2804,6 +2807,7 @@ pipe_mbxtofd_setup(pTHX_ int fd, char *out)
     struct stat s;
     struct dsc$descriptor_s d_mbx = {sizeof mbx, DSC$K_DTYPE_T,
                                       DSC$K_CLASS_S, mbx};
+    int n = sizeof(Pipe);
 
     /* things like terminals and mbx's don't need this filter */
     if (fd && fstat(fd,&s) == 0) {
@@ -2818,11 +2822,12 @@ pipe_mbxtofd_setup(pTHX_ int fd, char *out)
         }
     }
 
-    Newx(p, 1, Pipe);
+    _ckvmssts(lib$get_vm(&n, &p));
     p->fd_out = dup(fd);
     create_mbx(aTHX_ &p->chan_in, &d_mbx);
     _ckvmssts(lib$getdvi(&dviitm, &p->chan_in, 0, &p->bufsize));
-    Newx(p->buf, p->bufsize+1, char);
+    n = (p->bufsize+1) * sizeof(char);
+    _ckvmssts(lib$get_vm(&n, &p->buf));
     p->shut_on_empty = FALSE;
     p->retry = 0;
     p->info  = 0;
@@ -2898,7 +2903,7 @@ free_pipelocs(pTHX_ void *head)
     p = *pHead;
     while (p) {
         pnext = p->next;
-        Safefree(p);
+        PerlMem_free(p);
         p = pnext;
     }
     *pHead = 0;
@@ -2922,7 +2927,7 @@ store_pipelocs(pTHX)
 
 /*  the . directory from @INC comes last */
 
-    Newx(p,1,PLOC);
+    p = (pPLOC) PerlMem_malloc(sizeof(PLOC));
     p->next = head_PLOC;
     head_PLOC = p;
     strcpy(p->dir,"./");
@@ -2952,7 +2957,7 @@ store_pipelocs(pTHX)
        }
 
         if ((unixdir = tounixpath(temp, Nullch)) != Nullch) {
-            Newx(p,1,PLOC);
+            p = (pPLOC) PerlMem_malloc(sizeof(PLOC));
             p->next = head_PLOC;
             head_PLOC = p;
             strncpy(p->dir,unixdir,sizeof(p->dir)-1);
@@ -2976,7 +2981,7 @@ store_pipelocs(pTHX)
         if ((unixdir = tounixpath(dir, Nullch)) == Nullch)
             continue;
 
-        Newx(p,1,PLOC);
+        p = (pPLOC) PerlMem_malloc(sizeof(PLOC));
         p->next = head_PLOC;
         head_PLOC = p;
         strncpy(p->dir,unixdir,sizeof(p->dir)-1);
@@ -2987,7 +2992,7 @@ store_pipelocs(pTHX)
 
 #ifdef ARCHLIB_EXP
     if ((unixdir = tounixpath(ARCHLIB_EXP, Nullch)) != Nullch) {
-        Newx(p,1,PLOC);
+        p = (pPLOC) PerlMem_malloc(sizeof(PLOC));
         p->next = head_PLOC;
         head_PLOC = p;
         strncpy(p->dir,unixdir,sizeof(p->dir)-1);
@@ -3123,9 +3128,9 @@ vmspipe_tempfile(pTHX)
     fstat(fileno(fp), (struct stat *)&s1);
 
     #if defined(_USE_STD_STAT)
-      cmp_result = s0.st_ino != s1.st_ino;
+      cmp_result = s0.crtl_stat.st_ino != s1.crtl_stat.st_ino;
     #else
-      cmp_result = memcmp(&s0.st_ino, &s1.st_ino, 6);
+      cmp_result = memcmp(s0.crtl_stat.st_ino, s1.crtl_stat.st_ino, 6);
     #endif
     if ((cmp_result != 0) && (s0.st_ctime != s1.st_ctime))  {
         fclose(fp);
@@ -3147,12 +3152,12 @@ safe_popen(pTHX_ const char *cmd, const char *in_mode, int *psts)
      * environment.  Hence we've switched to LOCAL symbol table.
      */
     unsigned int table = LIB$K_CLI_LOCAL_SYM;
-    int j, wait = 0;
+    int j, wait = 0, n;
     char *p, mode[10], symbol[MAX_DCL_SYMBOL+1], *vmspipe;
     char in[512], out[512], err[512], mbx[512];
     FILE *tpipe = 0;
     char tfilebuf[NAM$C_MAXRSS+1];
-    pInfo info;
+    pInfo info = NULL;
     char cmd_sym_name[20];
     struct dsc$descriptor_s d_symbol= {0, DSC$K_DTYPE_T,
                                       DSC$K_CLASS_S, symbol};
@@ -3239,7 +3244,8 @@ safe_popen(pTHX_ const char *cmd, const char *in_mode, int *psts)
       *psts = sts;
       return Nullfp; 
     }
-    Newx(info,1,Info);
+    n = sizeof(Info);
+    _ckvmssts(lib$get_vm(&n, &info));
         
     strcpy(mode,in_mode);
     info->mode = *mode;
@@ -3293,9 +3299,14 @@ safe_popen(pTHX_ const char *cmd, const char *in_mode, int *psts)
                 if (!done) _ckvmssts(sys$waitfr(pipe_ef));
             }
 
-            if (info->out->buf) Safefree(info->out->buf);
-            Safefree(info->out);
-            Safefree(info);
+            if (info->out->buf) {
+                n = info->out->bufsize * sizeof(char);
+                _ckvmssts(lib$free_vm(&n, &info->out->buf));
+            }
+            n = sizeof(Pipe);
+            _ckvmssts(lib$free_vm(&n, &info->out));
+            n = sizeof(Info);
+            _ckvmssts(lib$free_vm(&n, &info));
             *psts = RMS$_FNF;
             return Nullfp;
         }
@@ -3325,7 +3336,7 @@ safe_popen(pTHX_ const char *cmd, const char *in_mode, int *psts)
 
         info->in = pipe_tochild_setup(aTHX_ in,mbx);
         if (!info->useFILE) {
-        info->fp  = PerlIO_open(mbx, mode);
+           info->fp  = PerlIO_open(mbx, mode);
         } else {
             info->fp = (PerlIO *) freopen(mbx, mode, stdout);
             Perl_vmssetuserlnm(aTHX_ "SYS$OUTPUT",mbx);
@@ -3352,9 +3363,14 @@ safe_popen(pTHX_ const char *cmd, const char *in_mode, int *psts)
                 if (!done) _ckvmssts(sys$waitfr(pipe_ef));
             }
 
-            if (info->in->buf) Safefree(info->in->buf);
-            Safefree(info->in);
-            Safefree(info);
+            if (info->in->buf) {
+                n = info->in->bufsize * sizeof(char);
+                _ckvmssts(lib$free_vm(&n, &info->in->buf));
+            }
+            n = sizeof(Pipe);
+            _ckvmssts(lib$free_vm(&n, &info->in));
+            n = sizeof(Info);
+            _ckvmssts(lib$free_vm(&n, &info));
             *psts = RMS$_FNF;
             return Nullfp;
         }
@@ -3391,9 +3407,6 @@ safe_popen(pTHX_ const char *cmd, const char *in_mode, int *psts)
     _ckvmssts(lib$set_symbol(&d_sym_out, &d_symbol, &table));
 
     p = vmscmd->dsc$a_pointer;
-    while (*p && *p != '\n') p++;
-    *p = '\0';                                  /* truncate on \n */
-    p = vmscmd->dsc$a_pointer;
     while (*p == ' ' || *p == '\t') p++;        /* remove leading whitespace */
     if (*p == '$') p++;                         /* remove leading $ */
     while (*p == ' ' || *p == '\t') p++;
@@ -3484,7 +3497,7 @@ I32 Perl_my_pclose(pTHX_ PerlIO *fp)
 {
     pInfo info, last = NULL;
     unsigned long int retsts;
-    int done, iss;
+    int done, iss, n;
     
     for (info = open_pipes; info != NULL; last = info, info = info->next)
         if (info->fp == fp) break;
@@ -3504,7 +3517,7 @@ I32 Perl_my_pclose(pTHX_ PerlIO *fp)
      */
      if (info->fp) {
         if (!info->useFILE) 
-     PerlIO_flush(info->fp);   /* first, flush data */
+            PerlIO_flush(info->fp);   /* first, flush data */
         else 
             fflush((FILE *)info->fp);
     }
@@ -3527,7 +3540,7 @@ I32 Perl_my_pclose(pTHX_ PerlIO *fp)
     _ckvmssts(sys$setast(1));
     if (info->fp) {
      if (!info->useFILE) 
-    PerlIO_close(info->fp);
+        PerlIO_close(info->fp);
      else 
         fclose((FILE *)info->fp);
     }
@@ -3555,18 +3568,31 @@ I32 Perl_my_pclose(pTHX_ PerlIO *fp)
     /* free buffers and structures */
 
     if (info->in) {
-        if (info->in->buf) Safefree(info->in->buf);
-        Safefree(info->in);
+        if (info->in->buf) {
+            n = info->in->bufsize * sizeof(char);
+            _ckvmssts(lib$free_vm(&n, &info->in->buf));
+        }
+        n = sizeof(Pipe);
+        _ckvmssts(lib$free_vm(&n, &info->in));
     }
     if (info->out) {
-        if (info->out->buf) Safefree(info->out->buf);
-        Safefree(info->out);
+        if (info->out->buf) {
+            n = info->out->bufsize * sizeof(char);
+            _ckvmssts(lib$free_vm(&n, &info->out->buf));
+        }
+        n = sizeof(Pipe);
+        _ckvmssts(lib$free_vm(&n, &info->out));
     }
     if (info->err) {
-        if (info->err->buf) Safefree(info->err->buf);
-        Safefree(info->err);
+        if (info->err->buf) {
+            n = info->err->bufsize * sizeof(char);
+            _ckvmssts(lib$free_vm(&n, &info->err->buf));
+        }
+        n = sizeof(Pipe);
+        _ckvmssts(lib$free_vm(&n, &info->err));
     }
-    Safefree(info);
+    n = sizeof(Info);
+    _ckvmssts(lib$free_vm(&n, &info));
 
     return retsts;
 
@@ -3737,6 +3763,105 @@ my_gconvert(double val, int ndig, int trail, char *buf)
 }
 /*}}}*/
 
+#if 1 /* defined(__VAX) || !defined(NAML$C_MAXRSS) */
+static int rms_free_search_context(struct FAB * fab)
+{
+struct NAM * nam;
+
+    nam = fab->fab$l_nam;
+    nam->nam$b_nop |= NAM$M_SYNCHK;
+    nam->nam$l_rlf = NULL;
+    fab->fab$b_dns = 0;
+    return sys$parse(fab, NULL, NULL);
+}
+
+#define rms_setup_nam(nam) struct NAM nam = cc$rms_nam
+#define rms_set_nam_nop(nam, opt) nam.nam$b_nop |= (opt)
+#define rms_set_nam_fnb(nam, opt) nam.nam$l_fnb |= (opt)
+#define rms_is_nam_fnb(nam, opt) (nam.nam$l_fnb & (opt))
+#define rms_nam_esll(nam) nam.nam$b_esl
+#define rms_nam_esl(nam) nam.nam$b_esl
+#define rms_nam_name(nam) nam.nam$l_name
+#define rms_nam_namel(nam) nam.nam$l_name
+#define rms_nam_type(nam) nam.nam$l_type
+#define rms_nam_typel(nam) nam.nam$l_type
+#define rms_nam_ver(nam) nam.nam$l_ver
+#define rms_nam_verl(nam) nam.nam$l_ver
+#define rms_nam_rsll(nam) nam.nam$b_rsl
+#define rms_nam_rsl(nam) nam.nam$b_rsl
+#define rms_bind_fab_nam(fab, nam) fab.fab$l_nam = &nam
+#define rms_set_fna(fab, nam, name, size) \
+       fab.fab$b_fns = size; fab.fab$l_fna = name;
+#define rms_get_fna(fab, nam) fab.fab$l_fna
+#define rms_set_dna(fab, nam, name, size) \
+       fab.fab$b_dns = size; fab.fab$l_dna = name;
+#define rms_nam_dns(fab, nam) fab.fab$b_dns;
+#define rms_set_esa(fab, nam, name, size) \
+       nam.nam$b_ess = size; nam.nam$l_esa = name;
+#define rms_set_esal(nam, s_name, s_size, l_name, l_size) \
+       nam.nam$l_esa = s_name; nam.nam$b_ess = s_size;
+#define rms_set_rsa(nam, name, size) \
+       nam.nam$l_rsa = name; nam.nam$b_rss = size;
+#define rms_set_rsal(nam, s_name, s_size, l_name, l_size) \
+       nam.nam$l_rsa = s_name; nam.nam$b_rss = s_size;
+
+#else
+static int rms_free_search_context(struct FAB * fab)
+{
+struct NAML * nam;
+
+    nam = fab->fab$l_naml;
+    nam->naml$b_nop |= NAM$M_SYNCHK;
+    nam->naml$l_rlf = NULL;
+    nam->naml$l_long_defname_size = 0;
+    fab->fab$b_dns = 0;
+    return sys$parse(fab, NULL, NULL);
+}
+
+#define rms_setup_nam(nam) struct NAML nam = cc$rms_naml
+#define rms_set_nam_nop(nam, opt) nam.naml$b_nop |= (opt)
+#define rms_set_nam_fnb(nam, opt) nam.naml$l_fnb |= (opt)
+#define rms_is_nam_fnb(nam, opt) (nam.naml$l_fnb & (opt))
+#define rms_nam_esll(nam) nam.naml$l_long_expand_size
+#define rms_nam_esl(nam) nam.naml$b_esl
+#define rms_nam_name(nam) nam.naml$l_name
+#define rms_nam_namel(nam) nam.naml$l_long_name
+#define rms_nam_type(nam) nam.naml$l_type
+#define rms_nam_typel(nam) nam.naml$l_long_type
+#define rms_nam_ver(nam) nam.naml$l_ver
+#define rms_nam_verl(nam) nam.naml$l_long_ver
+#define rms_nam_rsll(nam) nam.naml$l_long_result_size
+#define rms_nam_rsl(nam) nam.naml$b_rsl
+#define rms_bind_fab_nam(fab, nam) fab.fab$l_naml = &nam
+#define rms_set_fna(fab, nam, name, size) \
+       fab.fab$b_fns = 0; fab.fab$l_fna = (char *) -1; \
+       nam.naml$l_long_filename_size = size; \
+       nam.naml$l_long_filename = name
+#define rms_get_fna(fab, nam) nam.naml$l_long_filename
+#define rms_set_dna(fab, nam, name, size) \
+       fab.fab$b_dns = 0; fab.fab$l_dna = (char *) -1; \
+       nam.naml$l_long_defname_size = size; \
+       nam.naml$l_long_defname = name
+#define rms_nam_dns(fab, nam) nam.naml$l_long_defname_size
+#define rms_set_esa(fab, nam, name, size) \
+       nam.naml$b_ess = 0; nam.naml$l_esa = (char *) -1; \
+       nam.naml$l_long_expand_alloc = size; \
+       nam.naml$l_long_expand = name
+#define rms_set_esal(nam, s_name, s_size, l_name, l_size) \
+       nam.naml$l_esa = s_name; nam.naml$b_ess = s_size; \
+       nam.naml$l_long_expand = l_name; \
+       nam.naml$l_long_expand_alloc = l_size;
+#define rms_set_rsa(nam, name, size) \
+       nam.naml$l_rsa = NULL; nam.naml$b_rss = 0; \
+       nam.naml$l_long_result = name; \
+       nam.naml$l_long_result_alloc = size;
+#define rms_set_rsal(nam, s_name, s_size, l_name, l_size) \
+       nam.naml$l_rsa = s_name; nam.naml$b_rss = s_size; \
+       nam.naml$l_long_result = l_name; \
+       nam.naml$l_long_result_alloc = l_size;
+
+#endif
+
 
 /*{{{char *do_rmsexpand(char *fspec, char *out, int ts, char *def, unsigned opts)*/
 /* Shortcut for common case of simple calls to $PARSE and $SEARCH
@@ -3755,6 +3880,8 @@ my_gconvert(double val, int ndig, int trail, char *buf)
  */
 static char *mp_do_tounixspec(pTHX_ const char *, char *, int);
 
+#if defined(__VAX) || !defined(NAML$C_MAXRSS)
+/* ODS-2 only version */
 static char *
 mp_do_rmsexpand(pTHX_ const char *filespec, char *outbuf, int ts, const char *defspec, unsigned opts)
 {
@@ -3777,7 +3904,11 @@ mp_do_rmsexpand(pTHX_ const char *filespec, char *outbuf, int ts, const char *de
   }
   isunix = is_unix_filespec(filespec);
   if (isunix) {
-    if (do_tovmsspec(filespec,vmsfspec,0) == NULL) return NULL;
+    if (do_tovmsspec(filespec,vmsfspec,0) == NULL) {
+       if (out)
+          Safefree(out);
+       return NULL;
+    }
     filespec = vmsfspec;
   }
 
@@ -3787,7 +3918,11 @@ mp_do_rmsexpand(pTHX_ const char *filespec, char *outbuf, int ts, const char *de
 
   if (defspec && *defspec) {
     if (strchr(defspec,'/') != NULL) {
-      if (do_tovmsspec(defspec,tmpfspec,0) == NULL) return NULL;
+      if (do_tovmsspec(defspec,tmpfspec,0) == NULL) {
+       if (out)
+          Safefree(out);
+       return NULL;
+      }
       defspec = tmpfspec;
     }
     myfab.fab$l_dna = (char *)defspec; /* cast ok for read only pointer */
@@ -3799,13 +3934,14 @@ mp_do_rmsexpand(pTHX_ const char *filespec, char *outbuf, int ts, const char *de
   mynam.nam$l_rsa = outbuf;
   mynam.nam$b_rss = NAM$C_MAXRSS;
 
+#ifdef NAM$M_NO_SHORT_UPCASE
+  if (decc_efs_case_preserve)
+    mynam.nam$b_nop |= NAM$M_NO_SHORT_UPCASE;
+#endif
+
   retsts = sys$parse(&myfab,0,0);
   if (!(retsts & 1)) {
     mynam.nam$b_nop |= NAM$M_SYNCHK;
-#ifdef NAM$M_NO_SHORT_UPCASE
-    if (decc_efs_case_preserve)
-      mynam.nam$b_nop |= NAM$M_NO_SHORT_UPCASE;
-#endif
     if (retsts == RMS$_DNF || retsts == RMS$_DIR || retsts == RMS$_DEV) {
       retsts = sys$parse(&myfab,0,0);
       if (retsts & 1) goto expanded;
@@ -3823,10 +3959,6 @@ mp_do_rmsexpand(pTHX_ const char *filespec, char *outbuf, int ts, const char *de
   retsts = sys$search(&myfab,0,0);
   if (!(retsts & 1) && retsts != RMS$_FNF) {
     mynam.nam$b_nop |= NAM$M_SYNCHK; mynam.nam$l_rlf = NULL;
-#ifdef NAM$M_NO_SHORT_UPCASE
-    if (decc_efs_case_preserve)
-      mynam.nam$b_nop |= NAM$M_NO_SHORT_UPCASE;
-#endif
     myfab.fab$b_dns = 0; sts = sys$parse(&myfab,0,0);  /* Free search context */
     if (out) Safefree(out);
     set_vaxc_errno(retsts);
@@ -3878,7 +4010,7 @@ mp_do_rmsexpand(pTHX_ const char *filespec, char *outbuf, int ts, const char *de
     if (trimtype) {
       /* If we didn't already trim version, copy down */
       if (speclen > mynam.nam$l_ver - out)
-        memcpy(mynam.nam$l_type, mynam.nam$l_ver, 
+        memmove(mynam.nam$l_type, mynam.nam$l_ver, 
                speclen - (mynam.nam$l_ver - out));
       speclen -= mynam.nam$l_ver - mynam.nam$l_type; 
     }
@@ -3917,14 +4049,319 @@ mp_do_rmsexpand(pTHX_ const char *filespec, char *outbuf, int ts, const char *de
     strcpy(outbuf,tmpfspec);
   }
   mynam.nam$b_nop |= NAM$M_SYNCHK; mynam.nam$l_rlf = NULL;
+  mynam.nam$l_rsa = NULL;
+  mynam.nam$b_rss = 0;
+  myfab.fab$b_dns = 0;  sts = sys$parse(&myfab,0,0);  /* Free search context */
+  return outbuf;
+}
+#else
+/* ODS-5 supporting routine */
+static char *
+mp_do_rmsexpand(pTHX_ const char *filespec, char *outbuf, int ts, const char *defspec, unsigned opts)
+{
+  static char __rmsexpand_retbuf[NAML$C_MAXRSS+1];
+  char * vmsfspec, *tmpfspec;
+  char * esa, *cp, *out = NULL;
+  char * esal;
+  char * outbufl;
+  struct FAB myfab = cc$rms_fab;
+  rms_setup_nam(mynam);
+  STRLEN speclen;
+  unsigned long int retsts, trimver, trimtype, haslower = 0, isunix = 0;
+  int sts;
+
+  if (!filespec || !*filespec) {
+    set_vaxc_errno(LIB$_INVARG); set_errno(EINVAL);
+    return NULL;
+  }
+  if (!outbuf) {
+    if (ts) out = Newx(outbuf,VMS_MAXRSS,char);
+    else    outbuf = __rmsexpand_retbuf;
+  }
+
+  vmsfspec = NULL;
+  tmpfspec = NULL;
+  outbufl = NULL;
+  isunix = is_unix_filespec(filespec);
+  if (isunix) {
+    Newx(vmsfspec, VMS_MAXRSS, char);
+    if (do_tovmsspec(filespec,vmsfspec,0) == NULL) {
+       Safefree(vmsfspec);
+       if (out)
+          Safefree(out);
+       return NULL;
+    }
+    filespec = vmsfspec;
+
+     /* Unless we are forcing to VMS format, a UNIX input means
+      * UNIX output, and that requires long names to be used
+      */
+    if ((opts & PERL_RMSEXPAND_M_VMS) == 0)
+       opts |= PERL_RMSEXPAND_M_LONG;
+    else {
+       isunix = 0;
+    }
+  }
+
+  rms_set_fna(myfab, mynam, (char *)filespec, strlen(filespec)); /* cast ok */
+  rms_bind_fab_nam(myfab, mynam);
+
+  if (defspec && *defspec) {
+    int t_isunix;
+    t_isunix = is_unix_filespec(defspec);
+    if (t_isunix) {
+      Newx(tmpfspec, VMS_MAXRSS, char);
+      if (do_tovmsspec(defspec,tmpfspec,0) == NULL) {
+       Safefree(tmpfspec);
+       if (vmsfspec != NULL)
+           Safefree(vmsfspec);
+       if (out)
+          Safefree(out);
+       return NULL;
+      }
+      defspec = tmpfspec;
+    }
+    rms_set_dna(myfab, mynam, (char *)defspec, strlen(defspec)); /* cast ok */
+  }
+
+  Newx(esa, NAM$C_MAXRSS + 1, char);
+#if !defined(__VAX) && defined(NAML$C_MAXRSS)
+  Newx(esal, NAML$C_MAXRSS + 1, char);
+#endif
+  rms_set_esal(mynam, esa, NAM$C_MAXRSS, esal, NAML$C_MAXRSS);
+
+  if ((opts & PERL_RMSEXPAND_M_LONG) != 0) {
+    rms_set_rsa(mynam, outbuf, (VMS_MAXRSS - 1));
+  }
+  else {
+#if !defined(__VAX) && defined(NAML$C_MAXRSS)
+    Newx(outbufl, VMS_MAXRSS, char);
+    rms_set_rsal(mynam, outbuf, NAM$C_MAXRSS, outbufl, (VMS_MAXRSS - 1));
+#else
+    rms_set_rsa(mynam, outbuf, NAM$C_MAXRSS);
+#endif
+  }
+
 #ifdef NAM$M_NO_SHORT_UPCASE
   if (decc_efs_case_preserve)
-    mynam.nam$b_nop |= NAM$M_NO_SHORT_UPCASE;
+    rms_set_nam_nop(mynam, NAM$M_NO_SHORT_UPCASE);
+#endif
+
+  /* First attempt to parse as an existing file */
+  retsts = sys$parse(&myfab,0,0);
+  if (!(retsts & STS$K_SUCCESS)) {
+
+    /* Could not find the file, try as syntax only if error is not fatal */
+    rms_set_nam_nop(mynam, NAM$M_SYNCHK);
+    if (retsts == RMS$_DNF || retsts == RMS$_DIR || retsts == RMS$_DEV) {
+      retsts = sys$parse(&myfab,0,0);
+      if (retsts & STS$K_SUCCESS) goto expanded;
+    }  
+
+     /* Still could not parse the file specification */
+    /*----------------------------------------------*/
+    sts = rms_free_search_context(&myfab); /* Free search context */
+    if (out) Safefree(out);
+    if (tmpfspec != NULL)
+       Safefree(tmpfspec);
+    if (vmsfspec != NULL)
+       Safefree(vmsfspec);
+    Safefree(esa);
+    Safefree(esal);
+    set_vaxc_errno(retsts);
+    if      (retsts == RMS$_PRV) set_errno(EACCES);
+    else if (retsts == RMS$_DEV) set_errno(ENODEV);
+    else if (retsts == RMS$_DIR) set_errno(ENOTDIR);
+    else                         set_errno(EVMSERR);
+    return NULL;
+  }
+  retsts = sys$search(&myfab,0,0);
+  if (!(retsts & STS$K_SUCCESS) && retsts != RMS$_FNF) {
+    sts = rms_free_search_context(&myfab); /* Free search context */
+    if (out) Safefree(out);
+    if (tmpfspec != NULL)
+       Safefree(tmpfspec);
+    if (vmsfspec != NULL)
+       Safefree(vmsfspec);
+    Safefree(esa);
+    Safefree(esal);
+    set_vaxc_errno(retsts);
+    if      (retsts == RMS$_PRV) set_errno(EACCES);
+    else                         set_errno(EVMSERR);
+    return NULL;
+  }
+
+  /* If the input filespec contained any lowercase characters,
+   * downcase the result for compatibility with Unix-minded code. */
+  expanded:
+  if (!decc_efs_case_preserve) {
+    for (out = rms_get_fna(myfab, mynam); *out; out++)
+      if (islower(*out)) { haslower = 1; break; }
+  }
+
+   /* Is a long or a short name expected */
+  /*------------------------------------*/
+  if ((opts & PERL_RMSEXPAND_M_LONG) != 0) {
+    if (rms_nam_rsll(mynam)) {
+       out = outbuf;
+       speclen = rms_nam_rsll(mynam);
+    }
+    else {
+       out = esal; /* Not esa */
+       speclen = rms_nam_esll(mynam);
+    }
+  }
+  else {
+    if (rms_nam_rsl(mynam)) {
+       out = outbuf;
+       speclen = rms_nam_rsl(mynam);
+    }
+    else {
+       out = esa; /* Not esal */
+       speclen = rms_nam_esl(mynam);
+    }
+  }
+  /* Trim off null fields added by $PARSE
+   * If type > 1 char, must have been specified in original or default spec
+   * (not true for version; $SEARCH may have added version of existing file).
+   */
+  trimver  = !rms_is_nam_fnb(mynam, NAM$M_EXP_VER);
+  if ((opts & PERL_RMSEXPAND_M_LONG) != 0) {
+    trimtype = !rms_is_nam_fnb(mynam, NAM$M_EXP_TYPE) &&
+             ((rms_nam_verl(mynam) - rms_nam_typel(mynam)) == 1);
+  }
+  else {
+    trimtype = !rms_is_nam_fnb(mynam, NAM$M_EXP_TYPE) &&
+             ((rms_nam_ver(mynam) - rms_nam_type(mynam)) == 1);
+  }
+  if (trimver || trimtype) {
+    if (defspec && *defspec) {
+      char *defesal = NULL;
+      Newx(defesal, NAML$C_MAXRSS + 1, char);
+      if (defesal != NULL) {
+       struct FAB deffab = cc$rms_fab;
+       rms_setup_nam(defnam);
+     
+       rms_bind_fab_nam(deffab, defnam);
+
+       /* Cast ok */ 
+       rms_set_fna
+           (deffab, defnam, (char *)defspec, rms_nam_dns(myfab, mynam)); 
+
+       rms_set_esa(deffab, defnam, defesal, VMS_MAXRSS - 1);
+
+       rms_set_nam_nop(defnam, 0);
+       rms_set_nam_nop(defnam, NAM$M_SYNCHK);
+#ifdef NAM$M_NO_SHORT_UPCASE
+       if (decc_efs_case_preserve)
+         rms_set_nam_nop(defnam, NAM$M_NO_SHORT_UPCASE);
 #endif
-  mynam.nam$l_rsa = NULL; mynam.nam$b_rss = 0;
-  myfab.fab$b_dns = 0; sts = sys$parse(&myfab,0,0);  /* Free search context */
+       if (sys$parse(&deffab,0,0) & STS$K_SUCCESS) {
+         if (trimver) {
+            trimver  = !rms_is_nam_fnb(defnam, NAM$M_EXP_VER);
+         }
+         if (trimtype) {
+           trimtype = !rms_is_nam_fnb(defnam, NAM$M_EXP_TYPE); 
+         }
+       }
+       Safefree(defesal);
+      }
+    }
+    if (trimver) {
+      if ((opts & PERL_RMSEXPAND_M_LONG) != 0) {
+       if (*(rms_nam_verl(mynam)) != '\"')
+         speclen = rms_nam_verl(mynam) - out;
+      }
+      else {
+       if (*(rms_nam_ver(mynam)) != '\"')
+         speclen = rms_nam_ver(mynam) - out;
+      }
+    }
+    if (trimtype) {
+      /* If we didn't already trim version, copy down */
+      if ((opts & PERL_RMSEXPAND_M_LONG) != 0) {
+       if (speclen > rms_nam_verl(mynam) - out)
+         memmove
+          (rms_nam_typel(mynam),
+           rms_nam_verl(mynam),
+           speclen - (rms_nam_verl(mynam) - out));
+         speclen -= rms_nam_verl(mynam) - rms_nam_typel(mynam);
+      }
+      else {
+       if (speclen > rms_nam_ver(mynam) - out)
+         memmove
+          (rms_nam_type(mynam),
+           rms_nam_ver(mynam),
+           speclen - (rms_nam_ver(mynam) - out));
+         speclen -= rms_nam_ver(mynam) - rms_nam_type(mynam);
+      }
+    }
+  }
+
+   /* Done with these copies of the input files */
+  /*-------------------------------------------*/
+  if (vmsfspec != NULL)
+       Safefree(vmsfspec);
+  if (tmpfspec != NULL)
+       Safefree(tmpfspec);
+
+  /* If we just had a directory spec on input, $PARSE "helpfully"
+   * adds an empty name and type for us */
+  if ((opts & PERL_RMSEXPAND_M_LONG) != 0) {
+    if (rms_nam_namel(mynam) == rms_nam_typel(mynam) &&
+       rms_nam_verl(mynam)  == rms_nam_typel(mynam) + 1 &&
+       !(rms_is_nam_fnb(mynam, NAM$M_EXP_NAME)))
+      speclen = rms_nam_namel(mynam) - out;
+  }
+  else {
+    if (rms_nam_name(mynam) == rms_nam_type(mynam) &&
+       rms_nam_ver(mynam)  == rms_nam_ver(mynam) + 1 &&
+       !(rms_is_nam_fnb(mynam, NAM$M_EXP_NAME)))
+      speclen = rms_nam_name(mynam) - out;
+  }
+
+  /* Posix format specifications must have matching quotes */
+  if (decc_posix_compliant_pathnames && (out[0] == '\"')) {
+    if ((speclen > 1) && (out[speclen-1] != '\"')) {
+      out[speclen] = '\"';
+      speclen++;
+    }
+  }
+  out[speclen] = '\0';
+  if (haslower && !decc_efs_case_preserve) __mystrtolower(out);
+
+  /* Have we been working with an expanded, but not resultant, spec? */
+  /* Also, convert back to Unix syntax if necessary. */
+
+  if (!rms_nam_rsll(mynam)) {
+    if (isunix) {
+      if (do_tounixspec(esa,outbuf,0) == NULL) {
+       Safefree(esal);
+       Safefree(esa);
+       return NULL;
+      }
+    }
+    else strcpy(outbuf,esa);
+  }
+  else if (isunix) {
+    Newx(tmpfspec, VMS_MAXRSS, char);
+    if (do_tounixspec(outbuf,tmpfspec,0) == NULL) {
+       Safefree(esa);
+       Safefree(esal);
+       Safefree(tmpfspec);
+       return NULL;
+    }
+    strcpy(outbuf,tmpfspec);
+    Safefree(tmpfspec);
+  }
+
+  rms_set_rsal(mynam, NULL, 0, NULL, 0);
+  sts = rms_free_search_context(&myfab); /* Free search context */
+  Safefree(esa);
+  Safefree(esal);
   return outbuf;
 }
+#endif
 /*}}}*/
 /* External entry points */
 char *Perl_rmsexpand(pTHX_ const char *spec, char *buf, const char *def, unsigned opt)
@@ -3967,13 +4404,13 @@ char *Perl_rmsexpand_ts(pTHX_ const char *spec, char *buf, const char *def, unsi
 ** found in the Perl standard distribution.
  */
 
-/*{{{ char *fileify_dirspec[_ts](char *path, char *buf)*/
+/*{{{ char *fileify_dirspec[_ts](char *dir, char *buf)*/
 static char *mp_do_fileify_dirspec(pTHX_ const char *dir,char *buf,int ts)
 {
-    static char __fileify_retbuf[NAM$C_MAXRSS+1];
+    static char __fileify_retbuf[VMS_MAXRSS];
     unsigned long int dirlen, retlen, addmfd = 0, hasfilename = 0;
     char *retspec, *cp1, *cp2, *lastdir;
-    char trndir[NAM$C_MAXRSS+2], vmsdir[NAM$C_MAXRSS+1];
+    char *trndir, *vmsdir;
     unsigned short int trnlnm_iter_count;
     int sts;
 
@@ -3990,9 +4427,11 @@ static char *mp_do_fileify_dirspec(pTHX_ const char *dir,char *buf,int ts)
       else
        dirlen = 1;
     }
-    if (dirlen > NAM$C_MAXRSS) {
-      set_errno(ENAMETOOLONG); set_vaxc_errno(RMS$_SYN); return NULL;
+    if (dirlen > (VMS_MAXRSS - 1)) {
+      set_errno(ENAMETOOLONG); set_vaxc_errno(RMS$_SYN);
+      return NULL;
     }
+    Newx(trndir, VMS_MAXRSS + 1, char);
     if (!strpbrk(dir+1,"/]>:")  &&
        (!decc_posix_compliant_pathnames && decc_disable_posix_root)) {
       strcpy(trndir,*dir == '/' ? dir + 1: dir);
@@ -4046,14 +4485,21 @@ static char *mp_do_fileify_dirspec(pTHX_ const char *dir,char *buf,int ts)
       }
     }
 
-    cp1 = strpbrk(trndir,"]:>"); /* Prepare for future change */
+    Newx(vmsdir, VMS_MAXRSS + 1, char);
+    cp1 = strpbrk(trndir,"]:>");
     if (hasfilename || !cp1) { /* Unix-style path or filename */
       if (trndir[0] == '.') {
-        if (trndir[1] == '\0' || (trndir[1] == '/' && trndir[2] == '\0'))
+        if (trndir[1] == '\0' || (trndir[1] == '/' && trndir[2] == '\0')) {
+         Safefree(trndir);
+         Safefree(vmsdir);
           return do_fileify_dirspec("[]",buf,ts);
+       }
         else if (trndir[1] == '.' &&
-                 (trndir[2] == '\0' || (trndir[2] == '/' && trndir[3] == '\0')))
+               (trndir[2] == '\0' || (trndir[2] == '/' && trndir[3] == '\0'))) {
+         Safefree(trndir);
+         Safefree(vmsdir);
           return do_fileify_dirspec("[-]",buf,ts);
+       }
       }
       if (dirlen && trndir[dirlen-1] == '/') {    /* path ends with '/'; just add .dir;1 */
         dirlen -= 1;                 /* to last element */
@@ -4066,23 +4512,39 @@ static char *mp_do_fileify_dirspec(pTHX_ const char *dir,char *buf,int ts)
         do {
           if (*(cp1+2) == '.') cp1++;
           if (*(cp1+2) == '/' || *(cp1+2) == '\0') {
-            if (do_tovmsspec(trndir,vmsdir,0) == NULL) return NULL;
+           char * ret_chr;
+            if (do_tovmsspec(trndir,vmsdir,0) == NULL) {
+               Safefree(trndir);
+               Safefree(vmsdir);
+               return NULL;
+           }
             if (strchr(vmsdir,'/') != NULL) {
               /* If do_tovmsspec() returned it, it must have VMS syntax
                * delimiters in it, so it's a mixed VMS/Unix spec.  We take
                * the time to check this here only so we avoid a recursion
                * loop; otherwise, gigo.
                */
-              set_errno(EINVAL);  set_vaxc_errno(RMS$_SYN);  return NULL;
+             Safefree(trndir);
+             Safefree(vmsdir);
+              set_errno(EINVAL);  set_vaxc_errno(RMS$_SYN);
+             return NULL;
             }
-            if (do_fileify_dirspec(vmsdir,trndir,0) == NULL) return NULL;
-            return do_tounixspec(trndir,buf,ts);
+            if (do_fileify_dirspec(vmsdir,trndir,0) == NULL) {
+               Safefree(trndir);
+               Safefree(vmsdir);
+               return NULL;
+           }
+           ret_chr = do_tounixspec(trndir,buf,ts);
+           Safefree(trndir);
+           Safefree(vmsdir);
+            return ret_chr;
           }
           cp1++;
         } while ((cp1 = strstr(cp1,"/.")) != NULL);
         lastdir = strrchr(trndir,'/');
       }
       else if (dirlen >= 7 && !strcmp(&trndir[dirlen-7],"/000000")) {
+       char * ret_chr;
         /* Ditto for specs that end in an MFD -- let the VMS code
          * figure out whether it's a real device or a rooted logical. */
 
@@ -4093,9 +4555,20 @@ static char *mp_do_fileify_dirspec(pTHX_ const char *dir,char *buf,int ts)
          */
 
         trndir[dirlen] = '/'; trndir[dirlen+1] = '\0';
-        if (do_tovmsspec(trndir,vmsdir,0) == NULL) return NULL;
-        if (do_fileify_dirspec(vmsdir,trndir,0) == NULL) return NULL;
-        return do_tounixspec(trndir,buf,ts);
+        if (do_tovmsspec(trndir,vmsdir,0) == NULL) {
+           Safefree(trndir);
+           Safefree(vmsdir);
+           return NULL;
+       }
+        if (do_fileify_dirspec(vmsdir,trndir,0) == NULL) {
+           Safefree(trndir);
+           Safefree(vmsdir);
+           return NULL;
+       }
+       ret_chr = do_tounixspec(trndir,buf,ts);
+       Safefree(trndir);
+       Safefree(vmsdir);
+        return ret_chr;
       }
       else {
 
@@ -4116,6 +4589,8 @@ static char *mp_do_fileify_dirspec(pTHX_ const char *dir,char *buf,int ts)
                   (*(cp2+4) && ((*(cp2+4) != ';' && *(cp2+4) != '.')  ||
                   (*(cp2+5) && ((ver = strtol(cp2+5,&cp3,10)) != 1 &&
                             (ver || *cp3)))))) {
+                 Safefree(trndir);
+                 Safefree(vmsdir);
                   set_errno(ENOTDIR);
                   set_vaxc_errno(RMS$_DIR);
                   return NULL;
@@ -4128,6 +4603,8 @@ static char *mp_do_fileify_dirspec(pTHX_ const char *dir,char *buf,int ts)
                   (*(cp2+4) && ((*(cp2+4) != ';' && *(cp2+4) != '.')  ||
                   (*(cp2+5) && ((ver = strtol(cp2+5,&cp3,10)) != 1 &&
                             (ver || *cp3)))))) {
+                Safefree(trndir);
+                Safefree(vmsdir);
                  set_errno(ENOTDIR);
                  set_vaxc_errno(RMS$_DIR);
                  return NULL;
@@ -4150,34 +4627,41 @@ static char *mp_do_fileify_dirspec(pTHX_ const char *dir,char *buf,int ts)
        strcat(retspec,".dir;1");
       else
        strcat(retspec,".DIR;1");
+      Safefree(trndir);
+      Safefree(vmsdir);
       return retspec;
     }
     else {  /* VMS-style directory spec */
-      char esa[NAM$C_MAXRSS+1], term, *cp;
+
+      char *esa, term, *cp;
       unsigned long int sts, cmplen, haslower = 0;
+      unsigned int nam_fnb;
+      char * nam_type;
       struct FAB dirfab = cc$rms_fab;
-      struct NAM savnam, dirnam = cc$rms_nam;
-
-      dirfab.fab$b_fns = strlen(trndir);
-      dirfab.fab$l_fna = trndir;
-      dirfab.fab$l_nam = &dirnam;
-      dirfab.fab$l_dna = ".DIR;1";
-      dirfab.fab$b_dns = 6;
-      dirnam.nam$b_ess = NAM$C_MAXRSS;
-      dirnam.nam$l_esa = esa;
+      rms_setup_nam(savnam);
+      rms_setup_nam(dirnam);
+
+      Newx(esa, VMS_MAXRSS + 1, char);
+      rms_set_fna(dirfab, dirnam, trndir, strlen(trndir));
+      rms_bind_fab_nam(dirfab, dirnam);
+      rms_set_dna(dirfab, dirnam, ".DIR;1", 6);
+      rms_set_esa(dirfab, dirnam, esa, (VMS_MAXRSS - 1));
 #ifdef NAM$M_NO_SHORT_UPCASE
       if (decc_efs_case_preserve)
-       dirnam.nam$b_nop |= NAM$M_NO_SHORT_UPCASE;
+       rms_set_nam_nop(dirnam, NAM$M_NO_SHORT_UPCASE);
 #endif
 
       for (cp = trndir; *cp; cp++)
         if (islower(*cp)) { haslower = 1; break; }
-      if (!((sts = sys$parse(&dirfab))&1)) {
+      if (!((sts = sys$parse(&dirfab)) & STS$K_SUCCESS)) {
         if ((dirfab.fab$l_sts == RMS$_DIR) || (dirfab.fab$l_sts == RMS$_DNF)) {
-          dirnam.nam$b_nop |= NAM$M_SYNCHK;
-          sts = sys$parse(&dirfab) & 1;
+         rms_set_nam_nop(dirnam, NAM$M_SYNCHK);
+          sts = sys$parse(&dirfab) & STS$K_SUCCESS;
         }
         if (!sts) {
+         Safefree(esa);
+         Safefree(trndir);
+         Safefree(vmsdir);
           set_errno(EVMSERR);
           set_vaxc_errno(dirfab.fab$l_sts);
           return NULL;
@@ -4185,60 +4669,69 @@ static char *mp_do_fileify_dirspec(pTHX_ const char *dir,char *buf,int ts)
       }
       else {
         savnam = dirnam;
-        if (sys$search(&dirfab)&1) {  /* Does the file really exist? */
+       /* Does the file really exist? */
+        if (sys$search(&dirfab)& STS$K_SUCCESS) { 
           /* Yes; fake the fnb bits so we'll check type below */
-          dirnam.nam$l_fnb |= NAM$M_EXP_TYPE | NAM$M_EXP_VER;
+       rms_set_nam_fnb(dirnam, (NAM$M_EXP_TYPE | NAM$M_EXP_VER));
         }
         else { /* No; just work with potential name */
           if (dirfab.fab$l_sts == RMS$_FNF) dirnam = savnam;
           else { 
+           Safefree(esa);
+           Safefree(trndir);
+           Safefree(vmsdir);
             set_errno(EVMSERR);  set_vaxc_errno(dirfab.fab$l_sts);
-            dirnam.nam$b_nop |= NAM$M_SYNCHK;  dirnam.nam$l_rlf = NULL;
-            dirfab.fab$b_dns = 0;  sts = sys$parse(&dirfab,0,0);
+           sts = rms_free_search_context(&dirfab);
             return NULL;
           }
         }
       }
-      if (!(dirnam.nam$l_fnb & (NAM$M_EXP_DEV | NAM$M_EXP_DIR))) {
+      if (!rms_is_nam_fnb(dirnam, (NAM$M_EXP_DEV | NAM$M_EXP_DIR))) {
         cp1 = strchr(esa,']');
         if (!cp1) cp1 = strchr(esa,'>');
         if (cp1) {  /* Should always be true */
-          dirnam.nam$b_esl -= cp1 - esa - 1;
-          memcpy(esa,cp1 + 1,dirnam.nam$b_esl);
+          rms_nam_esll(dirnam) -= cp1 - esa - 1;
+          memmove(esa,cp1 + 1, rms_nam_esll(dirnam));
         }
       }
-      if (dirnam.nam$l_fnb & NAM$M_EXP_TYPE) {  /* Was type specified? */
+      if (rms_is_nam_fnb(dirnam, NAM$M_EXP_TYPE)) {  /* Was type specified? */
         /* Yep; check version while we're at it, if it's there. */
-        cmplen = (dirnam.nam$l_fnb & NAM$M_EXP_VER) ? 6 : 4;
-        if (strncmp(dirnam.nam$l_type,".DIR;1",cmplen)) { 
+        cmplen = rms_is_nam_fnb(dirnam, NAM$M_EXP_VER) ? 6 : 4;
+        if (strncmp(rms_nam_typel(dirnam), ".DIR;1", cmplen)) { 
           /* Something other than .DIR[;1].  Bzzt. */
-          dirnam.nam$b_nop |= NAM$M_SYNCHK;  dirnam.nam$l_rlf = NULL;
-          dirfab.fab$b_dns = 0;  sts = sys$parse(&dirfab,0,0);
+         sts = rms_free_search_context(&dirfab);
+         Safefree(esa);
+         Safefree(trndir);
+         Safefree(vmsdir);
           set_errno(ENOTDIR);
           set_vaxc_errno(RMS$_DIR);
           return NULL;
         }
       }
-      esa[dirnam.nam$b_esl] = '\0';
-      if (dirnam.nam$l_fnb & NAM$M_EXP_NAME) {
+      esa[rms_nam_esll(dirnam)] = '\0';
+      if (rms_is_nam_fnb(dirnam, NAM$M_EXP_NAME)) {
         /* They provided at least the name; we added the type, if necessary, */
         if (buf) retspec = buf;                            /* in sys$parse() */
-        else if (ts) Newx(retspec,dirnam.nam$b_esl+1,char);
+        else if (ts) Newx(retspec, rms_nam_esll(dirnam)+1, char);
         else retspec = __fileify_retbuf;
         strcpy(retspec,esa);
-        dirnam.nam$b_nop |= NAM$M_SYNCHK;  dirnam.nam$l_rlf = NULL;
-        dirfab.fab$b_dns = 0;  sts = sys$parse(&dirfab,0,0);
+       sts = rms_free_search_context(&dirfab);
+       Safefree(trndir);
+       Safefree(esa);
+       Safefree(vmsdir);
         return retspec;
       }
       if ((cp1 = strstr(esa,".][000000]")) != NULL) {
         for (cp2 = cp1 + 9; *cp2; cp1++,cp2++) *cp1 = *cp2;
         *cp1 = '\0';
-        dirnam.nam$b_esl -= 9;
+        rms_nam_esll(dirnam) -= 9;
       }
       if ((cp1 = strrchr(esa,']')) == NULL) cp1 = strrchr(esa,'>');
       if (cp1 == NULL) { /* should never happen */
-        dirnam.nam$b_nop |= NAM$M_SYNCHK;  dirnam.nam$l_rlf = NULL;
-        dirfab.fab$b_dns = 0;  sts = sys$parse(&dirfab,0,0);
+       sts = rms_free_search_context(&dirfab);
+       Safefree(trndir);
+       Safefree(esa);
+       Safefree(vmsdir);
         return NULL;
       }
       term = *cp1;
@@ -4267,21 +4760,23 @@ static char *mp_do_fileify_dirspec(pTHX_ const char *dir,char *buf,int ts)
         strcpy(retspec,esa);
       }
       else {
-        if (dirnam.nam$l_fnb & NAM$M_ROOT_DIR) {
+        if (rms_is_nam_fnb(dirnam, NAM$M_ROOT_DIR)) {
           /* Go back and expand rooted logical name */
-          dirnam.nam$b_nop = NAM$M_SYNCHK | NAM$M_NOCONCEAL;
+          rms_set_nam_nop(dirnam, NAM$M_SYNCHK | NAM$M_NOCONCEAL);
 #ifdef NAM$M_NO_SHORT_UPCASE
          if (decc_efs_case_preserve)
-           dirnam.nam$b_nop |= NAM$M_NO_SHORT_UPCASE;
+           rms_set_nam_nop(dirnam, NAM$M_NO_SHORT_UPCASE);
 #endif
-          if (!(sys$parse(&dirfab) & 1)) {
-            dirnam.nam$l_rlf = NULL;
-            dirfab.fab$b_dns = 0;  sts = sys$parse(&dirfab,0,0);
+          if (!(sys$parse(&dirfab) & STS$K_SUCCESS)) {
+           sts = rms_free_search_context(&dirfab);
+           Safefree(esa);
+           Safefree(trndir);
+           Safefree(vmsdir);
             set_errno(EVMSERR);
             set_vaxc_errno(dirfab.fab$l_sts);
             return NULL;
           }
-          retlen = dirnam.nam$b_esl - 9; /* esa - '][' - '].DIR;1' */
+          retlen = rms_nam_esll(dirnam) - 9; /* esa - '][' - '].DIR;1' */
           if (buf) retspec = buf;
           else if (ts) Newx(retspec,retlen+16,char);
           else retspec = __fileify_retbuf;
@@ -4306,11 +4801,11 @@ static char *mp_do_fileify_dirspec(pTHX_ const char *dir,char *buf,int ts)
             if (*cp1 == '.') *cp1 = ']';
             else {
               memmove(cp1+8,cp1+1,retspec+dirlen-cp1);
-              memcpy(cp1+1,"000000]",7);
+              memmove(cp1+1,"000000]",7);
             }
           }
           else {
-            memcpy(retspec+dirlen,cp1+2,retlen-dirlen);
+            memmove(retspec+dirlen,cp1+2,retlen-dirlen);
             retspec[retlen] = '\0';
             /* Convert last '.' to ']' */
             cp1 = retspec+retlen-1;
@@ -4325,7 +4820,7 @@ static char *mp_do_fileify_dirspec(pTHX_ const char *dir,char *buf,int ts)
             if (*cp1 == '.') *cp1 = ']';
             else {
               memmove(cp1+8,cp1+1,retspec+dirlen-cp1);
-              memcpy(cp1+1,"000000]",7);
+              memmove(cp1+1,"000000]",7);
             }
           }
         }
@@ -4335,14 +4830,13 @@ static char *mp_do_fileify_dirspec(pTHX_ const char *dir,char *buf,int ts)
           else retspec = __fileify_retbuf;
           cp1 = esa;
           cp2 = retspec;
-          while (*cp1 != ':') *(cp2++) = *(cp1++);
+          while ((*cp1 != ':')  && (*cp1 != '\0')) *(cp2++) = *(cp1++);
           strcpy(cp2,":[000000]");
           cp1 += 2;
           strcpy(cp2+9,cp1);
         }
       }
-      dirnam.nam$b_nop |= NAM$M_SYNCHK;  dirnam.nam$l_rlf = NULL;
-      dirfab.fab$b_dns = 0;  sts = sys$parse(&dirfab,0,0);
+      sts = rms_free_search_context(&dirfab);
       /* We've set up the string up through the filename.  Add the
          type and version, and we're done. */
       strcat(retspec,".DIR;1");
@@ -4350,6 +4844,9 @@ static char *mp_do_fileify_dirspec(pTHX_ const char *dir,char *buf,int ts)
       /* $PARSE may have upcased filespec, so convert output to lower
        * case if input contained any lowercase characters. */
       if (haslower && !decc_efs_case_preserve) __mystrtolower(retspec);
+      Safefree(trndir);
+      Safefree(esa);
+      Safefree(vmsdir);
       return retspec;
     }
 }  /* end of do_fileify_dirspec() */
@@ -4363,9 +4860,9 @@ char *Perl_fileify_dirspec_ts(pTHX_ const char *dir, char *buf)
 /*{{{ char *pathify_dirspec[_ts](char *path, char *buf)*/
 static char *mp_do_pathify_dirspec(pTHX_ const char *dir,char *buf, int ts)
 {
-    static char __pathify_retbuf[NAM$C_MAXRSS+1];
+    static char __pathify_retbuf[VMS_MAXRSS];
     unsigned long int retlen;
-    char *retpath, *cp1, *cp2, trndir[NAM$C_MAXRSS+1];
+    char *retpath, *cp1, *cp2, *trndir;
     unsigned short int trnlnm_iter_count;
     STRLEN trnlen;
     int sts;
@@ -4374,8 +4871,9 @@ static char *mp_do_pathify_dirspec(pTHX_ const char *dir,char *buf, int ts)
       set_errno(EINVAL); set_vaxc_errno(SS$_BADPARAM); return NULL;
     }
 
+    Newx(trndir, VMS_MAXRSS, char);
     if (*dir) strcpy(trndir,dir);
-    else getcwd(trndir,sizeof trndir - 1);
+    else getcwd(trndir,VMS_MAXRSS - 1);
 
     trnlnm_iter_count = 0;
     while (!strpbrk(trndir,"/]:>") && !no_translate_barewords
@@ -4391,6 +4889,7 @@ static char *mp_do_pathify_dirspec(pTHX_ const char *dir,char *buf, int ts)
         else retpath = __pathify_retbuf;
         strcpy(retpath,dir);
         strcat(retpath,":[000000]");
+       Safefree(trndir);
         return retpath;
       }
     }
@@ -4425,6 +4924,7 @@ static char *mp_do_pathify_dirspec(pTHX_ const char *dir,char *buf, int ts)
                   (*(cp2+4) && ((*(cp2+4) != ';' && *(cp2+4) != '.')  ||
                   (*(cp2+5) && ((ver = strtol(cp2+5,&cp3,10)) != 1 &&
                             (ver || *cp3)))))) {
+               Safefree(trndir);
                 set_errno(ENOTDIR);
                 set_vaxc_errno(RMS$_DIR);
                 return NULL;
@@ -4437,6 +4937,7 @@ static char *mp_do_pathify_dirspec(pTHX_ const char *dir,char *buf, int ts)
                   (*(cp2+4) && ((*(cp2+4) != ';' && *(cp2+4) != '.')  ||
                   (*(cp2+5) && ((ver = strtol(cp2+5,&cp3,10)) != 1 &&
                             (ver || *cp3)))))) {
+               Safefree(trndir);
                 set_errno(ENOTDIR);
                 set_vaxc_errno(RMS$_DIR);
                 return NULL;
@@ -4459,10 +4960,12 @@ static char *mp_do_pathify_dirspec(pTHX_ const char *dir,char *buf, int ts)
       else retpath[retlen-1] = '\0';
     }
     else {  /* VMS-style directory spec */
-      char esa[NAM$C_MAXRSS+1], *cp;
+      char *esa, *cp;
       unsigned long int sts, cmplen, haslower;
       struct FAB dirfab = cc$rms_fab;
-      struct NAM savnam, dirnam = cc$rms_nam;
+      int dirlen;
+      rms_setup_nam(savnam);
+      rms_setup_nam(dirnam);
 
       /* If we've got an explicit filename, we can just shuffle the string. */
       if ( ( (cp1 = strrchr(trndir,']')) != NULL ||
@@ -4476,6 +4979,7 @@ static char *mp_do_pathify_dirspec(pTHX_ const char *dir,char *buf, int ts)
                   (*(cp2+4) && ((*(cp2+4) != ';' && *(cp2+4) != '.')  ||
                   (*(cp2+5) && ((ver = strtol(cp2+5,&cp3,10)) != 1 &&
                             (ver || *cp3)))))) {
+              Safefree(trndir);
                set_errno(ENOTDIR);
                set_vaxc_errno(RMS$_DIR);
                return NULL;
@@ -4488,6 +4992,7 @@ static char *mp_do_pathify_dirspec(pTHX_ const char *dir,char *buf, int ts)
                   (*(cp2+4) && ((*(cp2+4) != ';' && *(cp2+4) != '.')  ||
                   (*(cp2+5) && ((ver = strtol(cp2+5,&cp3,10)) != 1 &&
                             (ver || *cp3)))))) {
+              Safefree(trndir);
                set_errno(ENOTDIR);
                set_vaxc_errno(RMS$_DIR);
                return NULL;
@@ -4502,36 +5007,39 @@ static char *mp_do_pathify_dirspec(pTHX_ const char *dir,char *buf, int ts)
         *cp1 = '.';
         /* We've now got a VMS 'path'; fall through */
       }
-      dirfab.fab$b_fns = strlen(trndir);
-      dirfab.fab$l_fna = trndir;
-      if (trndir[dirfab.fab$b_fns-1] == ']' ||
-          trndir[dirfab.fab$b_fns-1] == '>' ||
-          trndir[dirfab.fab$b_fns-1] == ':') { /* It's already a VMS 'path' */
+
+      dirlen = strlen(trndir);
+      if (trndir[dirlen-1] == ']' ||
+          trndir[dirlen-1] == '>' ||
+          trndir[dirlen-1] == ':') { /* It's already a VMS 'path' */
         if (buf) retpath = buf;
         else if (ts) Newx(retpath,strlen(trndir)+1,char);
         else retpath = __pathify_retbuf;
         strcpy(retpath,trndir);
+       Safefree(trndir);
         return retpath;
-      } 
-      dirfab.fab$l_dna = ".DIR;1";
-      dirfab.fab$b_dns = 6;
-      dirfab.fab$l_nam = &dirnam;
-      dirnam.nam$b_ess = (unsigned char) sizeof esa - 1;
-      dirnam.nam$l_esa = esa;
+      }
+      rms_set_fna(dirfab, dirnam, trndir, dirlen);
+      Newx(esa, VMS_MAXRSS, char);
+      rms_set_dna(dirfab, dirnam, ".DIR;1", 6);
+      rms_bind_fab_nam(dirfab, dirnam);
+      rms_set_esa(dirfab, dirnam, esa, VMS_MAXRSS - 1);
 #ifdef NAM$M_NO_SHORT_UPCASE
       if (decc_efs_case_preserve)
-         dirnam.nam$b_nop |= NAM$M_NO_SHORT_UPCASE;
+         rms_set_nam_nop(dirnam, NAM$M_NO_SHORT_UPCASE);
 #endif
 
       for (cp = trndir; *cp; cp++)
         if (islower(*cp)) { haslower = 1; break; }
 
-      if (!(sts = (sys$parse(&dirfab)&1))) {
+      if (!(sts = (sys$parse(&dirfab)& STS$K_SUCCESS))) {
         if ((dirfab.fab$l_sts == RMS$_DIR) || (dirfab.fab$l_sts == RMS$_DNF)) {
-          dirnam.nam$b_nop |= NAM$M_SYNCHK;
-          sts = sys$parse(&dirfab) & 1;
+         rms_set_nam_nop(dirnam, NAM$M_SYNCHK);
+          sts = sys$parse(&dirfab) & STS$K_SUCCESS;
         }
         if (!sts) {
+         Safefree(trndir);
+         Safefree(esa);
           set_errno(EVMSERR);
           set_vaxc_errno(dirfab.fab$l_sts);
           return NULL;
@@ -4539,12 +5047,13 @@ static char *mp_do_pathify_dirspec(pTHX_ const char *dir,char *buf, int ts)
       }
       else {
         savnam = dirnam;
-        if (!(sys$search(&dirfab)&1)) {  /* Does the file really exist? */
+       /* Does the file really exist? */
+        if (!(sys$search(&dirfab)&STS$K_SUCCESS)) {
           if (dirfab.fab$l_sts != RMS$_FNF) {
            int sts1;
-            dirnam.nam$b_nop |= NAM$M_SYNCHK;  dirnam.nam$l_rlf = NULL;
-            dirfab.fab$b_dns = 0;
-           sts1 = sys$parse(&dirfab,0,0);
+           sts1 = rms_free_search_context(&dirfab);
+           Safefree(trndir);
+           Safefree(esa);
             set_errno(EVMSERR);
             set_vaxc_errno(dirfab.fab$l_sts);
             return NULL;
@@ -4552,15 +5061,15 @@ static char *mp_do_pathify_dirspec(pTHX_ const char *dir,char *buf, int ts)
           dirnam = savnam; /* No; just work with potential name */
         }
       }
-      if (dirnam.nam$l_fnb & NAM$M_EXP_TYPE) {  /* Was type specified? */
+      if (rms_is_nam_fnb(dirnam, NAM$M_EXP_TYPE)) {  /* Was type specified? */
         /* Yep; check version while we're at it, if it's there. */
-        cmplen = (dirnam.nam$l_fnb & NAM$M_EXP_VER) ? 6 : 4;
-        if (strncmp(dirnam.nam$l_type,".DIR;1",cmplen)) { 
+        cmplen = rms_is_nam_fnb(dirnam, NAM$M_EXP_VER) ? 6 : 4;
+        if (strncmp(rms_nam_typel(dirnam),".DIR;1",cmplen)) {
          int sts2;
           /* Something other than .DIR[;1].  Bzzt. */
-          dirnam.nam$b_nop |= NAM$M_SYNCHK;  dirnam.nam$l_rlf = NULL;
-          dirfab.fab$b_dns = 0;
-         sts2 = sys$parse(&dirfab,0,0);
+         sts2 = rms_free_search_context(&dirfab);
+         Safefree(trndir);
+         Safefree(esa);
           set_errno(ENOTDIR);
           set_vaxc_errno(RMS$_DIR);
           return NULL;
@@ -4568,25 +5077,26 @@ static char *mp_do_pathify_dirspec(pTHX_ const char *dir,char *buf, int ts)
       }
       /* OK, the type was fine.  Now pull any file name into the
          directory path. */
-      if ((cp1 = strrchr(esa,']'))) *dirnam.nam$l_type = ']';
+      if ((cp1 = strrchr(esa,']'))) *(rms_nam_typel(dirnam)) = ']';
       else {
         cp1 = strrchr(esa,'>');
-        *dirnam.nam$l_type = '>';
+        *(rms_nam_typel(dirnam)) = '>';
       }
       *cp1 = '.';
-      *(dirnam.nam$l_type + 1) = '\0';
-      retlen = dirnam.nam$l_type - esa + 2;
+      *(rms_nam_typel(dirnam) + 1) = '\0';
+      retlen = (rms_nam_typel(dirnam)) - esa + 2;
       if (buf) retpath = buf;
       else if (ts) Newx(retpath,retlen,char);
       else retpath = __pathify_retbuf;
       strcpy(retpath,esa);
-      dirnam.nam$b_nop |= NAM$M_SYNCHK;  dirnam.nam$l_rlf = NULL;
-      dirfab.fab$b_dns = 0;  sts = sys$parse(&dirfab,0,0);
+      Safefree(esa);
+      sts = rms_free_search_context(&dirfab);
       /* $PARSE may have upcased filespec, so convert output to lower
        * case if input contained any lowercase characters. */
       if (haslower && !decc_efs_case_preserve) __mystrtolower(retpath);
     }
 
+    Safefree(trndir);
     return retpath;
 }  /* end of do_pathify_dirspec() */
 /*}}}*/
@@ -4599,10 +5109,10 @@ char *Perl_pathify_dirspec_ts(pTHX_ const char *dir, char *buf)
 /*{{{ char *tounixspec[_ts](char *spec, char *buf)*/
 static char *mp_do_tounixspec(pTHX_ const char *spec, char *buf, int ts)
 {
-  static char __tounixspec_retbuf[NAM$C_MAXRSS+1];
-  char *dirend, *rslt, *cp1, *cp3, tmp[NAM$C_MAXRSS+1];
+  static char __tounixspec_retbuf[VMS_MAXRSS];
+  char *dirend, *rslt, *cp1, *cp3, tmp[VMS_MAXRSS];
   const char *cp2;
-  int devlen, dirlen, retlen = NAM$C_MAXRSS+1;
+  int devlen, dirlen, retlen = VMS_MAXRSS;
   int expand = 1; /* guarantee room for leading and trailing slashes */
   unsigned short int trnlnm_iter_count;
   int cmp_rslt;
@@ -4921,14 +5431,14 @@ int unixlen;
   vmspath[vmspath_len] = 0;
   if (unixpath[unixlen - 1] == '/')
   dir_flag = 1;
-  Newx(esa, VMS_MAXRSS+1, char);
+  Newx(esa, VMS_MAXRSS, char);
   myfab.fab$l_fna = vmspath;
   myfab.fab$b_fns = strlen(vmspath);
   myfab.fab$l_naml = &mynam;
   mynam.naml$l_esa = NULL;
   mynam.naml$b_ess = 0;
   mynam.naml$l_long_expand = esa;
-  mynam.naml$l_long_expand_alloc = (unsigned char) VMS_MAXRSS;
+  mynam.naml$l_long_expand_alloc = (unsigned char) VMS_MAXRSS - 1;
   mynam.naml$l_rsa = NULL;
   mynam.naml$b_rss = 0;
   if (decc_efs_case_preserve)
@@ -5526,7 +6036,7 @@ int quoted;
 
 /*{{{ char *tovmsspec[_ts](char *path, char *buf)*/
 static char *mp_do_tovmsspec(pTHX_ const char *path, char *buf, int ts) {
-  static char __tovmsspec_retbuf[NAM$C_MAXRSS+1];
+  static char __tovmsspec_retbuf[VMS_MAXRSS];
   char *rslt, *dirend;
   char *lastdot;
   char *vms_delim;
@@ -5539,7 +6049,7 @@ static char *mp_do_tovmsspec(pTHX_ const char *path, char *buf, int ts) {
   if (path == NULL) return NULL;
   rslt_len = VMS_MAXRSS;
   if (buf) rslt = buf;
-  else if (ts) Newx(rslt,NAM$C_MAXRSS+1,char);
+  else if (ts) Newx(rslt, VMS_MAXRSS, char);
   else rslt = __tovmsspec_retbuf;
   if (strpbrk(path,"]:>") ||
       (dirend = strrchr(path,'/')) == NULL) {
@@ -5626,7 +6136,7 @@ static char *mp_do_tovmsspec(pTHX_ const char *path, char *buf, int ts) {
   cp2 = path;
   lastdot = strrchr(cp2,'.');
   if (*cp2 == '/') {
-    char trndev[NAM$C_MAXRSS+1];
+    char *trndev;
     int islnm, rooted;
     STRLEN trnend;
 
@@ -5642,6 +6152,7 @@ static char *mp_do_tovmsspec(pTHX_ const char *path, char *buf, int ts) {
     }
     while (*(++cp2) != '/' && *cp2) *(cp1++) = *cp2;
     *cp1 = '\0';
+    Newx(trndev, VMS_MAXRSS, char);
     islnm =  my_trnlnm(rslt,trndev,0);
 
      /* DECC special handling */
@@ -5692,7 +6203,6 @@ static char *mp_do_tovmsspec(pTHX_ const char *path, char *buf, int ts) {
     }
     else {
       if (cp2 != dirend) {
-        if (!buf && ts) Renew(rslt,strlen(path)-strlen(rslt)+trnend+4,char);
         strcpy(rslt,trndev);
         cp1 = rslt + trnend;
        if (*cp2 != 0) {
@@ -5707,6 +6217,7 @@ static char *mp_do_tovmsspec(pTHX_ const char *path, char *buf, int ts) {
        }
       }
     }
+    Safefree(trndev);
   }
   else {
     *(cp1++) = '[';
@@ -5889,23 +6400,38 @@ char *Perl_tovmsspec_ts(pTHX_ const char *path, char *buf) { return do_tovmsspec
 
 /*{{{ char *tovmspath[_ts](char *path, char *buf)*/
 static char *mp_do_tovmspath(pTHX_ const char *path, char *buf, int ts) {
-  static char __tovmspath_retbuf[NAM$C_MAXRSS+1];
+  static char __tovmspath_retbuf[VMS_MAXRSS];
   int vmslen;
-  char pathified[NAM$C_MAXRSS+1], vmsified[NAM$C_MAXRSS+1], *cp;
+  char *pathified, *vmsified, *cp;
 
   if (path == NULL) return NULL;
-  if (do_pathify_dirspec(path,pathified,0) == NULL) return NULL;
-  if (do_tovmsspec(pathified,buf ? buf : vmsified,0) == NULL) return NULL;
-  if (buf) return buf;
+  Newx(pathified, VMS_MAXRSS, char);
+  if (do_pathify_dirspec(path,pathified,0) == NULL) {
+    Safefree(pathified);
+    return NULL;
+  }
+  Newx(vmsified, VMS_MAXRSS, char);
+  if (do_tovmsspec(pathified,buf ? buf : vmsified,0) == NULL) {
+    Safefree(pathified);
+    Safefree(vmsified);
+    return NULL;
+  }
+  Safefree(pathified);
+  if (buf) {
+    Safefree(vmsified);
+    return buf;
+  }
   else if (ts) {
     vmslen = strlen(vmsified);
     Newx(cp,vmslen+1,char);
     memcpy(cp,vmsified,vmslen);
     cp[vmslen] = '\0';
+    Safefree(vmsified);
     return cp;
   }
   else {
     strcpy(__tovmspath_retbuf,vmsified);
+    Safefree(vmsified);
     return __tovmspath_retbuf;
   }
 
@@ -5918,23 +6444,38 @@ char *Perl_tovmspath_ts(pTHX_ const char *path, char *buf) { return do_tovmspath
 
 /*{{{ char *tounixpath[_ts](char *path, char *buf)*/
 static char *mp_do_tounixpath(pTHX_ const char *path, char *buf, int ts) {
-  static char __tounixpath_retbuf[NAM$C_MAXRSS+1];
+  static char __tounixpath_retbuf[VMS_MAXRSS];
   int unixlen;
-  char pathified[NAM$C_MAXRSS+1], unixified[NAM$C_MAXRSS+1], *cp;
+  char *pathified, *unixified, *cp;
 
   if (path == NULL) return NULL;
-  if (do_pathify_dirspec(path,pathified,0) == NULL) return NULL;
-  if (do_tounixspec(pathified,buf ? buf : unixified,0) == NULL) return NULL;
-  if (buf) return buf;
+  Newx(pathified, VMS_MAXRSS, char);
+  if (do_pathify_dirspec(path,pathified,0) == NULL) {
+    Safefree(pathified);
+    return NULL;
+  }
+  Newx(unixified, VMS_MAXRSS, char);
+  if (do_tounixspec(pathified,buf ? buf : unixified,0) == NULL) {
+    Safefree(pathified);
+    Safefree(unixified);
+    return NULL;
+  }
+  Safefree(pathified);
+  if (buf) {
+    Safefree(unixified);
+    return buf;
+  }
   else if (ts) {
     unixlen = strlen(unixified);
     Newx(cp,unixlen+1,char);
     memcpy(cp,unixified,unixlen);
     cp[unixlen] = '\0';
+    Safefree(unixified);
     return cp;
   }
   else {
     strcpy(__tounixpath_retbuf,unixified);
+    Safefree(unixified);
     return __tounixpath_retbuf;
   }
 
@@ -6147,6 +6688,7 @@ mp_getredirection(pTHX_ int *ac, char ***av)
      * the list with an extra null pointer.
      */
     Newx(argv, item_count+1, char *);
+    argv = (char **) PerlMem_malloc((item_count+1) * sizeof(char *));
     *av = argv;
     for (j = 0; j < item_count; ++j, list_head = list_head->next)
        argv[j] = list_head->value;
@@ -6241,11 +6783,11 @@ static void add_item(struct list_item **head,
 {
     if (*head == 0)
        {
-       Newx(*head,1,struct list_item);
+       *head = (struct list_item *) PerlMem_malloc(sizeof(struct list_item));
        *tail = *head;
        }
     else {
-       Newx((*tail)->next,1,struct list_item);
+       (*tail)->next = (struct list_item *) PerlMem_malloc(sizeof(struct list_item));
        *tail = (*tail)->next;
        }
     (*tail)->value = value;
@@ -6265,11 +6807,16 @@ char *had_version;
 char *had_device;
 int had_directory;
 char *devdir,*cp;
-char vmsspec[NAM$C_MAXRSS+1];
+char *vmsspec;
 $DESCRIPTOR(filespec, "");
 $DESCRIPTOR(defaultspec, "SYS$DISK:[]");
 $DESCRIPTOR(resultspec, "");
-unsigned long int zero = 0, sts;
+unsigned long int lff_flags = 0;
+int sts;
+
+#ifdef VMS_LONGNAME_SUPPORT
+    lff_flags = LIB$M_FIL_LONG_NAMES;
+#endif
 
     for (cp = item; *cp; cp++) {
        if (*cp == '*' || *cp == '%' || isspace(*cp)) break;
@@ -6297,6 +6844,7 @@ unsigned long int zero = 0, sts;
     resultspec.dsc$b_dtype = DSC$K_DTYPE_T;
     resultspec.dsc$b_class = DSC$K_CLASS_D;
     resultspec.dsc$a_pointer = NULL;
+    Newx(vmsspec, VMS_MAXRSS, char);
     if ((isunix = (int) strchr(item,'/')) != (int) NULL)
       filespec.dsc$a_pointer = do_tovmsspec(item,vmsspec,0);
     if (!isunix || !filespec.dsc$a_pointer)
@@ -6312,8 +6860,9 @@ unsigned long int zero = 0, sts;
     had_device = strchr(item, ':');
     had_directory = (isunix || NULL != strchr(item, '[')) || (NULL != strchr(item, '<'));
     
-    while (1 == (1 & (sts = lib$find_file(&filespec, &resultspec, &context,
-                                 &defaultspec, 0, 0, &zero))))
+    while ($VMS_STATUS_SUCCESS(sts = lib$find_file
+                                (&filespec, &resultspec, &context,
+                                 &defaultspec, 0, 0, &lff_flags)))
        {
        char *string;
        char *c;
@@ -6341,7 +6890,8 @@ unsigned long int zero = 0, sts;
        if (isunix) trim_unixpath(string,item,1);
        add_item(head, tail, string, count);
        ++expcount;
-       }
+    }
+    Safefree(vmsspec);
     if (sts != RMS$_NMF)
        {
        set_vaxc_errno(sts);
@@ -6461,7 +7011,7 @@ pipe_and_fork(pTHX_ char **cmargv)
 
 static int background_process(pTHX_ int argc, char **argv)
 {
-char command[2048] = "$";
+char command[MAX_DCL_SYMBOL + 1] = "$";
 $DESCRIPTOR(value, "");
 static $DESCRIPTOR(cmd, "BACKGROUND$COMMAND");
 static $DESCRIPTOR(null, "NLA0:");
@@ -6470,13 +7020,16 @@ char pidstring[80];
 $DESCRIPTOR(pidstr, "");
 int pid;
 unsigned long int flags = 17, one = 1, retsts;
+int len;
 
     strcat(command, argv[0]);
-    while (--argc)
+    len = strlen(command);
+    while (--argc && (len < MAX_DCL_SYMBOL))
        {
        strcat(command, " \"");
        strcat(command, *(++argv));
        strcat(command, "\"");
+       len = strlen(command);
        }
     value.dsc$a_pointer = command;
     value.dsc$w_length = strlen(value.dsc$a_pointer);
@@ -6510,6 +7063,8 @@ unsigned long int flags = 17, one = 1, retsts;
 #ifndef KGB$M_SUBSYSTEM
 #  define KGB$M_SUBSYSTEM 0x8
 #endif
+/* Avoid Newx() in vms_image_init as thread context has not been initialized. */
 
 /*{{{void vms_image_init(int *, char ***)*/
 void
@@ -6559,8 +7114,8 @@ vms_image_init(int *argcp, char ***argvp)
                          "Check your rights database for corruption.\n");
          exit(SS$_ABORT);
       }
-      if (jpilist[1].bufadr != rlst) Safefree(jpilist[1].bufadr);
-      jpilist[1].bufadr = Newx(mask,rsz,unsigned long int);
+      if (jpilist[1].bufadr != rlst) PerlMem_free(jpilist[1].bufadr);
+      jpilist[1].bufadr = mask = (unsigned long int *) PerlMem_malloc(rsz * sizeof(unsigned long int));
       jpilist[1].buflen = rsz * sizeof(unsigned long int);
       _ckvmssts_noperl(sys$getjpiw(0,NULL,NULL,&jpilist[1],iosb,NULL,NULL));
       _ckvmssts_noperl(iosb[0]);
@@ -6611,9 +7166,9 @@ vms_image_init(int *argcp, char ***argvp)
   if (will_taint) {
     char **newargv, **oldargv;
     oldargv = *argvp;
-    Newx(newargv,(*argcp)+2,char *);
+    newargv = (char **) PerlMem_malloc(((*argcp)+2) * sizeof(char *));
     newargv[0] = oldargv[0];
-    Newx(newargv[1],3,char);
+    newargv[1] = (char *) PerlMem_malloc(3 * sizeof(char));
     strcpy(newargv[1], "-T");
     Copy(&oldargv[1],&newargv[2],(*argcp)-1,char **);
     (*argcp)++;
@@ -6640,12 +7195,12 @@ vms_image_init(int *argcp, char ***argvp)
   for (tabidx = 0;
        len = my_trnlnm("PERL_ENV_TABLES",eqv,tabidx);
        tabidx++) {
-    if (!tabidx) Newx(tabvec,tabct,struct dsc$descriptor_s *);
+    if (!tabidx) tabvec = (struct dsc$descriptor_s **) PerlMem_malloc(tabct * sizeof(struct dsc$descriptor_s *));
     else if (tabidx >= tabct) {
       tabct += 8;
-      Renew(tabvec,tabct,struct dsc$descriptor_s *);
+      tabvec = (struct dsc$descriptor_s **) PerlMem_realloc(tabvec, tabct * sizeof(struct dsc$descriptor_s *));
     }
-    Newx(tabvec[tabidx],1,struct dsc$descriptor_s);
+    tabvec[tabidx] = (struct dsc$descriptor_s *) PerlMem_malloc(sizeof(struct dsc$descriptor_s));
     tabvec[tabidx]->dsc$w_length  = 0;
     tabvec[tabidx]->dsc$b_dtype   = DSC$K_DTYPE_T;
     tabvec[tabidx]->dsc$b_class   = DSC$K_CLASS_D;
@@ -6685,21 +7240,30 @@ vms_image_init(int *argcp, char ***argvp)
 int
 Perl_trim_unixpath(pTHX_ char *fspec, const char *wildspec, int opts)
 {
-  char unixified[NAM$C_MAXRSS+1], unixwild[NAM$C_MAXRSS+1],
+  char *unixified, *unixwild,
        *template, *base, *end, *cp1, *cp2;
   register int tmplen, reslen = 0, dirs = 0;
 
+  Newx(unixwild, VMS_MAXRSS, char);
   if (!wildspec || !fspec) return 0;
   template = unixwild;
   if (strpbrk(wildspec,"]>:") != NULL) {
-    if (do_tounixspec(wildspec,unixwild,0) == NULL) return 0;
+    if (do_tounixspec(wildspec,unixwild,0) == NULL) {
+       Safefree(unixwild);
+       return 0;
+    }
   }
   else {
-    strncpy(unixwild, wildspec, NAM$C_MAXRSS);
-    unixwild[NAM$C_MAXRSS] = 0;
+    strncpy(unixwild, wildspec, VMS_MAXRSS-1);
+    unixwild[VMS_MAXRSS-1] = 0;
   }
+  Newx(unixified, VMS_MAXRSS, char);
   if (strpbrk(fspec,"]>:") != NULL) {
-    if (do_tounixspec(fspec,unixified,0) == NULL) return 0;
+    if (do_tounixspec(fspec,unixified,0) == NULL) {
+       Safefree(unixwild);
+       Safefree(unixified);
+       return 0;
+    }
     else base = unixified;
     /* reslen != 0 ==> we had to unixify resultant filespec, so we must
      * check to see that final result fits into (isn't longer than) fspec */
@@ -6709,11 +7273,19 @@ Perl_trim_unixpath(pTHX_ char *fspec, const char *wildspec, int opts)
 
   /* No prefix or absolute path on wildcard, so nothing to remove */
   if (!*template || *template == '/') {
-    if (base == fspec) return 1;
+    Safefree(unixwild);
+    if (base == fspec) {
+       Safefree(unixified);
+       return 1;
+    }
     tmplen = strlen(unixified);
-    if (tmplen > reslen) return 0;  /* not enough space */
+    if (tmplen > reslen) {
+       Safefree(unixified);
+       return 0;  /* not enough space */
+    }
     /* Copy unixified resultant, including trailing NUL */
     memmove(fspec,unixified,tmplen+1);
+    Safefree(unixified);
     return 1;
   }
 
@@ -6724,18 +7296,21 @@ Perl_trim_unixpath(pTHX_ char *fspec, const char *wildspec, int opts)
       if ((*cp1 == '/') && !dirs--) /* postdec so we get front of rel path */
         { cp1++; break; }
     if (cp1 != fspec) memmove(fspec,cp1, end - cp1 + 1);
+    Safefree(unixified);
+    Safefree(unixwild);
     return 1;
   }
   else {
-    char tpl[NAM$C_MAXRSS+1], lcres[NAM$C_MAXRSS+1];
+    char *tpl, *lcres;
     char *front, *nextell, *lcend, *lcfront, *ellipsis = cp1;
     int ells = 1, totells, segdirs, match;
-    struct dsc$descriptor_s wilddsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, tpl},
+    struct dsc$descriptor_s wilddsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL},
                             resdsc =  {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
 
     while ((cp1 = strstr(ellipsis+4,".../")) != NULL) {ellipsis = cp1; ells++;}
     totells = ells;
     for (cp1 = ellipsis+4; *cp1; cp1++) if (*cp1 == '/') dirs++;
+    Newx(tpl, VMS_MAXRSS, char);
     if (ellipsis == template && opts & 1) {
       /* Template begins with an ellipsis.  Since we can't tell how many
        * directory names at the front of the resultant to keep for an
@@ -6745,7 +7320,12 @@ Perl_trim_unixpath(pTHX_ char *fspec, const char *wildspec, int opts)
        * ellipsis weren't there (i.e. return shortest possible path that
        * could match template).
        */
-      if (getcwd(tpl, sizeof tpl,0) == NULL) return 0;
+      if (getcwd(tpl, (VMS_MAXRSS - 1),0) == NULL) {
+         Safefree(tpl);
+         Safefree(unixified);
+         Safefree(unixwild);
+         return 0;
+      }
       if (!decc_efs_case_preserve) {
        for (cp1 = tpl, cp2 = base; *cp1 && *cp2; cp1++,cp2++)
          if (_tolower(*cp1) != _tolower(*cp2)) break;
@@ -6753,7 +7333,10 @@ Perl_trim_unixpath(pTHX_ char *fspec, const char *wildspec, int opts)
       segdirs = dirs - totells;  /* Min # of dirs we must have left */
       for (front = cp2+1; *front; front++) if (*front == '/') segdirs--;
       if (*cp1 == '\0' && *cp2 == '/' && segdirs < 1) {
-        memcpy(fspec,cp2+1,end - cp2);
+        memmove(fspec,cp2+1,end - cp2);
+       Safefree(unixified);
+       Safefree(unixwild);
+       Safefree(tpl);
         return 1;
       }
     }
@@ -6762,11 +7345,23 @@ Perl_trim_unixpath(pTHX_ char *fspec, const char *wildspec, int opts)
       for (front = end ; front >= base; front--)
          if (*front == '/' && !dirs--) { front++; break; }
     }
-    if (!decc_efs_case_preserve) {
-      for (cp1=template,cp2=lcres; *cp1 && cp2 <= lcres + sizeof lcres;
-         cp1++,cp2++) *cp2 = _tolower(*cp1);  /* Make lc copy for match */
+    Newx(lcres, VMS_MAXRSS, char);
+    for (cp1=template,cp2=lcres; *cp1 && cp2 <= lcres + (VMS_MAXRSS - 1);
+         cp1++,cp2++) {
+           if (!decc_efs_case_preserve) {
+               *cp2 = _tolower(*cp1);  /* Make lc copy for match */
+           }
+           else {
+               *cp2 = *cp1;
+           }
+    }
+    if (cp1 != '\0') {
+       Safefree(unixified);
+       Safefree(unixwild);
+       Safefree(lcres);
+       Safefree(tpl);
+       return 0;  /* Path too long. */
     }
-    if (cp1 != '\0') return 0;  /* Path too long. */
     lcend = cp2;
     *cp2 = '\0';  /* Pick up with memcpy later */
     lcfront = lcres + (front - base);
@@ -6779,10 +7374,11 @@ Perl_trim_unixpath(pTHX_ char *fspec, const char *wildspec, int opts)
       if (cp1 + 4 == ellipsis) { /* Consecutive ellipses */
         ellipsis = cp1; continue;
       }
+      wilddsc.dsc$a_pointer = tpl;
       wilddsc.dsc$w_length = resdsc.dsc$w_length = ellipsis - 1 - cp1;
       nextell = cp1;
       for (segdirs = 0, cp2 = tpl;
-           cp1 <= ellipsis - 1 && cp2 <= tpl + sizeof tpl;
+           cp1 <= ellipsis - 1 && cp2 <= tpl + (VMS_MAXRSS-1);
            cp1++, cp2++) {
          if (*cp1 == '?') *cp2 = '%'; /* Substitute VMS' wildcard for Unix' */
          else {
@@ -6795,7 +7391,13 @@ Perl_trim_unixpath(pTHX_ char *fspec, const char *wildspec, int opts)
         }
          if (*cp2 == '/') segdirs++;
       }
-      if (cp1 != ellipsis - 1) return 0; /* Path too long */
+      if (cp1 != ellipsis - 1) {
+         Safefree(unixified);
+         Safefree(unixwild);
+         Safefree(lcres);
+         Safefree(tpl);
+         return 0; /* Path too long */
+      }
       /* Back up at least as many dirs as in template before matching */
       for (cp1 = lcfront - 1; segdirs && cp1 >= lcres; cp1--)
         if (*cp1 == '/' && !segdirs--) { cp1++; break; }
@@ -6807,7 +7409,13 @@ Perl_trim_unixpath(pTHX_ char *fspec, const char *wildspec, int opts)
         }
         for ( ; cp1 >= lcres; cp1--) if (*cp1 == '/') { cp1++; break; }
       }
-      if (!match) return 0;  /* Can't find prefix ??? */
+      if (!match) {
+       Safefree(unixified);
+       Safefree(unixwild);
+       Safefree(lcres);
+       Safefree(tpl);
+       return 0;  /* Can't find prefix ??? */
+      }
       if (match > 1 && opts & 1) {
         /* This ... wildcard could cover more than one set of dirs (i.e.
          * a set of similar dir names is repeated).  If the template
@@ -6819,7 +7427,13 @@ Perl_trim_unixpath(pTHX_ char *fspec, const char *wildspec, int opts)
          */
         char def[NAM$C_MAXRSS+1], *st;
 
-        if (getcwd(def, sizeof def,0) == NULL) return 0;
+        if (getcwd(def, sizeof def,0) == NULL) {
+           Safefree(unixified);
+           Safefree(unixwild);
+           Safefree(lcres);
+           Safefree(tpl);
+           return 0;
+       }
        if (!decc_efs_case_preserve) {
          for (cp1 = def, cp2 = base; *cp1 && *cp2; cp1++,cp2++)
            if (_tolower(*cp1) != _tolower(*cp2)) break;
@@ -6827,13 +7441,21 @@ Perl_trim_unixpath(pTHX_ char *fspec, const char *wildspec, int opts)
         segdirs = dirs - totells;  /* Min # of dirs we must have left */
         for (st = cp2+1; *st; st++) if (*st == '/') segdirs--;
         if (*cp1 == '\0' && *cp2 == '/') {
-          memcpy(fspec,cp2+1,end - cp2);
+          memmove(fspec,cp2+1,end - cp2);
+         Safefree(lcres);
+         Safefree(unixified);
+         Safefree(unixwild);
+         Safefree(tpl);
           return 1;
         }
         /* Nope -- stick with lcfront from above and keep going. */
       }
     }
-    memcpy(fspec,base + (lcfront - lcres), lcend - lcfront + 1);
+    memmove(fspec,base + (lcfront - lcres), lcend - lcfront + 1);
+    Safefree(unixified);
+    Safefree(unixwild);
+    Safefree(lcres);
+    Safefree(tpl);
     return 1;
     ellipsis = nextell;
   }
@@ -6869,10 +7491,10 @@ Perl_trim_unixpath(pTHX_ char *fspec, const char *wildspec, int opts)
  *  Open a directory, return a handle for later use.
  */
 /*{{{ DIR *opendir(char*name) */
-MY_DIR *
+DIR *
 Perl_opendir(pTHX_ const char *name)
 {
-    MY_DIR *dd;
+    DIR *dd;
     char dir[NAM$C_MAXRSS+1];
     Stat_t sb;
 
@@ -6892,7 +7514,7 @@ Perl_opendir(pTHX_ const char *name)
       return NULL;
     }
     /* Get memory for the handle, and the pattern. */
-    Newx(dd,1,MY_DIR);
+    Newx(dd,1,DIR);
     Newx(dd->pattern,strlen(dir)+sizeof "*.*" + 1,char);
 
     /* Fill in the fields; mainly playing with the descriptor. */
@@ -6920,7 +7542,7 @@ Perl_opendir(pTHX_ const char *name)
  */
 /*{{{ void vmsreaddirversions(DIR *dd, int flag)*/
 void
-vmsreaddirversions(MY_DIR *dd, int flag)
+vmsreaddirversions(DIR *dd, int flag)
 {
     dd->vms_wantversions = flag;
 }
@@ -6931,7 +7553,7 @@ vmsreaddirversions(MY_DIR *dd, int flag)
  */
 /*{{{ void closedir(DIR *dd)*/
 void
-Perl_closedir(MY_DIR *dd)
+Perl_closedir(DIR *dd)
 {
     int sts;
 
@@ -6949,11 +7571,11 @@ Perl_closedir(MY_DIR *dd)
  *  Collect all the version numbers for the current file.
  */
 static void
-collectversions(pTHX_ MY_DIR *dd)
+collectversions(pTHX_ DIR *dd)
 {
     struct dsc$descriptor_s    pat;
     struct dsc$descriptor_s    res;
-    struct my_dirent *e;
+    struct dirent *e;
     char *p, *text, buff[sizeof dd->entry.d_name];
     int i;
     unsigned long context, tmpsts;
@@ -7002,8 +7624,8 @@ collectversions(pTHX_ MY_DIR *dd)
  *  Read the next entry from the directory.
  */
 /*{{{ struct dirent *readdir(DIR *dd)*/
-struct my_dirent *
-Perl_readdir(pTHX_ MY_DIR *dd)
+struct dirent *
+Perl_readdir(pTHX_ DIR *dd)
 {
     struct dsc$descriptor_s    res;
     char *p, buff[sizeof dd->entry.d_name];
@@ -7068,7 +7690,7 @@ Perl_readdir(pTHX_ MY_DIR *dd)
  */
 /*{{{ int readdir_r(DIR *dd, struct dirent *entry, struct dirent **result)*/
 int
-Perl_readdir_r(pTHX_ MY_DIR *dd, struct my_dirent *entry, struct my_dirent **result)
+Perl_readdir_r(pTHX_ DIR *dd, struct dirent *entry, struct dirent **result)
 {
     int retval;
 
@@ -7090,7 +7712,7 @@ Perl_readdir_r(pTHX_ MY_DIR *dd, struct my_dirent *entry, struct my_dirent **res
  */
 /*{{{ long telldir(DIR *dd)*/
 long
-Perl_telldir(MY_DIR *dd)
+Perl_telldir(DIR *dd)
 {
     return dd->count;
 }
@@ -7101,7 +7723,7 @@ Perl_telldir(MY_DIR *dd)
  */
 /*{{{ void seekdir(DIR *dd,long count)*/
 void
-Perl_seekdir(pTHX_ MY_DIR *dd, long count)
+Perl_seekdir(pTHX_ DIR *dd, long count)
 {
     int vms_wantversions;
 
@@ -8904,7 +9526,7 @@ is_null_device(name)
  * subset of the applicable information.
  */
 bool
-Perl_cando(pTHX_ Mode_t bit, Uid_t effective, const Stat_t *statbufp)
+Perl_cando(pTHX_ Mode_t bit, bool effective, const Stat_t *statbufp)
 {
   char fname_phdev[NAM$C_MAXRSS+1];
 #if __CRTL_VER >= 80200000 && !defined(__VAX)
@@ -8957,9 +9579,9 @@ Perl_cando(pTHX_ Mode_t bit, Uid_t effective, const Stat_t *statbufp)
 /*}}}*/
 
 
-/*{{{I32 cando_by_name(I32 bit, Uid_t effective, char *fname)*/
+/*{{{I32 cando_by_name(I32 bit, bool effective, char *fname)*/
 I32
-Perl_cando_by_name(pTHX_ I32 bit, Uid_t effective, const char *fname)
+Perl_cando_by_name(pTHX_ I32 bit, bool effective, const char *fname)
 {
   static char usrname[L_cuserid];
   static struct dsc$descriptor_s usrdsc =
@@ -9080,7 +9702,11 @@ Perl_flex_fstat(pTHX_ int fd, Stat_t *statbufp)
        if (cptr == NULL)
           namecache[0] = '\0';
     }
+#ifdef _USE_STD_STAT
+    memcpy(&statbufp->st_ino, &statbufp->crtl_stat.st_ino, 8);
+#else
     memcpy(&statbufp->st_ino, statbufp->crtl_stat.st_ino, 8);
+#endif
 #ifndef _USE_STD_STAT
     strncpy(statbufp->st_devnam, statbufp->crtl_stat.st_dev, 63);
     statbufp->st_devnam[63] = 0;
@@ -9196,7 +9822,11 @@ Perl_flex_stat_int(pTHX_ const char *fspec, Stat_t *statbufp, int lstat_flag)
   }
 #endif
     if (!retval) {
+#ifdef _USE_STD_STAT
+      memcpy(&statbufp->st_ino, &statbufp->crtl_stat.st_ino, 8);
+#else
       memcpy(&statbufp->st_ino, statbufp->crtl_stat.st_ino, 8);
+#endif
 #ifndef _USE_STD_STAT
       strncpy(statbufp->st_devnam, statbufp->crtl_stat.st_dev, 63);
       statbufp->st_devnam[63] = 0;
@@ -9288,8 +9918,9 @@ my_getlogin(void)
  * as part of the Perl standard distribution under the terms of the
  * GNU General Public License or the Perl Artistic License.  Copies
  * of each may be found in the Perl standard distribution.
- */
+ */ /* FIXME */
 /*{{{int rmscopy(char *src, char *dst, int preserve_dates)*/
+#if defined(__VAX) || !defined(NAML$C_MAXRSS)
 int
 Perl_rmscopy(pTHX_ const char *spec_in, const char *spec_out, int preserve_dates)
 {
@@ -9456,6 +10087,253 @@ Perl_rmscopy(pTHX_ const char *spec_in, const char *spec_out, int preserve_dates
     return 1;
 
 }  /* end of rmscopy() */
+#else
+/* ODS-5 support version */
+int
+Perl_rmscopy(pTHX_ const char *spec_in, const char *spec_out, int preserve_dates)
+{
+    char *vmsin, * vmsout, *esa, *esa_out,
+         *rsa, *ubf;
+    unsigned long int i, sts, sts2;
+    struct FAB fab_in, fab_out;
+    struct RAB rab_in, rab_out;
+    struct NAML nam;
+    struct NAML nam_out;
+    struct XABDAT xabdat;
+    struct XABFHC xabfhc;
+    struct XABRDT xabrdt;
+    struct XABSUM xabsum;
+
+    Newx(vmsin, VMS_MAXRSS, char);
+    Newx(vmsout, VMS_MAXRSS, char);
+    if (!spec_in  || !*spec_in  || !do_tovmsspec(spec_in,vmsin,1) ||
+        !spec_out || !*spec_out || !do_tovmsspec(spec_out,vmsout,1)) {
+      Safefree(vmsin);
+      Safefree(vmsout);
+      set_errno(EINVAL); set_vaxc_errno(LIB$_INVARG);
+      return 0;
+    }
+
+    Newx(esa, VMS_MAXRSS, char);
+    nam = cc$rms_naml;
+    fab_in = cc$rms_fab;
+    fab_in.fab$l_fna = (char *) -1;
+    fab_in.fab$b_fns = 0;
+    nam.naml$l_long_filename = vmsin;
+    nam.naml$l_long_filename_size = strlen(vmsin);
+    fab_in.fab$b_shr = FAB$M_SHRPUT | FAB$M_UPI;
+    fab_in.fab$b_fac = FAB$M_BIO | FAB$M_GET;
+    fab_in.fab$l_fop = FAB$M_SQO;
+    fab_in.fab$l_naml =  &nam;
+    fab_in.fab$l_xab = (void *) &xabdat;
+
+    Newx(rsa, VMS_MAXRSS, char);
+    nam.naml$l_rsa = NULL;
+    nam.naml$b_rss = 0;
+    nam.naml$l_long_result = rsa;
+    nam.naml$l_long_result_alloc = VMS_MAXRSS - 1;
+    nam.naml$l_esa = NULL;
+    nam.naml$b_ess = 0;
+    nam.naml$l_long_expand = esa;
+    nam.naml$l_long_expand_alloc = VMS_MAXRSS - 1;
+    nam.naml$b_esl = nam.naml$b_rsl = 0;
+    nam.naml$l_long_expand_size = 0;
+    nam.naml$l_long_result_size = 0;
+#ifdef NAM$M_NO_SHORT_UPCASE
+    if (decc_efs_case_preserve)
+        nam.naml$b_nop |= NAM$M_NO_SHORT_UPCASE;
+#endif
+
+    xabdat = cc$rms_xabdat;        /* To get creation date */
+    xabdat.xab$l_nxt = (void *) &xabfhc;
+
+    xabfhc = cc$rms_xabfhc;        /* To get record length */
+    xabfhc.xab$l_nxt = (void *) &xabsum;
+
+    xabsum = cc$rms_xabsum;        /* To get key and area information */
+
+    if (!((sts = sys$open(&fab_in)) & 1)) {
+      Safefree(vmsin);
+      Safefree(vmsout);
+      Safefree(esa);
+      Safefree(rsa);
+      set_vaxc_errno(sts);
+      switch (sts) {
+        case RMS$_FNF: case RMS$_DNF:
+          set_errno(ENOENT); break;
+        case RMS$_DIR:
+          set_errno(ENOTDIR); break;
+        case RMS$_DEV:
+          set_errno(ENODEV); break;
+        case RMS$_SYN:
+          set_errno(EINVAL); break;
+        case RMS$_PRV:
+          set_errno(EACCES); break;
+        default:
+          set_errno(EVMSERR);
+      }
+      return 0;
+    }
+
+    nam_out = nam;
+    fab_out = fab_in;
+    fab_out.fab$w_ifi = 0;
+    fab_out.fab$b_fac = FAB$M_BIO | FAB$M_PUT;
+    fab_out.fab$b_shr = FAB$M_SHRGET | FAB$M_UPI;
+    fab_out.fab$l_fop = FAB$M_SQO;
+    fab_out.fab$l_naml = &nam_out;
+    fab_out.fab$l_fna = (char *) -1;
+    fab_out.fab$b_fns = 0;
+    nam_out.naml$l_long_filename = vmsout;
+    nam_out.naml$l_long_filename_size = strlen(vmsout);
+    fab_out.fab$l_dna = (char *) -1;
+    fab_out.fab$b_dns = 0;
+    nam_out.naml$l_long_defname = nam.naml$l_long_name;
+    nam_out.naml$l_long_defname_size =
+       nam.naml$l_long_name ?
+          nam.naml$l_long_name_size + nam.naml$l_long_type_size : 0;
+
+    Newx(esa_out, VMS_MAXRSS, char);
+    nam_out.naml$l_rsa = NULL;
+    nam_out.naml$b_rss = 0;
+    nam_out.naml$l_long_result = NULL;
+    nam_out.naml$l_long_result_alloc = 0;
+    nam_out.naml$l_esa = NULL;
+    nam_out.naml$b_ess = 0;
+    nam_out.naml$l_long_expand = esa_out;
+    nam_out.naml$l_long_expand_alloc = VMS_MAXRSS - 1;
+
+    if (preserve_dates == 0) {  /* Act like DCL COPY */
+      nam_out.naml$b_nop |= NAM$M_SYNCHK;
+      fab_out.fab$l_xab = NULL;  /* Don't disturb data from input file */
+      if (!((sts = sys$parse(&fab_out)) & 1)) {
+       Safefree(vmsin);
+       Safefree(vmsout);
+       Safefree(esa);
+       Safefree(rsa);
+       Safefree(esa_out);
+        set_errno(sts == RMS$_SYN ? EINVAL : EVMSERR);
+        set_vaxc_errno(sts);
+        return 0;
+      }
+      fab_out.fab$l_xab = (void *) &xabdat;
+      if (nam.naml$l_fnb & (NAM$M_EXP_NAME | NAM$M_EXP_TYPE)) preserve_dates = 1;
+    }
+    if (preserve_dates < 0)   /* Clear all bits; we'll use it as a */
+      preserve_dates =0;      /* bitmask from this point forward   */
+
+    if (!(preserve_dates & 1)) fab_out.fab$l_xab = (void *) &xabfhc;
+    if (!((sts = sys$create(&fab_out)) & 1)) {
+      Safefree(vmsin);
+      Safefree(vmsout);
+      Safefree(esa);
+      Safefree(rsa);
+      Safefree(esa_out);
+      set_vaxc_errno(sts);
+      switch (sts) {
+        case RMS$_DNF:
+          set_errno(ENOENT); break;
+        case RMS$_DIR:
+          set_errno(ENOTDIR); break;
+        case RMS$_DEV:
+          set_errno(ENODEV); break;
+        case RMS$_SYN:
+          set_errno(EINVAL); break;
+        case RMS$_PRV:
+          set_errno(EACCES); break;
+        default:
+          set_errno(EVMSERR);
+      }
+      return 0;
+    }
+    fab_out.fab$l_fop |= FAB$M_DLT;  /* in case we have to bail out */
+    if (preserve_dates & 2) {
+      /* sys$close() will process xabrdt, not xabdat */
+      xabrdt = cc$rms_xabrdt;
+#ifndef __GNUC__
+      xabrdt.xab$q_rdt = xabdat.xab$q_rdt;
+#else
+      /* gcc doesn't like the assignment, since its prototype for xab$q_rdt
+       * is unsigned long[2], while DECC & VAXC use a struct */
+      memcpy(xabrdt.xab$q_rdt,xabdat.xab$q_rdt,sizeof xabrdt.xab$q_rdt);
+#endif
+      fab_out.fab$l_xab = (void *) &xabrdt;
+    }
+
+    Newx(ubf, 32256, char);
+    rab_in = cc$rms_rab;
+    rab_in.rab$l_fab = &fab_in;
+    rab_in.rab$l_rop = RAB$M_BIO;
+    rab_in.rab$l_ubf = ubf;
+    rab_in.rab$w_usz = 32256;
+    if (!((sts = sys$connect(&rab_in)) & 1)) {
+      sys$close(&fab_in); sys$close(&fab_out);
+      Safefree(vmsin);
+      Safefree(vmsout);
+      Safefree(esa);
+      Safefree(ubf);
+      Safefree(rsa);
+      Safefree(esa_out);
+      set_errno(EVMSERR); set_vaxc_errno(sts);
+      return 0;
+    }
+
+    rab_out = cc$rms_rab;
+    rab_out.rab$l_fab = &fab_out;
+    rab_out.rab$l_rbf = ubf;
+    if (!((sts = sys$connect(&rab_out)) & 1)) {
+      sys$close(&fab_in); sys$close(&fab_out);
+      Safefree(vmsin);
+      Safefree(vmsout);
+      Safefree(esa);
+      Safefree(ubf);
+      Safefree(rsa);
+      Safefree(esa_out);
+      set_errno(EVMSERR); set_vaxc_errno(sts);
+      return 0;
+    }
+
+    while ((sts = sys$read(&rab_in))) {  /* always true  */
+      if (sts == RMS$_EOF) break;
+      rab_out.rab$w_rsz = rab_in.rab$w_rsz;
+      if (!(sts & 1) || !((sts = sys$write(&rab_out)) & 1)) {
+        sys$close(&fab_in); sys$close(&fab_out);
+       Safefree(vmsin);
+       Safefree(vmsout);
+       Safefree(esa);
+       Safefree(ubf);
+       Safefree(rsa);
+       Safefree(esa_out);
+        set_errno(EVMSERR); set_vaxc_errno(sts);
+        return 0;
+      }
+    }
+
+
+    fab_out.fab$l_fop &= ~FAB$M_DLT;  /* We got this far; keep the output */
+    sys$close(&fab_in);  sys$close(&fab_out);
+    sts = (fab_in.fab$l_sts & 1) ? fab_out.fab$l_sts : fab_in.fab$l_sts;
+    if (!(sts & 1)) {
+      Safefree(vmsin);
+      Safefree(vmsout);
+      Safefree(esa);
+      Safefree(ubf);
+      Safefree(rsa);
+      Safefree(esa_out);
+      set_errno(EVMSERR); set_vaxc_errno(sts);
+      return 0;
+    }
+
+    Safefree(vmsin);
+    Safefree(vmsout);
+    Safefree(esa);
+    Safefree(ubf);
+    Safefree(rsa);
+    Safefree(esa_out);
+    return 1;
+
+}  /* end of rmscopy() */
+#endif
 /*}}}*/
 
 
@@ -9607,7 +10485,7 @@ void
 rmscopy_fromperl(pTHX_ CV *cv)
 {
   dXSARGS;
-  char inspec[NAM$C_MAXRSS+1], outspec[NAM$C_MAXRSS+1], *inp, *outp;
+  char *inspec, *outspec, *inp, *outp;
   int date_flag;
   struct dsc$descriptor indsc  = { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0},
                         outdsc = { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
@@ -9620,10 +10498,12 @@ rmscopy_fromperl(pTHX_ CV *cv)
     Perl_croak(aTHX_ "Usage: File::Copy::rmscopy(from,to[,date_flag])");
 
   mysv = SvROK(ST(0)) ? SvRV(ST(0)) : ST(0);
+  Newx(inspec, VMS_MAXRSS, char);
   if (SvTYPE(mysv) == SVt_PVGV) {
     if (!(io = GvIOp(mysv)) || !PerlIO_getname(IoIFP(io),inspec)) {
       set_errno(EINVAL); set_vaxc_errno(LIB$_INVARG);
       ST(0) = &PL_sv_no;
+      Safefree(inspec);
       XSRETURN(1);
     }
     inp = inspec;
@@ -9632,14 +10512,18 @@ rmscopy_fromperl(pTHX_ CV *cv)
     if (mysv != ST(0) || !(inp = SvPV(mysv,n_a)) || !*inp) {
       set_errno(EINVAL); set_vaxc_errno(LIB$_INVARG);
       ST(0) = &PL_sv_no;
+      Safefree(inspec);
       XSRETURN(1);
     }
   }
   mysv = SvROK(ST(1)) ? SvRV(ST(1)) : ST(1);
+  Newx(outspec, VMS_MAXRSS, char);
   if (SvTYPE(mysv) == SVt_PVGV) {
     if (!(io = GvIOp(mysv)) || !PerlIO_getname(IoIFP(io),outspec)) {
       set_errno(EINVAL); set_vaxc_errno(LIB$_INVARG);
       ST(0) = &PL_sv_no;
+      Safefree(inspec);
+      Safefree(outspec);
       XSRETURN(1);
     }
     outp = outspec;
@@ -9648,16 +10532,22 @@ rmscopy_fromperl(pTHX_ CV *cv)
     if (mysv != ST(1) || !(outp = SvPV(mysv,n_a)) || !*outp) {
       set_errno(EINVAL); set_vaxc_errno(LIB$_INVARG);
       ST(0) = &PL_sv_no;
+      Safefree(inspec);
+      Safefree(outspec);
       XSRETURN(1);
     }
   }
   date_flag = (items == 3) ? SvIV(ST(2)) : 0;
 
   ST(0) = boolSV(rmscopy(inp,outp,date_flag));
+  Safefree(inspec);
+  Safefree(outspec);
   XSRETURN(1);
 }
 
-
+/* The mod2fname is limited to shorter filenames by design, so it should
+ * not be modified to support longer EFS pathnames
+ */
 void
 mod2fname(pTHX_ CV *cv)
 {
@@ -9980,10 +10870,12 @@ static int set_features
     int dflt;
     char* str;
     char val_str[10];
+#if defined(JPI$_CASE_LOOKUP_PERM) && !defined(__VAX)
     const unsigned long int jpicode1 = JPI$_CASE_LOOKUP_PERM;
     const unsigned long int jpicode2 = JPI$_CASE_LOOKUP_IMAGE;
     unsigned long case_perm;
     unsigned long case_image;
+#endif
 
     /* hacks to see if known bugs are still present for testing */
 
@@ -10163,7 +11055,7 @@ static int set_features
     }
 #endif
 
-#ifndef __VAX
+#if defined(JPI$_CASE_LOOKUP_PERM) && !defined(__VAX)
 
      /* Report true case tolerance */
     /*----------------------------*/