This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Fix some style issues in vms/vms.c.
[perl5.git] / vms / vms.c
index a2552d7..032387b 100644 (file)
--- a/vms/vms.c
+++ b/vms/vms.c
@@ -2,13 +2,10 @@
  *
  *    VMS-specific routines for perl5
  *
- *    Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- *    2002, 2003, 2004, 2005, 2006, 2007 by Charles Bailey and others.
+ *    Copyright (C) 1993-2015 by Charles Bailey and others.
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
- *
- *    Please see Changes*.* or the Perl Repository Browser for revision history.
  */
 
 /*
 #include <acedef.h>
 #include <acldef.h>
 #include <armdef.h>
+#if __CRTL_VER < 70300000
+/* needed for home-rolled utime() */
 #include <atrdef.h>
+#include <fibdef.h>
+#endif
 #include <chpdef.h>
 #include <clidef.h>
 #include <climsgdef.h>
@@ -34,7 +35,6 @@
 #include <descrip.h>
 #include <devdef.h>
 #include <dvidef.h>
-#include <fibdef.h>
 #include <float.h>
 #include <fscndef.h>
 #include <iodef.h>
@@ -44,7 +44,6 @@
 #include <libdef.h>
 #include <lib$routines.h>
 #include <lnmdef.h>
-#include <msgdef.h>
 #include <ossdef.h>
 #if __CRTL_VER >= 70301000 && !defined(__VAX)
 #include <ppropdef.h>
 #include <uaidef.h>
 #include <uicdef.h>
 #include <stsdef.h>
-#include <rmsdef.h>
-#include <smgdef.h>
-#if __CRTL_VER >= 70000000 /* FIXME to earliest version */
 #include <efndef.h>
 #define NO_EFN EFN$C_ENF
-#else
-#define NO_EFN 0;
-#endif
 
 #if  __CRTL_VER < 70301000 && __CRTL_VER >= 70300000
 int   decc$feature_get_index(const char *name);
@@ -89,29 +82,6 @@ struct item_list_3 {
 };
 #pragma member_alignment restore
 
-#if __CRTL_VER >= 70300000 && !defined(__VAX)
-
-static int set_feature_default(const char *name, int value)
-{
-    int status;
-    int index;
-
-    index = decc$feature_get_index(name);
-
-    status = decc$feature_set_value(index, 1, value);
-    if (index == -1 || (status == -1)) {
-      return -1;
-    }
-
-    status = decc$feature_get_value(index, 1);
-    if (status != value) {
-      return -1;
-    }
-
-return 0;
-}
-#endif
-
 /* Older versions of ssdef.h don't have these */
 #ifndef SS$_INVFILFOROP
 #  define SS$_INVFILFOROP 3930
@@ -138,10 +108,6 @@ return 0;
 #include <libfildef.h>
 #endif
 
-#if defined(__VMS_VER) && __VMS_VER >= 70000000 && __DECC_VER >= 50200000
-#  define RTL_USES_UTC 1
-#endif
-
 #if !defined(__VAX) && __CRTL_VER >= 80200000
 #ifdef lstat
 #undef lstat
@@ -182,8 +148,7 @@ static int (*decw_term_port)
 dEXT int h_errno;
 #endif
 
-#ifdef __DECC
-#pragma message disable pragma
+#if defined(__DECC) || defined(__DECCXX)
 #pragma member_alignment save
 #pragma nomember_alignment longword
 #pragma message save
@@ -204,10 +169,11 @@ struct filescan_itmlst_2 {
 
 struct vs_str_st {
     unsigned short length;
-    char str[65536];
+    char str[VMS_MAXRSS];
+    unsigned short pad; /* for longword struct alignment */
 };
 
-#ifdef __DECC
+#if defined(__DECC) || defined(__DECCXX)
 #pragma message restore
 #pragma member_alignment restore
 #endif
@@ -277,10 +243,6 @@ static bool will_taint = FALSE;  /* tainting active, but no PL_curinterp yet */
 /* munching */ 
 static int no_translate_barewords;
 
-#ifndef RTL_USES_UTC
-static int tz_updated = 1;
-#endif
-
 /* DECC Features that may need to affect how Perl interprets
  * displays filename information
  */
@@ -302,17 +264,14 @@ static int vms_posix_exit = 0;
 
 /* bug workarounds if needed */
 int decc_bug_devnull = 1;
-int decc_dir_barename = 0;
 int vms_bug_stat_filename = 0;
 
 static int vms_debug_on_exception = 0;
 static int vms_debug_fileify = 0;
 
 /* Simple logical name translation */
-static int simple_trnlnm
-   (const char * logname,
-    char * value,
-    int value_len)
+static int
+simple_trnlnm(const char * logname, char * value, int value_len)
 {
     const $DESCRIPTOR(table_dsc, "LNM$FILE_DEV");
     const unsigned long attr = LNM$M_CASE_BLIND;
@@ -349,10 +308,11 @@ static int simple_trnlnm
  *   changes to many other conversion routines.
  */
 
-static int is_unix_filespec(const char *path)
+static int
+is_unix_filespec(const char *path)
 {
-int ret_val;
-const char * pch1;
+    int ret_val;
+    const char * pch1;
 
     ret_val = 0;
     if (strncmp(path,"\"^UP^",5) != 0) {
@@ -374,13 +334,11 @@ const char * pch1;
 /* This routine converts a UCS-2 character to be VTF-7 encoded.
  */
 
-static void ucs2_to_vtf7
-   (char *outspec,
-    unsigned long ucs2_char,
-    int * output_cnt)
+static void
+ucs2_to_vtf7(char *outspec, unsigned long ucs2_char, int * output_cnt)
 {
-unsigned char * ucs_ptr;
-int hex;
+    unsigned char * ucs_ptr;
+    int hex;
 
     ucs_ptr = (unsigned char *)&ucs2_char;
 
@@ -421,12 +379,11 @@ int hex;
  *
  * The return value is the number of characters read from the input string
  */
-static int copy_expand_unix_filename_escape
-  (char *outspec, const char *inspec, int *output_cnt, const int * utf8_fl)
+static int
+copy_expand_unix_filename_escape(char *outspec, const char *inspec, int *output_cnt, const int * utf8_fl)
 {
-int count;
-int scnt;
-int utf8_flag;
+    int count;
+    int utf8_flag;
 
     utf8_flag = 0;
     if (utf8_fl)
@@ -475,8 +432,8 @@ int utf8_flag;
        /* High bit set, but not a Unicode character! */
 
        /* Non printing DECMCS or ISO Latin-1 character? */
-       if (*inspec <= 0x9F) {
-       int hex;
+       if ((unsigned char)*inspec <= 0x9F) {
+           int hex;
            outspec[0] = '^';
            outspec++;
            hex = (*inspec >> 4) & 0xF;
@@ -493,13 +450,13 @@ int utf8_flag;
            }
            *output_cnt = 3;
            return 1;
-       } else if (*inspec == 0xA0) {
+       } else if ((unsigned char)*inspec == 0xA0) {
            outspec[0] = '^';
            outspec[1] = 'A';
            outspec[2] = '0';
            *output_cnt = 3;
            return 1;
-       } else if (*inspec == 0xFF) {
+       } else if ((unsigned char)*inspec == 0xFF) {
            outspec[0] = '^';
            outspec[1] = 'F';
            outspec[2] = 'F';
@@ -605,6 +562,7 @@ int utf8_flag;
        return 1;
        break;
     }
+    return 0;
 }
 
 
@@ -617,11 +575,11 @@ int utf8_flag;
  * The return value is the number of characters read from the input
  * string
  */
-static int copy_expand_vms_filename_escape
-  (char *outspec, const char *inspec, int *output_cnt)
+static int
+copy_expand_vms_filename_escape(char *outspec, const char *inspec, int *output_cnt)
 {
-int count;
-int scnt;
+    int count;
+    int scnt;
 
     count = 0;
     *output_cnt = 0;
@@ -655,8 +613,8 @@ int scnt;
            if (scnt == 4) {
                unsigned int c1, c2;
                scnt = sscanf(inspec, "%2x%2x", &c1, &c2);
-               outspec[0] == c1 & 0xff;
-               outspec[1] == c2 & 0xff;
+               outspec[0] = c1 & 0xff;
+               outspec[1] = c2 & 0xff;
                if (scnt > 1) {
                    (*output_cnt) += 2;
                    count += 4;
@@ -708,34 +666,24 @@ int scnt;
  * string, then the passed file specification is probably a UNIX style
  * path.
  */
-static int vms_split_path
-   (const char * path,
-    char * * volume,
-    int * vol_len,
-    char * * root,
-    int * root_len,
-    char * * dir,
-    int * dir_len,
-    char * * name,
-    int * name_len,
-    char * * ext,
-    int * ext_len,
-    char * * version,
-    int * ver_len)
-{
-struct dsc$descriptor path_desc;
-int status;
-unsigned long flags;
-int ret_stat;
-struct filescan_itmlst_2 item_list[9];
-const int filespec = 0;
-const int nodespec = 1;
-const int devspec = 2;
-const int rootspec = 3;
-const int dirspec = 4;
-const int namespec = 5;
-const int typespec = 6;
-const int verspec = 7;
+static int
+vms_split_path(const char * path, char * * volume, int * vol_len, char * * root, int * root_len, 
+               char * * dir, int * dir_len, char * * name, int * name_len,
+               char * * ext, int * ext_len, char * * version, int * ver_len)
+{
+    struct dsc$descriptor path_desc;
+    int status;
+    unsigned long flags;
+    int ret_stat;
+    struct filescan_itmlst_2 item_list[9];
+    const int filespec = 0;
+    const int nodespec = 1;
+    const int devspec = 2;
+    const int rootspec = 3;
+    const int dirspec = 4;
+    const int namespec = 5;
+    const int typespec = 6;
+    const int verspec = 7;
 
     /* Assume the worst for an easy exit */
     ret_stat = -1;
@@ -744,7 +692,6 @@ const int verspec = 7;
     *root = NULL;
     *root_len = 0;
     *dir = NULL;
-    *dir_len;
     *name = NULL;
     *name_len = 0;
     *ext = NULL;
@@ -776,7 +723,7 @@ const int verspec = 7;
     item_list[devspec].component = NULL;
 
     /* root is a special case,  adding it to either the directory or
-     * the device components will probalby complicate things for the
+     * the device components will probably complicate things for the
      * callers of this routine, so leave it separate.
      */
     item_list[rootspec].itmcode = FSCN$_ROOT;
@@ -857,7 +804,9 @@ const int verspec = 7;
 }
 
 /* Routine to determine if the file specification ends with .dir */
-static int is_dir_ext(char * e_spec, int e_len, char * vs_spec, int vs_len) {
+static int
+is_dir_ext(char * e_spec, int e_len, char * vs_spec, int vs_len)
+{
 
     /* e_len must be 4, and version must be <= 2 characters */
     if (e_len != 4 || vs_len > 2)
@@ -918,6 +867,25 @@ my_maxidx(const char *lnm)
 }
 /*}}}*/
 
+/* Routine to remove the 2-byte prefix from the translation of a
+ * process-permanent file (PPF).
+ */
+static inline unsigned short int
+S_remove_ppf_prefix(const char *lnm, char *eqv, unsigned short int eqvlen)
+{
+    if (*((int *)lnm) == *((int *)"SYS$")                    &&
+        eqvlen >= 4 && eqv[0] == 0x1b && eqv[1] == 0x00      &&
+        ( (lnm[4] == 'O' && !strcmp(lnm,"SYS$OUTPUT"))  ||
+          (lnm[4] == 'I' && !strcmp(lnm,"SYS$INPUT"))   ||
+          (lnm[4] == 'E' && !strcmp(lnm,"SYS$ERROR"))   ||
+          (lnm[4] == 'C' && !strcmp(lnm,"SYS$COMMAND")) )  ) {
+
+        memmove(eqv, eqv+4, eqvlen-4);
+        eqvlen -= 4;
+    }
+    return eqvlen;
+}
+
 /*{{{int vmstrnenv(const char *lnm, char *eqv, unsigned long int idx, struct dsc$descriptor_s **tabvec, unsigned long int flags) */
 int
 Perl_vmstrnenv(const char *lnm, char *eqv, unsigned long int idx,
@@ -964,7 +932,7 @@ Perl_vmstrnenv(const char *lnm, char *eqv, unsigned long int idx,
     for (curtab = 0; tabvec[curtab]; curtab++) {
       if (!str$case_blind_compare(tabvec[curtab],&crtlenv)) {
         if (!ivenv && !secure) {
-          char *eq, *end;
+          char *eq;
           int i;
           if (!environ) {
             ivenv = 1; 
@@ -997,7 +965,7 @@ Perl_vmstrnenv(const char *lnm, char *eqv, unsigned long int idx,
         if (!ivsym && !secure) {
           unsigned short int deflen = LNM$C_NAMLENGTH;
           struct dsc$descriptor_d eqvdsc = {0,DSC$K_DTYPE_T,DSC$K_CLASS_D,0};
-          /* dynamic dsc to accomodate possible long value */
+          /* dynamic dsc to accommodate possible long value */
           _ckvmssts_noperl(lib$sget1_dd(&deflen,&eqvdsc));
           retsts = lib$get_symbol(&lnmdsc,&eqvdsc,&eqvlen,0);
           if (retsts & 1) { 
@@ -1035,39 +1003,33 @@ Perl_vmstrnenv(const char *lnm, char *eqv, unsigned long int idx,
             retsts = sys$trnlnm(&attr,tabvec[curtab],&lnmdsc,&acmode,lnmlst);
             if (retsts == SS$_IVLOGNAM) { ivlnm = 1; break; }
             if (retsts == SS$_NOLOGNAM) break;
-            /* PPFs have a prefix */
-            if (
-#if INTSIZE == 4
-                 *((int *)uplnm) == *((int *)"SYS$")                    &&
-#endif
-                 eqvlen >= 4 && eqv[0] == 0x1b && eqv[1] == 0x00        &&
-                 ( (uplnm[4] == 'O' && !strcmp(uplnm,"SYS$OUTPUT"))  ||
-                   (uplnm[4] == 'I' && !strcmp(uplnm,"SYS$INPUT"))   ||
-                   (uplnm[4] == 'E' && !strcmp(uplnm,"SYS$ERROR"))   ||
-                   (uplnm[4] == 'C' && !strcmp(uplnm,"SYS$COMMAND")) )  ) {
-              memmove(eqv,eqv+4,eqvlen-4);
-              eqvlen -= 4;
-            }
+            eqvlen = S_remove_ppf_prefix(uplnm, eqv, eqvlen);
             cp2 += eqvlen;
             *cp2 = '\0';
           }
           if ((retsts == SS$_IVLOGNAM) ||
               (retsts == SS$_NOLOGNAM)) { continue; }
+          eqvlen = strlen(eqv);
         }
         else {
           retsts = sys$trnlnm(&attr,tabvec[curtab],&lnmdsc,&acmode,lnmlst);
           if (retsts == SS$_IVLOGNAM) { ivlnm = 1; continue; }
           if (retsts == SS$_NOLOGNAM) continue;
+          eqvlen = S_remove_ppf_prefix(uplnm, eqv, eqvlen);
           eqv[eqvlen] = '\0';
         }
-        eqvlen = strlen(eqv);
         break;
       }
     }
     if (retsts & 1) { eqv[eqvlen] = '\0'; return eqvlen; }
-    else if (retsts == LIB$_NOSUCHSYM || retsts == LIB$_INVSYMNAM ||
-             retsts == SS$_IVLOGNAM   || retsts == SS$_IVLOGTAB   ||
+    else if (retsts == LIB$_NOSUCHSYM ||
              retsts == SS$_NOLOGNAM) {
+     /* Unsuccessful lookup is normal -- no need to set errno */
+     return 0;
+    }
+    else if (retsts == LIB$_INVSYMNAM ||
+             retsts == SS$_IVLOGNAM   ||
+             retsts == SS$_IVLOGTAB) {
       set_errno(EINVAL);  set_vaxc_errno(retsts);
     }
     else _ckvmssts_noperl(retsts);
@@ -1077,7 +1039,8 @@ Perl_vmstrnenv(const char *lnm, char *eqv, unsigned long int idx,
 
 /*{{{ int my_trnlnm(const char *lnm, char *eqv, unsigned long int idx)*/
 /* Define as a function so we can access statics. */
-int Perl_my_trnlnm(pTHX_ const char *lnm, char *eqv, unsigned long int idx)
+int
+Perl_my_trnlnm(pTHX_ const char *lnm, char *eqv, unsigned long int idx)
 {
     int flags = 0;
 
@@ -1085,7 +1048,7 @@ int Perl_my_trnlnm(pTHX_ const char *lnm, char *eqv, unsigned long int idx)
     if (aTHX != NULL)
 #endif
 #ifdef SECURE_INTERNAL_GETENV
-        flags = (PL_curinterp ? PL_tainting : will_taint) ?
+        flags = (PL_curinterp ? TAINTING_get : will_taint) ?
                  PERL__TRNENV_SECURE : 0;
 #endif
 
@@ -1109,7 +1072,7 @@ Perl_my_getenv(pTHX_ const char *lnm, bool sys)
     static char *__my_getenv_eqv = NULL;
     char uplnm[LNM$C_NAMLENGTH+1], *cp2, *eqv;
     unsigned long int idx = 0;
-    int trnsuccess, success, secure, saverr, savvmserr;
+    int success, secure;
     int midx, flags;
     SV *tmpsv;
 
@@ -1158,8 +1121,7 @@ Perl_my_getenv(pTHX_ const char *lnm, bool sys)
       /* Impose security constraints only if tainting */
       if (sys) {
         /* Impose security constraints only if tainting */
-        secure = PL_curinterp ? PL_tainting : will_taint;
-        saverr = errno;  savvmserr = vaxc$errno;
+        secure = PL_curinterp ? TAINTING_get : will_taint;
       }
       else {
         secure = 0;
@@ -1183,8 +1145,7 @@ Perl_my_getenv(pTHX_ const char *lnm, bool sys)
        * off and make sure we only retrieve the equivalence name for 
        * that index.  */
       if ((cp2 = strchr(lnm,';')) != NULL) {
-        strcpy(uplnm,lnm);
-        uplnm[cp2-lnm] = '\0';
+        my_strlcpy(uplnm, lnm, cp2 - lnm + 1);
         idx = strtoul(cp2+1,NULL,0);
         lnm = uplnm;
         flags &= ~PERL__TRNENV_JOIN_SEARCHLIST;
@@ -1192,10 +1153,6 @@ Perl_my_getenv(pTHX_ const char *lnm, bool sys)
 
       success = vmstrnenv(lnm,eqv,idx,secure ? fildev : NULL,flags);
 
-      /* Discard NOLOGNAM on internal calls since we're often looking
-       * for an optional name, and this "error" often shows up as the
-       * (bogus) exit status for a die() call later on.  */
-      if (sys && vaxc$errno == SS$_NOLOGNAM) SETERRNO(saverr,savvmserr);
       return success ? eqv : NULL;
     }
 
@@ -1212,7 +1169,7 @@ Perl_my_getenv_len(pTHX_ const char *lnm, unsigned long *len, bool sys)
     unsigned long idx = 0;
     int midx, flags;
     static char *__my_getenv_len_eqv = NULL;
-    int secure, saverr, savvmserr;
+    int secure;
     SV *tmpsv;
     
     midx = my_maxidx(lnm) + 1;
@@ -1258,8 +1215,7 @@ Perl_my_getenv_len(pTHX_ const char *lnm, unsigned long *len, bool sys)
     else {
       if (sys) {
         /* Impose security constraints only if tainting */
-        secure = PL_curinterp ? PL_tainting : will_taint;
-        saverr = errno;  savvmserr = vaxc$errno;
+        secure = PL_curinterp ? TAINTING_get : will_taint;
       }
       else {
         secure = 0;
@@ -1276,8 +1232,7 @@ Perl_my_getenv_len(pTHX_ const char *lnm, unsigned long *len, bool sys)
       flags |= PERL__TRNENV_JOIN_SEARCHLIST;
 
       if ((cp2 = strchr(lnm,';')) != NULL) {
-        strcpy(buf,lnm);
-        buf[cp2-lnm] = '\0';
+        my_strlcpy(buf, lnm, cp2 - lnm + 1);
         idx = strtoul(cp2+1,NULL,0);
         lnm = buf;
         flags &= ~PERL__TRNENV_JOIN_SEARCHLIST;
@@ -1287,7 +1242,7 @@ Perl_my_getenv_len(pTHX_ const char *lnm, unsigned long *len, bool sys)
 
       /* Get rid of "000000/ in rooted filespecs */
       if (*len > 7) {
-      char * zeros;
+       char * zeros;
        zeros = strstr(buf, "/000000/");
        if (zeros != NULL) {
          int mlen;
@@ -1298,10 +1253,6 @@ Perl_my_getenv_len(pTHX_ const char *lnm, unsigned long *len, bool sys)
        }
       }
 
-      /* Discard NOLOGNAM on internal calls since we're often looking
-       * for an optional name, and this "error" often shows up as the
-       * (bogus) exit status for a die() call later on.  */
-      if (sys && vaxc$errno == SS$_NOLOGNAM) SETERRNO(saverr,savvmserr);
       return *len ? buf : NULL;
     }
 
@@ -1328,7 +1279,7 @@ prime_env_iter(void)
 #  define CLI$M_TRUSTED 0x40  /* Missing from VAXC headers */
 #endif
   unsigned long int defflags = CLI$M_NOWAIT | CLI$M_NOKEYPAD | CLI$M_TRUSTED;
-  unsigned long int mbxbufsiz, flags, retsts, subpid = 0, substs = 0, wakect = 0;
+  unsigned long int mbxbufsiz, flags, retsts, subpid = 0, substs = 0;
   long int i;
   bool have_sym = FALSE, have_lnm = FALSE;
   struct dsc$descriptor_s tmpdsc = {6,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
@@ -1402,19 +1353,18 @@ prime_env_iter(void)
     }
     else if ((tmpdsc.dsc$a_pointer = env_tables[i]->dsc$a_pointer) &&
              !str$case_blind_compare(&tmpdsc,&clisym)) {
-      strcpy(cmd,"Show Symbol/Global *");
+      my_strlcpy(cmd, "Show Symbol/Global *", sizeof(cmd));
       cmddsc.dsc$w_length = 20;
       if (env_tables[i]->dsc$w_length == 12 &&
           (tmpdsc.dsc$a_pointer = env_tables[i]->dsc$a_pointer + 6) &&
-          !str$case_blind_compare(&tmpdsc,&local)) strcpy(cmd+12,"Local  *");
+          !str$case_blind_compare(&tmpdsc,&local)) my_strlcpy(cmd+12, "Local  *", sizeof(cmd)-12);
       flags = defflags | CLI$M_NOLOGNAM;
     }
     else {
-      strcpy(cmd,"Show Logical *");
+      my_strlcpy(cmd, "Show Logical *", sizeof(cmd));
       if (str$case_blind_compare(env_tables[i],&fildevdsc)) {
-        strcat(cmd," /Table=");
-        strncat(cmd,env_tables[i]->dsc$a_pointer,env_tables[i]->dsc$w_length);
-        cmddsc.dsc$w_length = strlen(cmd);
+        my_strlcat(cmd," /Table=", sizeof(cmd));
+        cmddsc.dsc$w_length = my_strlcat(cmd, env_tables[i]->dsc$a_pointer, sizeof(cmd));
       }
       else cmddsc.dsc$w_length = 14;  /* N.B. We test this below */
       flags = defflags | CLI$M_NOCLISYM;
@@ -1437,7 +1387,7 @@ prime_env_iter(void)
     while (1) {
       char *cp1, *cp2, *key;
       unsigned long int sts, iosb[2], retlen, keylen;
-      register U32 hash;
+      U32 hash;
 
       sts = sys$qiow(0,chan,IO$_READVBLK,iosb,0,0,buf,mbxbufsiz,0,0,0,0);
       if (sts & 1) sts = iosb[0] & 0xffff;
@@ -1723,16 +1673,6 @@ Perl_my_setenv(pTHX_ const char *lnm, const char *eqv)
           return;
         }
     } 
-#ifndef RTL_USES_UTC
-    if (len == 6 || len == 2) {
-      char uplnm[7];
-      int i;
-      for (i = 0; lnm[i]; i++) uplnm[i] = _toupper(lnm[i]);
-      uplnm[len] = '\0';
-      if (!strcmp(uplnm,"UCX$TZ")) tz_updated = 1;
-      if (!strcmp(uplnm,"TZ")) tz_updated = 1;
-    }
-#endif
   }
   (void) vmssetenv(lnm,eqv,NULL);
 }
@@ -1742,14 +1682,9 @@ Perl_my_setenv(pTHX_ const char *lnm, const char *eqv)
 /*  vmssetuserlnm
  *  sets a user-mode logical in the process logical name table
  *  used for redirection of sys$error
- *
- *  Fix-me: The pTHX is not needed for this routine, however doio.c
- *          is calling it with one instead of using a macro.
- *          A macro needs to be added to vmsish.h and doio.c updated to use it.
- *
  */
 void
-Perl_vmssetuserlnm(pTHX_ const char *name, const char *eqv)
+Perl_vmssetuserlnm(const char *name, const char *eqv)
 {
     $DESCRIPTOR(d_tab, "LNM$PROCESS");
     struct dsc$descriptor_d d_name = {0,DSC$K_DTYPE_T,DSC$K_CLASS_D,0};
@@ -1836,26 +1771,12 @@ static char *mp_do_rmsexpand(pTHX_ const char *, char *, int, const char *, unsi
 static char *mp_do_fileify_dirspec(pTHX_ const char *, char *, int, int *);
 static char *mp_do_tovmsspec(pTHX_ const char *, char *, int, int, int *);
 
-/* fixup barenames that are directories for internal use.
- * There have been problems with the consistent handling of UNIX
- * style directory names when routines are presented with a name that
- * has no directory delimitors at all.  So this routine will eventually
- * fix the issue.
- */
-static char * fixup_bare_dirnames(const char * name)
-{
-  if (decc_disable_to_vms_logname_translation) {
-/* fix me */
-  }
-  return NULL;
-}
-
 /* 8.3, remove() is now broken on symbolic links */
 static int rms_erase(const char * vmsname);
 
 
 /* mp_do_kill_file
- * A little hack to get around a bug in some implemenation of remove()
+ * A little hack to get around a bug in some implementation of remove()
  * that do not know how to delete a directory
  *
  * Delete any file to which user has control access, regardless of whether
@@ -1872,7 +1793,8 @@ mp_do_kill_file(pTHX_ const char *name, int dirflag)
     char *vmsname;
     char *rslt;
     unsigned long int jpicode = JPI$_UIC, type = ACL$C_FILE;
-    unsigned long int cxt = 0, aclsts, fndsts, rmsts = -1;
+    unsigned long int cxt = 0, aclsts, fndsts;
+    int rmsts = -1;
     struct dsc$descriptor_s fildsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
     struct myacedef {
       unsigned char myace$b_length;
@@ -1894,7 +1816,7 @@ mp_do_kill_file(pTHX_ const char *name, int dirflag)
     /* Expand the input spec using RMS, since the CRTL remove() and
      * system services won't do this by themselves, so we may miss
      * a file "hiding" behind a logical name or search list. */
-    vmsname = PerlMem_malloc(NAM$C_MAXRSS+1);
+    vmsname = (char *)PerlMem_malloc(NAM$C_MAXRSS+1);
     if (vmsname == NULL) _ckvmssts_noperl(SS$_INSFMEM);
 
     rslt = int_rmsexpand_tovms(name, vmsname, PERL_RMSEXPAND_M_SYMLINK);
@@ -2156,16 +2078,18 @@ int
 Perl_my_chdir(pTHX_ const char *dir)
 {
   STRLEN dirlen = strlen(dir);
+  const char *dir1 = dir;
 
   /* zero length string sometimes gives ACCVIO */
-  if (dirlen == 0) return -1;
-  const char *dir1;
+  if (dirlen == 0) {
+    SETERRNO(EINVAL, SS$_BADPARAM);
+    return -1;
+  }
 
   /* Perl is passing the output of the DCL SHOW DEFAULT with leading spaces.
    * This does not work if DECC$EFS_CHARSET is active.  Hack it here
    * so that existing scripts do not need to be changed.
    */
-  dir1 = dir;
   while ((dirlen > 0) && (*dir1 == ' ')) {
     dir1++;
     dirlen--;
@@ -2181,10 +2105,10 @@ Perl_my_chdir(pTHX_ const char *dir)
   if ((dirlen > 1) && (dir1[dirlen-1] == '/')) {
       char *newdir;
       int ret;
-      newdir = PerlMem_malloc(dirlen);
+      newdir = (char *)PerlMem_malloc(dirlen);
       if (newdir ==NULL)
           _ckvmssts_noperl(SS$_INSFMEM);
-      strncpy(newdir, dir1, dirlen-1);
+      memcpy(newdir, dir1, dirlen-1);
       newdir[dirlen-1] = '\0';
       ret = chdir(newdir);
       PerlMem_free(newdir);
@@ -2247,7 +2171,7 @@ my_tmpfile(void)
 
   if ((fp = tmpfile())) return fp;
 
-  cp = PerlMem_malloc(L_tmpnam+24);
+  cp = (char *)PerlMem_malloc(L_tmpnam+24);
   if (cp == NULL) _ckvmssts_noperl(SS$_INSFMEM);
 
   if (decc_filename_unix_only == 0)
@@ -2263,7 +2187,6 @@ my_tmpfile(void)
 /*}}}*/
 
 
-#ifndef HOMEGROWN_POSIX_SIGNALS
 /*
  * The C RTL's sigaction fails to check for invalid signal numbers so we 
  * help it out a bit.  The docs are correct, but the actual routine doesn't
@@ -2281,7 +2204,6 @@ Perl_my_sigaction (pTHX_ int sig, const struct sigaction* act,
   return sigaction(sig, act, oact);
 }
 /*}}}*/
-#endif
 
 #ifdef KILL_BY_SIGPRC
 #include <errnodef.h>
@@ -2360,20 +2282,16 @@ Perl_sig_to_vmscondition_int(int sig)
         0                   /* 28 SIGWINCH  */
     };
 
-#if __VMS_VER >= 60200000
     static int initted = 0;
     if (!initted) {
         initted = 1;
         sig_code[16] = C$_SIGUSR1;
         sig_code[17] = C$_SIGUSR2;
-#if __CRTL_VER >= 70000000
         sig_code[20] = C$_SIGCHLD;
-#endif
 #if __CRTL_VER >= 70300000
         sig_code[28] = C$_SIGWINCH;
 #endif
     }
-#endif
 
     if (sig < _SIG_MIN) return 0;
     if (sig > _MY_SIG_MAX) return 0;
@@ -2391,16 +2309,22 @@ Perl_sig_to_vmscondition(int sig)
 }
 
 
+#define sys$sigprc SYS$SIGPRC
+#ifdef __cplusplus
+extern "C" {
+#endif
+int sys$sigprc(unsigned int *pidadr,
+               struct dsc$descriptor_s *prcname,
+               unsigned int code);
+#ifdef __cplusplus
+}
+#endif
+
 int
 Perl_my_kill(int pid, int sig)
 {
-    dTHX;
     int iss;
     unsigned int code;
-#define sys$sigprc SYS$SIGPRC
-    int sys$sigprc(unsigned int *pidadr,
-                     struct dsc$descriptor_s *prcname,
-                     unsigned int code);
 
      /* sig 0 means validate the PID */
     /*------------------------------*/
@@ -2490,13 +2414,14 @@ Perl_my_kill(int pid, int sig)
 #define DCL_IVVERB 0x38090
 #endif
 
-int Perl_vms_status_to_unix(int vms_status, int child_flag)
+int
+Perl_vms_status_to_unix(int vms_status, int child_flag)
 {
-int facility;
-int fac_sp;
-int msg_no;
-int msg_status;
-int unix_status;
+  int facility;
+  int fac_sp;
+  int msg_no;
+  int msg_status;
+  int unix_status;
 
   /* Assume the best or the worst */
   if (vms_status & STS$M_SUCCESS)
@@ -2672,9 +2597,10 @@ int unix_status;
  * error statuses that caused the errno value to be set.
  */
 
-int Perl_unix_status_to_vms(int unix_status)
+int
+Perl_unix_status_to_vms(int unix_status)
 {
-int test_unix_status;
+    int test_unix_status;
 
      /* Trivial cases first */
     /*---------------------*/
@@ -2793,8 +2719,6 @@ int test_unix_status;
     default:
        return SS$_ABORT; /* punt */
     }
-
-  return SS$_ABORT; /* Should not get here */
 } 
 
 
@@ -2929,7 +2853,7 @@ struct pipe_details
 struct exit_control_block
 {
     struct exit_control_block *flink;
-    unsigned long int  (*exit_routine)();
+    unsigned long int (*exit_routine)(void);
     unsigned long int arg_count;
     unsigned long int *status_address;
     unsigned long int exit_status;
@@ -2962,11 +2886,11 @@ static $DESCRIPTOR(nl_desc, "NL:");
 
 
 static unsigned long int
-pipe_exit_routine()
+pipe_exit_routine(void)
 {
     pInfo info;
     unsigned long int retsts = SS$_NORMAL, abort = SS$_TIMEOUT;
-    int sts, did_stuff, need_eof, j;
+    int sts, did_stuff, j;
 
    /* 
     * Flush any pending i/o, but since we are in process run-down, be
@@ -3010,7 +2934,6 @@ pipe_exit_routine()
     info = open_pipes;
 
     while (info) {
-      int need_eof;
       _ckvmssts_noperl(sys$setast(0));
       if (info->in && !info->in->shut_on_empty) {
         _ckvmssts_noperl(sys$qio(0,info->in->chan_in,IO$_WRITEOF,0,0,0,
@@ -3115,8 +3038,6 @@ popen_completion_ast(pInfo info)
 {
   pInfo i = open_pipes;
   int iss;
-  int sts;
-  pXpipe x;
 
   info->completion &= 0x0FFFFFFF; /* strip off "control" field */
   closed_list[closed_index].pid = info->pid;
@@ -3178,59 +3099,6 @@ popen_completion_ast(pInfo info)
 
 static unsigned long int setup_cmddsc(pTHX_ const char *cmd, int check_img, int *suggest_quote, struct dsc$descriptor_s **pvmscmd);
 static void vms_execfree(struct dsc$descriptor_s *vmscmd);
-
-/*
-    we actually differ from vmstrnenv since we use this to
-    get the RMS IFI to check if SYS$OUTPUT and SYS$ERROR *really*
-    are pointing to the same thing
-*/
-
-static unsigned short
-popen_translate(pTHX_ char *logical, char *result)
-{
-    int iss;
-    $DESCRIPTOR(d_table,"LNM$PROCESS_TABLE");
-    $DESCRIPTOR(d_log,"");
-    struct _il3 {
-        unsigned short length;
-        unsigned short code;
-        char *         buffer_addr;
-        unsigned short *retlenaddr;
-    } itmlst[2];
-    unsigned short l, ifi;
-
-    d_log.dsc$a_pointer = logical;
-    d_log.dsc$w_length  = strlen(logical);
-
-    itmlst[0].code = LNM$_STRING;
-    itmlst[0].length = 255;
-    itmlst[0].buffer_addr = result;
-    itmlst[0].retlenaddr = &l;
-
-    itmlst[1].code = 0;
-    itmlst[1].length = 0;
-    itmlst[1].buffer_addr = 0;
-    itmlst[1].retlenaddr = 0;
-
-    iss = sys$trnlnm(0, &d_table, &d_log, 0, itmlst);
-    if (iss == SS$_NOLOGNAM) {
-        iss = SS$_NORMAL;
-        l = 0;
-    }
-    if (!(iss&1)) lib$signal(iss);
-    result[l] = '\0';
-/*
-    logicals for PPFs have a 4 byte prefix  ESC+NUL+(RMS IFI)
-    strip it off and return the ifi, if any
-*/
-    ifi  = 0;
-    if (result[0] == 0x1b && result[1] == 0x00) {
-        memmove(&ifi,result+2,2);
-        strcpy(result,result+4);
-    }
-    return ifi;     /* this is the RMS internal file id */
-}
-
 static void pipe_infromchild_ast(pPipe p);
 
 /*
@@ -3543,7 +3411,7 @@ pipe_mbxtofd_setup(pTHX_ int fd, char *out)
 
     /* things like terminals and mbx's don't need this filter */
     if (fd && fstat(fd,&s) == 0) {
-        unsigned long dviitm = DVI$_DEVCHAR, devchar;
+        unsigned long devchar;
        char device[65];
        unsigned short dev_len;
        struct dsc$descriptor_s d_dev;
@@ -3677,7 +3545,6 @@ store_pipelocs(pTHX)
     pPLOC  p;
     AV    *av = 0;
     SV    *dirsv;
-    GV    *gv;
     char  *dir, *x;
     char  *unixdir;
     char  temp[NAM$C_MAXRSS+1];
@@ -3696,7 +3563,7 @@ store_pipelocs(pTHX)
 
 /*  get the directory from $^X */
 
-    unixdir = PerlMem_malloc(VMS_MAXRSS);
+    unixdir = (char *)PerlMem_malloc(VMS_MAXRSS);
     if (unixdir == NULL) _ckvmssts_noperl(SS$_INSFMEM);
 
 #ifdef PERL_IMPLICIT_CONTEXT
@@ -3704,7 +3571,7 @@ store_pipelocs(pTHX)
 #else
     if (PL_origargv && PL_origargv[0]) {    /* maybe nul if embedded Perl */
 #endif
-        strcpy(temp, PL_origargv[0]);
+        my_strlcpy(temp, PL_origargv[0], sizeof(temp));
         x = strrchr(temp,']');
        if (x == NULL) {
        x = strrchr(temp,'>');
@@ -3726,8 +3593,7 @@ store_pipelocs(pTHX)
            if (p == NULL) _ckvmssts_noperl(SS$_INSFMEM);
             p->next = head_PLOC;
             head_PLOC = p;
-            strncpy(p->dir,unixdir,sizeof(p->dir)-1);
-            p->dir[NAM$C_MAXRSS] = '\0';
+            my_strlcpy(p->dir, unixdir, sizeof(p->dir));
        }
     }
 
@@ -3750,8 +3616,7 @@ store_pipelocs(pTHX)
         p = (pPLOC) PerlMem_malloc(sizeof(PLOC));
         p->next = head_PLOC;
         head_PLOC = p;
-        strncpy(p->dir,unixdir,sizeof(p->dir)-1);
-        p->dir[NAM$C_MAXRSS] = '\0';
+        my_strlcpy(p->dir, unixdir, sizeof(p->dir));
     }
 
 /* most likely spot (ARCHLIB) put first in the list */
@@ -3762,16 +3627,14 @@ store_pipelocs(pTHX)
        if (p == NULL) _ckvmssts_noperl(SS$_INSFMEM);
         p->next = head_PLOC;
         head_PLOC = p;
-        strncpy(p->dir,unixdir,sizeof(p->dir)-1);
-        p->dir[NAM$C_MAXRSS] = '\0';
+        my_strlcpy(p->dir, unixdir, sizeof(p->dir));
     }
 #endif
     PerlMem_free(unixdir);
 }
 
-static I32
-Perl_cando_by_name_int
-   (pTHX_ I32 bit, bool effective, const char *fname, int opts);
+static I32 Perl_cando_by_name_int(pTHX_ I32 bit, bool effective,
+                                  const char *fname, int opts);
 #if !defined(PERL_IMPLICIT_CONTEXT)
 #define cando_by_name_int              Perl_cando_by_name_int
 #else
@@ -3804,10 +3667,8 @@ find_vmspipe(pTHX)
         while (p) {
            char * exp_res;
            int dirlen;
-            strcpy(file, p->dir);
-           dirlen = strlen(file);
-            strncat(file, "vmspipe.com",NAM$C_MAXRSS - dirlen);
-            file[NAM$C_MAXRSS] = '\0';
+           dirlen = my_strlcpy(file, p->dir, sizeof(file));
+            my_strlcat(file, "vmspipe.com", sizeof(file));
             p = p->next;
 
             exp_res = int_rmsexpand_tovms(file, vmspipe_file, 0);
@@ -3920,7 +3781,8 @@ vmspipe_tempfile(pTHX)
 }
 
 
-static int vms_is_syscommand_xterm(void)
+static int
+vms_is_syscommand_xterm(void)
 {
     const static struct dsc$descriptor_s syscommand_dsc = 
       { 11, DSC$K_DTYPE_T, DSC$K_CLASS_S, "SYS$COMMAND" };
@@ -3986,7 +3848,8 @@ static int vms_is_syscommand_xterm(void)
 }
 
 /* If we are on a DECTerm, we can pretend to fork xterms when requested */
-static PerlIO * create_forked_xterm(pTHX_ const char *cmd, const char *mode)
+static PerlIO* 
+create_forked_xterm(pTHX_ const char *cmd, const char *mode)
 {
     int status;
     int ret_stat;
@@ -3996,7 +3859,6 @@ static PerlIO * create_forked_xterm(pTHX_ const char *cmd, const char *mode)
     struct dsc$descriptor_s customization_dsc;
     struct dsc$descriptor_s device_name_dsc;
     const char * cptr;
-    char * tptr;
     char customization[200];
     char title[40];
     pInfo info = NULL;
@@ -4004,7 +3866,6 @@ static PerlIO * create_forked_xterm(pTHX_ const char *cmd, const char *mode)
     unsigned short p_chan;
     int n;
     unsigned short iosb[4];
-    struct item_list_3 items[2];
     const char * cust_str =
         "DECW$TERMINAL.iconName:\tPerl Dbg\nDECW$TERMINAL.title:\t%40s\n";
     struct dsc$descriptor_s d_mbx1 = {sizeof mbx1, DSC$K_DTYPE_T,
@@ -4077,7 +3938,7 @@ static PerlIO * create_forked_xterm(pTHX_ const char *cmd, const char *mode)
            title[n] = *cptr;
            n++;
            if (n == 39) {
-               title[39] == 0;
+               title[39] = 0;
                break;
            }
            cptr++;
@@ -4265,7 +4126,7 @@ safe_popen(pTHX_ const char *cmd, const char *in_mode, int *psts)
     tfilebuf[0] = '@';
     vmspipe = find_vmspipe(aTHX);
     if (vmspipe) {
-        strcpy(tfilebuf+1,vmspipe);
+        vmspipedsc.dsc$w_length = my_strlcpy(tfilebuf+1, vmspipe, sizeof(tfilebuf)-1) + 1;
     } else {        /* uh, oh...we're in tempfile hell */
         tpipe = vmspipe_tempfile(aTHX);
         if (!tpipe) {       /* a fish popular in Boston */
@@ -4275,9 +4136,9 @@ safe_popen(pTHX_ const char *cmd, const char *in_mode, int *psts)
         return NULL;
         }
         fgetname(tpipe,tfilebuf+1,1);
+        vmspipedsc.dsc$w_length  = strlen(tfilebuf);
     }
     vmspipedsc.dsc$a_pointer = tfilebuf;
-    vmspipedsc.dsc$w_length  = strlen(tfilebuf);
 
     sts = setup_cmddsc(aTHX_ cmd,0,0,&vmscmd);
     if (!(sts & 1)) { 
@@ -4309,7 +4170,7 @@ safe_popen(pTHX_ const char *cmd, const char *in_mode, int *psts)
     n = sizeof(Info);
     _ckvmssts_noperl(lib$get_vm(&n, &info));
         
-    strcpy(mode,in_mode);
+    my_strlcpy(mode, in_mode, sizeof(mode));
     info->mode = *mode;
     info->done = FALSE;
     info->completion = 0;
@@ -4326,11 +4187,11 @@ safe_popen(pTHX_ const char *cmd, const char *in_mode, int *psts)
     info->xchan      = 0;
     info->xchan_valid = 0;
 
-    in = PerlMem_malloc(VMS_MAXRSS);
+    in = (char *)PerlMem_malloc(VMS_MAXRSS);
     if (in == NULL) _ckvmssts_noperl(SS$_INSFMEM);
-    out = PerlMem_malloc(VMS_MAXRSS);
+    out = (char *)PerlMem_malloc(VMS_MAXRSS);
     if (out == NULL) _ckvmssts_noperl(SS$_INSFMEM);
-    err = PerlMem_malloc(VMS_MAXRSS);
+    err = (char *)PerlMem_malloc(VMS_MAXRSS);
     if (err == NULL) _ckvmssts_noperl(SS$_INSFMEM);
 
     in[0] = out[0] = err[0] = '\0';
@@ -4356,7 +4217,7 @@ safe_popen(pTHX_ const char *cmd, const char *in_mode, int *psts)
            info->fp  = PerlIO_open(mbx, mode);
         } else {
             info->fp = (PerlIO *) freopen(mbx, mode, stdin);
-            Perl_vmssetuserlnm(aTHX_ "SYS$INPUT",mbx);
+            vmssetuserlnm("SYS$INPUT", mbx);
         }
 
         if (!info->fp && info->out) {
@@ -4411,7 +4272,7 @@ safe_popen(pTHX_ const char *cmd, const char *in_mode, int *psts)
            info->fp  = PerlIO_open(mbx, mode);
         } else {
             info->fp = (PerlIO *) freopen(mbx, mode, stdout);
-            Perl_vmssetuserlnm(aTHX_ "SYS$OUTPUT",mbx);
+            vmssetuserlnm("SYS$OUTPUT", mbx);
         }
 
         if (info->in) {
@@ -4449,6 +4310,13 @@ safe_popen(pTHX_ const char *cmd, const char *in_mode, int *psts)
         
 
     } else if (*mode == 'n') {       /* separate subprocess, no Perl i/o */
+        /* Let the child inherit standard input, unless it's a directory. */
+        Stat_t st;
+        if (my_trnlnm("SYS$INPUT", in, 0)) {
+            if (flex_stat(in, &st) != 0 || S_ISDIR(st.st_mode))
+                *in = '\0';
+        }
+
         info->out = pipe_mbxtofd_setup(aTHX_ fileno(stdout), out);
         if (info->out) {
             info->out->pipe_done = &info->out_done;
@@ -4464,18 +4332,13 @@ safe_popen(pTHX_ const char *cmd, const char *in_mode, int *psts)
         }
     }
 
-    symbol[MAX_DCL_SYMBOL] = '\0';
-
-    strncpy(symbol, in, MAX_DCL_SYMBOL);
-    d_symbol.dsc$w_length = strlen(symbol);
+    d_symbol.dsc$w_length = my_strlcpy(symbol, in, sizeof(symbol));
     _ckvmssts_noperl(lib$set_symbol(&d_sym_in, &d_symbol, &table));
 
-    strncpy(symbol, err, MAX_DCL_SYMBOL);
-    d_symbol.dsc$w_length = strlen(symbol);
+    d_symbol.dsc$w_length = my_strlcpy(symbol, err, sizeof(symbol));
     _ckvmssts_noperl(lib$set_symbol(&d_sym_err, &d_symbol, &table));
 
-    strncpy(symbol, out, MAX_DCL_SYMBOL);
-    d_symbol.dsc$w_length = strlen(symbol);
+    d_symbol.dsc$w_length = my_strlcpy(symbol, out, sizeof(symbol));
     _ckvmssts_noperl(lib$set_symbol(&d_sym_out, &d_symbol, &table));
 
     /* Done with the names for the pipes */
@@ -4492,8 +4355,7 @@ safe_popen(pTHX_ const char *cmd, const char *in_mode, int *psts)
         sprintf(cmd_sym_name,"PERL_POPEN_CMD%d",j);
         d_sym_cmd.dsc$w_length = strlen(cmd_sym_name);
 
-    strncpy(symbol, p, MAX_DCL_SYMBOL);
-    d_symbol.dsc$w_length = strlen(symbol);
+    d_symbol.dsc$w_length = my_strlcpy(symbol, p, sizeof(symbol));
     _ckvmssts_noperl(lib$set_symbol(&d_sym_cmd, &d_symbol, &table));
 
         if (strlen(p) > MAX_DCL_SYMBOL) {
@@ -4583,11 +4445,11 @@ Perl_my_popen(pTHX_ const char *cmd, const char *mode)
 
 /* Routine to close and cleanup a pipe info structure */
 
-static I32 my_pclose_pinfo(pTHX_ pInfo info) {
+static I32
+my_pclose_pinfo(pTHX_ pInfo info) {
 
     unsigned long int retsts;
-    int done, iss, n;
-    int status;
+    int done, n;
     pInfo next, last;
 
     /* If we were writing to a subprocess, insure that someone reading from
@@ -4728,7 +4590,15 @@ I32 Perl_my_pclose(pTHX_ PerlIO *fp)
   /* Roll our own prototype because we want this regardless of whether
    * _VMS_WAIT is defined.
    */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
   __pid_t __vms_waitpid( __pid_t __pid, int *__stat_loc, int __options );
+#ifdef __cplusplus
+}
+#endif
+
 #endif
 /* sort-of waitpid; special handling of pipe clean-up for subprocesses 
    created with popen(); otherwise partially emulate waitpid() unless 
@@ -4870,13 +4740,6 @@ my_gconvert(double val, int ndig, int trail, char *buf)
 
   loc = buf ? buf : __gcvtbuf;
 
-#ifndef __DECC  /* VAXCRTL gcvt uses E format for numbers < 1 */
-  if (val < 1) {
-    sprintf(loc,"%.*g",ndig,val);
-    return loc;
-  }
-#endif
-
   if (val) {
     if (!buf && ndig > DBL_DIG) ndig = DBL_DIG;
     return gcvt(val,ndig,loc);
@@ -4890,9 +4753,10 @@ my_gconvert(double val, int ndig, int trail, char *buf)
 /*}}}*/
 
 #if defined(__VAX) || !defined(NAML$C_MAXRSS)
-static int rms_free_search_context(struct FAB * fab)
+static int
+rms_free_search_context(struct FAB * fab)
 {
-struct NAM * nam;
+    struct NAM * nam;
 
     nam = fab->fab$l_nam;
     nam->nam$b_nop |= NAM$M_SYNCHK;
@@ -4934,9 +4798,10 @@ struct NAM * nam;
 #define rms_nam_name_type_l_size(nam) \
        (nam.nam$b_name + nam.nam$b_type)
 #else
-static int rms_free_search_context(struct FAB * fab)
+static int
+rms_free_search_context(struct FAB * fab)
 {
-struct NAML * nam;
+    struct NAML * nam;
 
     nam = fab->fab$l_naml;
     nam->naml$b_nop |= NAM$M_SYNCHK;
@@ -4999,7 +4864,8 @@ struct NAML * nam;
  * however in 8.3 the unlink/remove/delete routines will only properly handle
  * them if one of the PCP modes is active.
  */
-static int rms_erase(const char * vmsname)
+static int
+rms_erase(const char * vmsname)
 {
   int status;
   struct FAB myfab = cc$rms_fab;
@@ -5032,28 +4898,28 @@ vms_rename_with_acl(pTHX_ const struct dsc$descriptor_s * vms_src_dsc,
    /* I can not find online documentation for $change_acl
     * it appears to be replaced by $set_security some time ago */
 
-const unsigned int access_mode = 0;
-$DESCRIPTOR(obj_file_dsc,"FILE");
-char *vmsname;
-char *rslt;
-unsigned long int jpicode = JPI$_UIC, type = ACL$C_FILE;
-int aclsts, fndsts, rnsts = -1;
-unsigned int ctx = 0;
-struct dsc$descriptor_s fildsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
-struct dsc$descriptor_s * clean_dsc;
-
-struct myacedef {
-    unsigned char myace$b_length;
-    unsigned char myace$b_type;
-    unsigned short int myace$w_flags;
-    unsigned long int myace$l_access;
-    unsigned long int myace$l_ident;
-} newace = { sizeof(struct myacedef), ACE$C_KEYID, 0,
-            ACE$M_READ | ACE$M_WRITE | ACE$M_DELETE | ACE$M_CONTROL,
-            0},
-            oldace = { sizeof(struct myacedef), ACE$C_KEYID, 0, 0, 0};
-
-struct item_list_3
+    const unsigned int access_mode = 0;
+    $DESCRIPTOR(obj_file_dsc,"FILE");
+    char *vmsname;
+    char *rslt;
+    unsigned long int jpicode = JPI$_UIC;
+    int aclsts, fndsts, rnsts = -1;
+    unsigned int ctx = 0;
+    struct dsc$descriptor_s fildsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
+    struct dsc$descriptor_s * clean_dsc;
+    
+    struct myacedef {
+        unsigned char myace$b_length;
+        unsigned char myace$b_type;
+        unsigned short int myace$w_flags;
+        unsigned long int myace$l_access;
+        unsigned long int myace$l_ident;
+    } newace = { sizeof(struct myacedef), ACE$C_KEYID, 0,
+            ACE$M_READ | ACE$M_WRITE | ACE$M_DELETE | ACE$M_CONTROL,
+            0},
+            oldace = { sizeof(struct myacedef), ACE$C_KEYID, 0, 0, 0};
+
+    struct item_list_3
        findlst[3] = {{sizeof oldace, OSS$_ACL_FIND_ENTRY, &oldace, 0},
                      {sizeof oldace, OSS$_ACL_READ_ENTRY, &oldace, 0},
                      {0,0,0,0}},
@@ -5064,7 +4930,7 @@ struct item_list_3
 
     /* Expand the input spec using RMS, since we do not want to put
      * ACLs on the target of a symbolic link */
-    vmsname = PerlMem_malloc(NAM$C_MAXRSS+1);
+    vmsname = (char *)PerlMem_malloc(NAM$C_MAXRSS+1);
     if (vmsname == NULL)
        return SS$_INSFMEM;
 
@@ -5190,12 +5056,12 @@ struct item_list_3
 int
 Perl_rename(pTHX_ const char *src, const char * dst)
 {
-int retval;
-int pre_delete = 0;
-int src_sts;
-int dst_sts;
-Stat_t src_st;
-Stat_t dst_st;
+    int retval;
+    int pre_delete = 0;
+    int src_sts;
+    int dst_sts;
+    Stat_t src_st;
+    Stat_t dst_st;
 
     /* Validate the source file */
     src_sts = flex_lstat(src, &src_st);
@@ -5294,7 +5160,7 @@ Stat_t dst_st;
     {
        /* Is the source and dest both in VMS format */
        /* if the source is a directory, then need to fileify */
-       /*  and dest must be a directory or non-existant. */
+       /*  and dest must be a directory or non-existent. */
 
        char * vms_dst;
        int sts;
@@ -5307,7 +5173,7 @@ Stat_t dst_st;
         * on if one or more of them are directories.
         */
 
-       vms_dst = PerlMem_malloc(VMS_MAXRSS);
+       vms_dst = (char *)PerlMem_malloc(VMS_MAXRSS);
        if (vms_dst == NULL)
            _ckvmssts_noperl(SS$_INSFMEM);
 
@@ -5315,18 +5181,18 @@ Stat_t dst_st;
        char * ret_str;
        char * vms_dir_file;
 
-           vms_dir_file = PerlMem_malloc(VMS_MAXRSS);
+           vms_dir_file = (char *)PerlMem_malloc(VMS_MAXRSS);
            if (vms_dir_file == NULL)
                _ckvmssts_noperl(SS$_INSFMEM);
 
-           /* If the dest is a directory, we must remove it
+           /* If the dest is a directory, we must remove it */
            if (dst_sts == 0) {
                int d_sts;
                d_sts = mp_do_kill_file(aTHX_ dst_st.st_devnam, 1);
                if (d_sts != 0) {
                    PerlMem_free(vms_dst);
                    errno = EIO;
-                   return sts;
+                   return d_sts;
                }
 
                pre_delete = 1;
@@ -5341,10 +5207,6 @@ Stat_t dst_st;
           }
 
            /* The source must be a file specification */
-           vms_dir_file = PerlMem_malloc(VMS_MAXRSS);
-           if (vms_dir_file == NULL)
-               _ckvmssts_noperl(SS$_INSFMEM);
-
            ret_str = do_fileify_dirspec(vms_dst, vms_dir_file, 0, NULL);
            if (ret_str == NULL) {
                PerlMem_free(vms_dst);
@@ -5537,7 +5399,7 @@ int_rmsexpand
           isunix = 1;
           char * ret_spec;
 
-          vmsfspec = PerlMem_malloc(VMS_MAXRSS);
+          vmsfspec = (char *)PerlMem_malloc(VMS_MAXRSS);
           if (vmsfspec == NULL) _ckvmssts_noperl(SS$_INSFMEM);
           ret_spec = int_tovmsspec(filespec, vmsfspec, 0, fs_utf8);
           if (ret_spec == NULL) {
@@ -5570,7 +5432,7 @@ int_rmsexpand
     int t_isunix;
     t_isunix = is_unix_filespec(defspec);
     if (t_isunix) {
-      vmsdefspec = PerlMem_malloc(VMS_MAXRSS);
+      vmsdefspec = (char *)PerlMem_malloc(VMS_MAXRSS);
       if (vmsdefspec == NULL) _ckvmssts_noperl(SS$_INSFMEM);
       ret_spec = int_tovmsspec(defspec, vmsdefspec, 0, dfs_utf8);
 
@@ -5588,10 +5450,10 @@ int_rmsexpand
   }
 
   /* Now we need the expansion buffers */
-  esa = PerlMem_malloc(NAM$C_MAXRSS + 1);
+  esa = (char *)PerlMem_malloc(NAM$C_MAXRSS + 1);
   if (esa == NULL) _ckvmssts_noperl(SS$_INSFMEM);
 #if !defined(__VAX) && defined(NAML$C_MAXRSS)
-  esal = PerlMem_malloc(VMS_MAXRSS);
+  esal = (char *)PerlMem_malloc(VMS_MAXRSS);
   if (esal == NULL) _ckvmssts_noperl(SS$_INSFMEM);
 #endif
   rms_set_esal(mynam, esa, NAM$C_MAXRSS, esal, VMS_MAXRSS-1);
@@ -5600,7 +5462,7 @@ int_rmsexpand
    * addresses unless you suppress the short name.
    */
 #if !defined(__VAX) && defined(NAML$C_MAXRSS)
-  outbufl = PerlMem_malloc(VMS_MAXRSS);
+  outbufl = (char *)PerlMem_malloc(VMS_MAXRSS);
   if (outbufl == NULL) _ckvmssts_noperl(SS$_INSFMEM);
 #endif
    rms_set_rsal(mynam, outbuf, NAM$C_MAXRSS, outbufl, (VMS_MAXRSS - 1));
@@ -5722,11 +5584,11 @@ int_expanded:
     if (defspec && *defspec) {
       char *defesal = NULL;
       char *defesa = NULL;
-      defesa = PerlMem_malloc(VMS_MAXRSS + 1);
+      defesa = (char *)PerlMem_malloc(VMS_MAXRSS + 1);
       if (defesa != NULL) {
         struct FAB deffab = cc$rms_fab;
 #if !defined(__VAX) && defined(NAML$C_MAXRSS)
-        defesal = PerlMem_malloc(VMS_MAXRSS + 1);
+        defesal = (char *)PerlMem_malloc(VMS_MAXRSS + 1);
         if (defesal == NULL) _ckvmssts_noperl(SS$_INSFMEM);
 #endif
        rms_setup_nam(defnam);
@@ -5856,7 +5718,7 @@ int_expanded:
         /* VMS file specs are not in UTF-8 */
         if (fs_utf8 != NULL)
             *fs_utf8 = 0;
-        strcpy(outbuf, spec_buf);
+        my_strlcpy(outbuf, spec_buf, VMS_MAXRSS);
         ret_spec = outbuf;
       }
     }
@@ -5869,8 +5731,8 @@ int_expanded:
            char * src;
            char * new_src = NULL;
            if (spec_buf == outbuf) {
-               new_src = PerlMem_malloc(VMS_MAXRSS);
-               strcpy(new_src, spec_buf);
+               new_src = (char *)PerlMem_malloc(VMS_MAXRSS);
+               my_strlcpy(new_src, spec_buf, VMS_MAXRSS);
            } else {
                src = spec_buf;
            }
@@ -5885,7 +5747,7 @@ int_expanded:
 
            /* Copy the buffer if needed */
            if (outbuf != spec_buf)
-               strcpy(outbuf, spec_buf);
+               my_strlcpy(outbuf, spec_buf, VMS_MAXRSS);
            ret_spec = outbuf;
       }
     }
@@ -5962,18 +5824,31 @@ mp_do_rmsexpand
 }
 /*}}}*/
 /* External entry points */
-char *Perl_rmsexpand(pTHX_ const char *spec, char *buf, const char *def, unsigned opt)
-{ return do_rmsexpand(spec,buf,0,def,opt,NULL,NULL); }
-char *Perl_rmsexpand_ts(pTHX_ const char *spec, char *buf, const char *def, unsigned opt)
-{ return do_rmsexpand(spec,buf,1,def,opt,NULL,NULL); }
-char *Perl_rmsexpand_utf8
-  (pTHX_ const char *spec, char *buf, const char *def,
-   unsigned opt, int * fs_utf8, int * dfs_utf8)
-{ return do_rmsexpand(spec,buf,0,def,opt, fs_utf8, dfs_utf8); }
-char *Perl_rmsexpand_utf8_ts
-  (pTHX_ const char *spec, char *buf, const char *def,
-   unsigned opt, int * fs_utf8, int * dfs_utf8)
-{ return do_rmsexpand(spec,buf,1,def,opt, fs_utf8, dfs_utf8); }
+char *
+Perl_rmsexpand(pTHX_ const char *spec, char *buf, const char *def, unsigned opt)
+{
+    return do_rmsexpand(spec, buf, 0, def, opt, NULL, NULL);
+}
+
+char *
+Perl_rmsexpand_ts(pTHX_ const char *spec, char *buf, const char *def, unsigned opt)
+{
+    return do_rmsexpand(spec, buf, 1, def, opt, NULL, NULL);
+}
+
+char *
+Perl_rmsexpand_utf8(pTHX_ const char *spec, char *buf, const char *def,
+                    unsigned opt, int * fs_utf8, int * dfs_utf8)
+{
+    return do_rmsexpand(spec, buf, 0, def, opt, fs_utf8, dfs_utf8);
+}
+
+char *
+Perl_rmsexpand_utf8_ts(pTHX_ const char *spec, char *buf, const char *def,
+                       unsigned opt, int * fs_utf8, int * dfs_utf8)
+{
+    return do_rmsexpand(spec, buf, 1, def, opt, fs_utf8, dfs_utf8);
+}
 
 
 /*
@@ -6015,12 +5890,10 @@ char *Perl_rmsexpand_utf8_ts
 static char *
 int_fileify_dirspec(const char *dir, char *buf, int *utf8_fl)
 {
-    unsigned long int dirlen, retlen, addmfd = 0, hasfilename = 0;
+    unsigned long int dirlen, retlen, hasfilename = 0;
     char *cp1, *cp2, *lastdir;
     char *trndir, *vmsdir;
     unsigned short int trnlnm_iter_count;
-    int is_vms = 0;
-    int is_unix = 0;
     int sts;
     if (utf8_fl != NULL)
        *utf8_fl = 0;
@@ -6042,7 +5915,7 @@ int_fileify_dirspec(const char *dir, char *buf, int *utf8_fl)
       set_errno(ENAMETOOLONG); set_vaxc_errno(RMS$_SYN);
       return NULL;
     }
-    trndir = PerlMem_malloc(VMS_MAXRSS + 1);
+    trndir = (char *)PerlMem_malloc(VMS_MAXRSS + 1);
     if (trndir == NULL) _ckvmssts_noperl(SS$_INSFMEM);
     if (!strpbrk(dir+1,"/]>:")  &&
        (!decc_posix_compliant_pathnames && decc_disable_posix_root)) {
@@ -6055,7 +5928,7 @@ int_fileify_dirspec(const char *dir, char *buf, int *utf8_fl)
       dirlen = strlen(trndir);
     }
     else {
-      strncpy(trndir,dir,dirlen);
+      memcpy(trndir, dir, dirlen);
       trndir[dirlen] = '\0';
     }
 
@@ -6098,35 +5971,14 @@ int_fileify_dirspec(const char *dir, char *buf, int *utf8_fl)
       }
     }
 
-    vmsdir = PerlMem_malloc(VMS_MAXRSS + 1);
+    vmsdir = (char *)PerlMem_malloc(VMS_MAXRSS + 1);
     if (vmsdir == NULL) _ckvmssts_noperl(SS$_INSFMEM);
     cp1 = strpbrk(trndir,"]:>");
-    if (hasfilename || !cp1) { /* filename present or not VMS */
-
-      if (decc_efs_charset && !cp1) {
+    if (cp1 && *(cp1+1) == ':')   /* DECNet node spec with :: */
+        cp1 = strpbrk(cp1+2,"]:>");
 
-          /* EFS handling for UNIX mode */
-
-          /* Just remove the trailing '/' and we should be done */
-          STRLEN trndir_len;
-          trndir_len = strlen(trndir);
-
-          if (trndir_len > 1) {
-              trndir_len--;
-              if (trndir[trndir_len] == '/') {
-                  trndir[trndir_len] = '\0';
-              }
-          }
-          strcpy(buf, trndir);
-          PerlMem_free(trndir);
-          PerlMem_free(vmsdir);
-          return buf;
-      }
+    if (hasfilename || !cp1) { /* filename present or not VMS */
 
-      /* For non-EFS mode, this is left for backwards compatibility */
-      /* For EFS mode, this is only done for VMS format filespecs as */
-      /* Perl programs generally have problems when a UNIX format spec */
-      /* returns a VMS format spec */
       if (trndir[0] == '.') {
         if (trndir[1] == '\0' || (trndir[1] == '/' && trndir[2] == '\0')) {
          PerlMem_free(trndir);
@@ -6244,6 +6096,20 @@ int_fileify_dirspec(const char *dir, char *buf, int *utf8_fl)
                 /* The .dir for now, and fix this better later */
                 dirlen = cp2 - trndir;
             }
+            if (decc_efs_charset && !strchr(trndir,'/')) {
+                /* Dots are allowed in dir names, so escape them if input not in Unix syntax. */
+                char *cp4 = is_dir ? (cp2 - 1) : cp2;
+                  
+                for (; cp4 > cp1; cp4--) {
+                    if (*cp4 == '.') {
+                        if ((cp4 - 1 > trndir) && (*(cp4 - 1) != '^')) {
+                            memmove(cp4 + 1, cp4, trndir + dirlen - cp4 + 1);
+                            *cp4 = '^';
+                            dirlen++;
+                       }
+                    }
+                }
+            }
         }
 
       }
@@ -6254,52 +6120,12 @@ int_fileify_dirspec(const char *dir, char *buf, int *utf8_fl)
 
       /* We've picked up everything up to the directory file name.
          Now just add the type and version, and we're set. */
-
-      /* We should only add type for VMS syntax, but historically Perl
-         has added it for UNIX style also */
-
-      /* Fix me - we should not be using the same routine for VMS and
-         UNIX format files.  Things are too tangled so we need to lookup
-         what syntax the output is */
-
-      is_unix = 0;
-      is_vms = 0;
-      lastdir = strrchr(trndir,'/');
-      if (lastdir) {
-          is_unix = 1;
-      } else {
-          lastdir = strpbrk(trndir,"]:>");
-          if (lastdir) {
-              is_vms = 1;
-          }
-      }
-
-      if ((is_vms == 0) && (is_unix == 0)) {
-          /* We still do not  know? */
-          is_unix = decc_filename_unix_report;
-          if (is_unix == 0)
-              is_vms = 1;
-      }
-
-      if ((is_unix && !decc_efs_charset) || is_vms) {
-
-           /* It is a bug to add a .dir to a UNIX format directory spec */
-           /* However Perl on VMS may have programs that expect this so */
-           /* If not using EFS character specifications allow it. */
-
-           if ((!decc_efs_case_preserve) && vms_process_case_tolerant) {
-               /* Traditionally Perl expects filenames in lower case */
-               strcat(buf, ".dir");
-           } else {
-               /* VMS expects the .DIR to be in upper case */
-               strcat(buf, ".DIR");
-           }
-
-           /* It is also a bug to put a VMS format version on a UNIX file */
-           /* specification.  Perl self tests are looking for this */
-           if (is_vms || !(decc_efs_charset || decc_filename_unix_report))
-               strcat(buf, ";1");
-      }
+      if ((!decc_efs_case_preserve) && vms_process_case_tolerant)
+          strcat(buf,".dir");
+      else
+          strcat(buf,".DIR");
+      if (!decc_filename_unix_no_version)
+          strcat(buf,";1");
       PerlMem_free(trndir);
       PerlMem_free(vmsdir);
       return buf;
@@ -6309,18 +6135,16 @@ int_fileify_dirspec(const char *dir, char *buf, int *utf8_fl)
       char *esa, *esal, term, *cp;
       char *my_esa;
       int my_esa_len;
-      unsigned long int sts, cmplen, haslower = 0;
-      unsigned int nam_fnb;
-      char * nam_type;
+      unsigned long int cmplen, haslower = 0;
       struct FAB dirfab = cc$rms_fab;
       rms_setup_nam(savnam);
       rms_setup_nam(dirnam);
 
-      esa = PerlMem_malloc(NAM$C_MAXRSS + 1);
+      esa = (char *)PerlMem_malloc(NAM$C_MAXRSS + 1);
       if (esa == NULL) _ckvmssts_noperl(SS$_INSFMEM);
       esal = NULL;
 #if !defined(__VAX) && defined(NAML$C_MAXRSS)
-      esal = PerlMem_malloc(VMS_MAXRSS);
+      esal = (char *)PerlMem_malloc(VMS_MAXRSS);
       if (esal == NULL) _ckvmssts_noperl(SS$_INSFMEM);
 #endif
       rms_set_fna(dirfab, dirnam, trndir, strlen(trndir));
@@ -6360,7 +6184,10 @@ int_fileify_dirspec(const char *dir, char *buf, int *utf8_fl)
           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;
+          if (dirfab.fab$l_sts    == RMS$_FNF
+              || dirfab.fab$l_sts == RMS$_DNF
+              || dirfab.fab$l_sts == RMS$_FND)
+                dirnam = savnam;
           else { 
            int fab_sts;
            fab_sts = dirfab.fab$l_sts;
@@ -6416,7 +6243,7 @@ int_fileify_dirspec(const char *dir, char *buf, int *utf8_fl)
 
       if (rms_is_nam_fnb(dirnam, NAM$M_EXP_NAME)) {
         /* They provided at least the name; we added the type, if necessary, */
-        strcpy(buf, my_esa);
+        my_strlcpy(buf, my_esa, VMS_MAXRSS);
        sts = rms_free_search_context(&dirfab);
        PerlMem_free(trndir);
        PerlMem_free(esa);
@@ -6461,7 +6288,7 @@ int_fileify_dirspec(const char *dir, char *buf, int *utf8_fl)
       if ((cp1) != NULL) {
         /* There's more than one directory in the path.  Just roll back. */
         *cp1 = term;
-        strcpy(buf, my_esa);
+        my_strlcpy(buf, my_esa, VMS_MAXRSS);
       }
       else {
         if (rms_is_nam_fnb(dirnam, NAM$M_ROOT_DIR)) {
@@ -6536,12 +6363,12 @@ int_fileify_dirspec(const char *dir, char *buf, int *utf8_fl)
           }
         }
         else {  /* This is a top-level dir.  Add the MFD to the path. */
-          cp1 = my_esa;
-          cp2 = buf;
-          while ((*cp1 != ':')  && (*cp1 != '\0')) *(cp2++) = *(cp1++);
-          strcpy(cp2,":[000000]");
-          cp1 += 2;
-          strcpy(cp2+9,cp1);
+          cp1 = strrchr(my_esa, ':');
+          assert(cp1);
+          memmove(buf, my_esa, cp1 - my_esa + 1);
+          memmove(buf + (cp1 - my_esa) + 1, "[000000]", 8);
+          memmove(buf + (cp1 - my_esa) + 9, cp1 + 2, retlen - (cp1 - my_esa + 2));
+          buf[retlen + 7] = '\0';  /* We've inserted '000000]' */
         }
       }
       sts = rms_free_search_context(&dirfab);
@@ -6563,7 +6390,8 @@ int_fileify_dirspec(const char *dir, char *buf, int *utf8_fl)
 
 
 /*{{{ char *fileify_dirspec[_ts](char *dir, char *buf, int * utf8_fl)*/
-static char *mp_do_fileify_dirspec(pTHX_ const char *dir,char *buf,int ts, int *utf8_fl)
+static char *
+mp_do_fileify_dirspec(pTHX_ const char *dir,char *buf,int ts, int *utf8_fl)
 {
     static char __fileify_retbuf[VMS_MAXRSS];
     char * fileified, *ret_spec, *ret_buf;
@@ -6594,19 +6422,36 @@ static char *mp_do_fileify_dirspec(pTHX_ const char *dir,char *buf,int ts, int *
 /*}}}*/
 
 /* External entry points */
-char *Perl_fileify_dirspec(pTHX_ const char *dir, char *buf)
-{ return do_fileify_dirspec(dir,buf,0,NULL); }
-char *Perl_fileify_dirspec_ts(pTHX_ const char *dir, char *buf)
-{ return do_fileify_dirspec(dir,buf,1,NULL); }
-char *Perl_fileify_dirspec_utf8(pTHX_ const char *dir, char *buf, int * utf8_fl)
-{ return do_fileify_dirspec(dir,buf,0,utf8_fl); }
-char *Perl_fileify_dirspec_utf8_ts(pTHX_ const char *dir, char *buf, int * utf8_fl)
-{ return do_fileify_dirspec(dir,buf,1,utf8_fl); }
-
-static char * int_pathify_dirspec_simple(const char * dir, char * buf,
+char *
+Perl_fileify_dirspec(pTHX_ const char *dir, char *buf)
+{
+    return do_fileify_dirspec(dir, buf, 0, NULL);
+}
+
+char *
+Perl_fileify_dirspec_ts(pTHX_ const char *dir, char *buf)
+{
+    return do_fileify_dirspec(dir, buf, 1, NULL);
+}
+
+char *
+Perl_fileify_dirspec_utf8(pTHX_ const char *dir, char *buf, int * utf8_fl)
+{
+    return do_fileify_dirspec(dir, buf, 0, utf8_fl);
+}
+
+char *
+Perl_fileify_dirspec_utf8_ts(pTHX_ const char *dir, char *buf, int * utf8_fl)
+{
+    return do_fileify_dirspec(dir, buf, 1, utf8_fl);
+}
+
+static char * 
+int_pathify_dirspec_simple(const char * dir, char * buf,
     char * v_spec, int v_len, char * r_spec, int r_len,
     char * d_spec, int d_len, char * n_spec, int n_len,
-    char * e_spec, int e_len, char * vs_spec, int vs_len) {
+    char * e_spec, int e_len, char * vs_spec, int vs_len)
+{
 
     /* VMS specification - Try to do this the simple way */
     if ((v_len + r_len > 0) || (d_len > 0)) {
@@ -6628,10 +6473,10 @@ static char * int_pathify_dirspec_simple(const char * dir, char * buf,
              int len;
              len = v_len + r_len + d_len - 1;
              char dclose = d_spec[d_len - 1];
-             strncpy(buf, dir, len);
+             memcpy(buf, dir, len);
              buf[len] = '.';
              len++;
-             strncpy(&buf[len], n_spec, n_len);
+             memcpy(&buf[len], n_spec, n_len);
              len += n_len;
              buf[len] = dclose;
              buf[len + 1] = '\0';
@@ -6646,20 +6491,33 @@ static char * int_pathify_dirspec_simple(const char * dir, char * buf,
             int len;
             len = v_len + r_len + d_len - 1;
             char dclose = d_spec[d_len - 1];
-            strncpy(buf, dir, len);
+            memcpy(buf, dir, len);
             buf[len] = '.';
             len++;
-            strncpy(&buf[len], n_spec, n_len);
+            memcpy(&buf[len], n_spec, n_len);
             len += n_len;
             if (e_len > 0) {
                 if (decc_efs_charset) {
-                    buf[len] = '^';
-                    len++;
-                    strncpy(&buf[len], e_spec, e_len);
-                    len += e_len;
-                } else {
-                    set_vaxc_errno(RMS$_DIR);
-                    set_errno(ENOTDIR);
+                    if (e_len == 4 
+                        && (toupper(e_spec[1]) == 'D')
+                        && (toupper(e_spec[2]) == 'I')
+                        && (toupper(e_spec[3]) == 'R')) {
+
+                        /* Corner case: directory spec with invalid version.
+                         * Valid would have followed is_dir path above.
+                         */
+                        SETERRNO(ENOTDIR, RMS$_DIR);
+                        return NULL;
+                    }
+                    else {
+                        buf[len] = '^';
+                        len++;
+                        memcpy(&buf[len], e_spec, e_len);
+                        len += e_len;
+                    }
+                }
+                else {
+                    SETERRNO(ENOTDIR, RMS$_DIR);
                     return NULL;
                 }
             }
@@ -6683,7 +6541,8 @@ static char * int_pathify_dirspec_simple(const char * dir, char * buf,
 
 /* Internal routine to make sure or convert a directory to be in a */
 /* path specification.  No utf8 flag because it is not changed or used */
-static char *int_pathify_dirspec(const char *dir, char *buf)
+static char *
+int_pathify_dirspec(const char *dir, char *buf)
 {
     char * v_spec, * r_spec, * d_spec, * n_spec, * e_spec, * vs_spec;
     int sts, v_len, r_len, d_len, n_len, e_len, vs_len;
@@ -6710,13 +6569,13 @@ static char *int_pathify_dirspec(const char *dir, char *buf)
       return NULL;
     }
 
-    trndir = PerlMem_malloc(VMS_MAXRSS);
+    trndir = (char *)PerlMem_malloc(VMS_MAXRSS);
     if (trndir == NULL)
         _ckvmssts_noperl(SS$_INSFMEM);
 
     /* If no directory specified use the current default */
     if (*dir)
-        strcpy(trndir, dir);
+        my_strlcpy(trndir, dir, VMS_MAXRSS);
     else {
         getcwd(trndir, VMS_MAXRSS - 1);
         need_to_lower = 1;
@@ -6734,7 +6593,7 @@ static char *int_pathify_dirspec(const char *dir, char *buf)
 
         /* Trap simple rooted lnms, and return lnm:[000000] */
         if (!strcmp(trndir+trnlen-2,".]")) {
-            strcpy(buf, dir);
+            my_strlcpy(buf, dir, VMS_MAXRSS);
             strcat(buf, ":[000000]");
             PerlMem_free(trndir);
 
@@ -6788,7 +6647,7 @@ static char *int_pathify_dirspec(const char *dir, char *buf)
                         /* Traditional mode, assume .DIR is directory */
                         buf[0] = '[';
                         buf[1] = '.';
-                        strncpy(&buf[2], n_spec, n_len);
+                        memcpy(&buf[2], n_spec, n_len);
                         buf[n_len + 2] = ']';
                         buf[n_len + 3] = '\0';
                         PerlMem_free(trndir);
@@ -6821,7 +6680,7 @@ static char *int_pathify_dirspec(const char *dir, char *buf)
         /* Simple way did not work, which means that a logical name */
         /* was present for the directory specification.             */
         /* Need to use an rmsexpand variant to decode it completely */
-        exp_spec = PerlMem_malloc(VMS_MAXRSS);
+        exp_spec = (char *)PerlMem_malloc(VMS_MAXRSS);
         if (exp_spec == NULL)
             _ckvmssts_noperl(SS$_INSFMEM);
 
@@ -6859,65 +6718,55 @@ static char *int_pathify_dirspec(const char *dir, char *buf)
         return ret_spec;
 
     } else {
-        /* Unix specification, Could be trivial conversion */
-        STRLEN dir_len;
-        dir_len = strlen(trndir);
-
-        /* If the extended file character set is in effect */
-        /* then pathify is simple */
-
-        if (!decc_efs_charset) {
-            /* Have to deal with traiing '.dir' or extra '.' */
-            /* that should not be there in legacy mode, but is */
-
-            char * lastdot;
-            char * lastslash;
-            int is_dir;
+        /* Unix specification, Could be trivial conversion, */
+        /* but have to deal with trailing '.dir' or extra '.' */
 
-            lastslash = strrchr(trndir, '/');
-            if (lastslash == NULL)
-                lastslash = trndir;
-            else
-                lastslash++;
-
-            lastdot = NULL;
+        char * lastdot;
+        char * lastslash;
+        int is_dir;
+        STRLEN dir_len = strlen(trndir);
 
-            /* '..' or '.' are valid directory components */
-            is_dir = 0;
-            if (lastslash[0] == '.') {
-                if (lastslash[1] == '\0') {
-                   is_dir = 1;
-                } else if (lastslash[1] == '.') {
-                    if (lastslash[2] == '\0') {
+        lastslash = strrchr(trndir, '/');
+        if (lastslash == NULL)
+            lastslash = trndir;
+        else
+            lastslash++;
+
+        lastdot = NULL;
+
+        /* '..' or '.' are valid directory components */
+        is_dir = 0;
+        if (lastslash[0] == '.') {
+            if (lastslash[1] == '\0') {
+               is_dir = 1;
+            } else if (lastslash[1] == '.') {
+                if (lastslash[2] == '\0') {
+                    is_dir = 1;
+                } else {
+                    /* And finally allow '...' */
+                    if ((lastslash[2] == '.') && (lastslash[3] == '\0')) {
                         is_dir = 1;
-                    } else {
-                        /* And finally allow '...' */
-                        if ((lastslash[2] == '.') && (lastslash[3] == '\0')) {
-                            is_dir = 1;
-                        }
                     }
                 }
             }
+        }
 
-            if (!is_dir) {
-               lastdot = strrchr(lastslash, '.');
-            }
-            if (lastdot != NULL) {
-                STRLEN e_len;
-
-                /* '.dir' is discarded, and any other '.' is invalid */
-                e_len = strlen(lastdot);
-
-                is_dir = is_dir_ext(lastdot, e_len, NULL, 0);
+        if (!is_dir) {
+           lastdot = strrchr(lastslash, '.');
+        }
+        if (lastdot != NULL) {
+            STRLEN e_len;
+             /* '.dir' is discarded, and any other '.' is invalid */
+            e_len = strlen(lastdot);
 
-                if (is_dir) {
-                    dir_len = dir_len - 4;
+            is_dir = is_dir_ext(lastdot, e_len, NULL, 0);
 
-                }
+            if (is_dir) {
+                dir_len = dir_len - 4;
             }
         }
 
-        strcpy(buf, trndir);
+        my_strlcpy(buf, trndir, VMS_MAXRSS);
         if (buf[dir_len - 1] != '/') {
             buf[dir_len] = '/';
             buf[dir_len + 1] = '\0';
@@ -6985,7 +6834,8 @@ static char *int_pathify_dirspec(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, int * utf8_fl)
+static char *
+mp_do_pathify_dirspec(pTHX_ const char *dir,char *buf, int ts, int * utf8_fl)
 {
     static char __pathify_retbuf[VMS_MAXRSS];
     char * pathified, *ret_spec, *ret_buf;
@@ -7017,25 +6867,40 @@ static char *mp_do_pathify_dirspec(pTHX_ const char *dir,char *buf, int ts, int
 
 
 /* External entry points */
-char *Perl_pathify_dirspec(pTHX_ const char *dir, char *buf)
-{ return do_pathify_dirspec(dir,buf,0,NULL); }
-char *Perl_pathify_dirspec_ts(pTHX_ const char *dir, char *buf)
-{ return do_pathify_dirspec(dir,buf,1,NULL); }
-char *Perl_pathify_dirspec_utf8(pTHX_ const char *dir, char *buf, int *utf8_fl)
-{ return do_pathify_dirspec(dir,buf,0,utf8_fl); }
-char *Perl_pathify_dirspec_utf8_ts(pTHX_ const char *dir, char *buf, int *utf8_fl)
-{ return do_pathify_dirspec(dir,buf,1,utf8_fl); }
+char *
+Perl_pathify_dirspec(pTHX_ const char *dir, char *buf)
+{
+    return do_pathify_dirspec(dir, buf, 0, NULL);
+}
+
+char *
+Perl_pathify_dirspec_ts(pTHX_ const char *dir, char *buf)
+{
+    return do_pathify_dirspec(dir, buf, 1, NULL);
+}
+
+char *
+Perl_pathify_dirspec_utf8(pTHX_ const char *dir, char *buf, int *utf8_fl)
+{
+    return do_pathify_dirspec(dir, buf, 0, utf8_fl);
+}
+
+char *
+Perl_pathify_dirspec_utf8_ts(pTHX_ const char *dir, char *buf, int *utf8_fl)
+{
+    return do_pathify_dirspec(dir, buf, 1, utf8_fl);
+}
 
 /* Internal tounixspec routine that does not use a thread context */
 /*{{{ char *int_tounixspec[_ts](char *spec, char *buf, int *)*/
-static char *int_tounixspec(const char *spec, char *rslt, int * utf8_fl)
+static char *
+int_tounixspec(const char *spec, char *rslt, int * utf8_fl)
 {
   char *dirend, *cp1, *cp3, *tmp;
   const char *cp2;
-  int devlen, dirlen, retlen = VMS_MAXRSS;
-  int expand = 1; /* guarantee room for leading and trailing slashes */
+  int dirlen;
   unsigned short int trnlnm_iter_count;
-  int cmp_rslt;
+  int cmp_rslt, outchars_added;
   if (utf8_fl != NULL)
     *utf8_fl = 0;
 
@@ -7068,10 +6933,9 @@ static char *int_tounixspec(const char *spec, char *rslt, int * utf8_fl)
       int tunix_len;
       int nl_flag;
 
-      tunix = PerlMem_malloc(VMS_MAXRSS);
+      tunix = (char *)PerlMem_malloc(VMS_MAXRSS);
       if (tunix == NULL) _ckvmssts_noperl(SS$_INSFMEM);
-      strcpy(tunix, spec);
-      tunix_len = strlen(tunix);
+      tunix_len = my_strlcpy(tunix, spec, VMS_MAXRSS);
       nl_flag = 0;
       if (tunix[tunix_len - 1] == '\n') {
        tunix[tunix_len - 1] = '\"';
@@ -7082,13 +6946,13 @@ static char *int_tounixspec(const char *spec, char *rslt, int * utf8_fl)
       uspec = decc$translate_vms(tunix);
       PerlMem_free(tunix);
       if ((int)uspec > 0) {
-       strcpy(rslt,uspec);
+       my_strlcpy(rslt, uspec, VMS_MAXRSS);
        if (nl_flag) {
          strcat(rslt,"\n");
        }
        else {
          /* If we can not translate it, makemaker wants as-is */
-         strcpy(rslt, spec);
+         my_strlcpy(rslt, spec, VMS_MAXRSS);
        }
        return rslt;
       }
@@ -7127,22 +6991,34 @@ static char *int_tounixspec(const char *spec, char *rslt, int * utf8_fl)
       }
     }
   }
-  /* This is already UNIX or at least nothing VMS understands */
+
+  cp1 = rslt;
+  cp2 = spec;
+
+  /* This is already UNIX or at least nothing VMS understands,
+   * so all we can reasonably do is unescape extended chars.
+   */
   if (cmp_rslt) {
-    strcpy(rslt,spec);
+    while (*cp2) {
+        cp2 += copy_expand_vms_filename_escape(cp1, cp2, &outchars_added);
+        cp1 += outchars_added;
+    }
+    *cp1 = '\0';    
     if (vms_debug_fileify) {
         fprintf(stderr, "int_tounixspec: rslt = %s\n", rslt);
     }
     return rslt;
   }
 
-  cp1 = rslt;
-  cp2 = spec;
   dirend = strrchr(spec,']');
   if (dirend == NULL) dirend = strrchr(spec,'>');
   if (dirend == NULL) dirend = strchr(spec,':');
   if (dirend == NULL) {
-    strcpy(rslt,spec);
+    while (*cp2) {
+        cp2 += copy_expand_vms_filename_escape(cp1, cp2, &outchars_added);
+        cp1 += outchars_added;
+    }
+    *cp1 = '\0';    
     if (vms_debug_fileify) {
         fprintf(stderr, "int_tounixspec: rslt = %s\n", rslt);
     }
@@ -7150,7 +7026,6 @@ static char *int_tounixspec(const char *spec, char *rslt, int * utf8_fl)
   }
 
   /* Special case 1 - sys$posix_root = / */
-#if __CRTL_VER >= 70000000
   if (!decc_disable_posix_root) {
     if (strncasecmp(spec, "SYS$POSIX_ROOT:", 15) == 0) {
       *cp1 = '/';
@@ -7158,36 +7033,23 @@ static char *int_tounixspec(const char *spec, char *rslt, int * utf8_fl)
       cp2 = cp2 + 15;
       }
   }
-#endif
 
   /* Special case 2 - Convert NLA0: to /dev/null */
-#if __CRTL_VER < 70000000
-  cmp_rslt = strncmp(spec,"NLA0:", 5);
-  if (cmp_rslt != 0)
-     cmp_rslt = strncmp(spec,"nla0:", 5);
-#else
   cmp_rslt = strncasecmp(spec,"NLA0:", 5);
-#endif
   if (cmp_rslt == 0) {
     strcpy(rslt, "/dev/null");
     cp1 = cp1 + 9;
     cp2 = cp2 + 5;
     if (spec[6] != '\0') {
-      cp1[9] == '/';
+      cp1[9] = '/';
       cp1++;
       cp2++;
     }
   }
 
    /* Also handle special case "SYS$SCRATCH:" */
-#if __CRTL_VER < 70000000
-  cmp_rslt = strncmp(spec,"SYS$SCRATCH:", 12);
-  if (cmp_rslt != 0)
-     cmp_rslt = strncmp(spec,"sys$scratch:", 12);
-#else
   cmp_rslt = strncasecmp(spec,"SYS$SCRATCH:", 12);
-#endif
-  tmp = PerlMem_malloc(VMS_MAXRSS);
+  tmp = (char *)PerlMem_malloc(VMS_MAXRSS);
   if (tmp == NULL) _ckvmssts_noperl(SS$_INSFMEM);
   if (cmp_rslt == 0) {
   int islnm;
@@ -7198,7 +7060,7 @@ static char *int_tounixspec(const char *spec, char *rslt, int * utf8_fl)
       cp1 = cp1 + 4;
       cp2 = cp2 + 12;
       if (spec[12] != '\0') {
-       cp1[4] == '/';
+       cp1[4] = '/';
        cp1++;
        cp2++;
       }
@@ -7250,9 +7112,8 @@ static char *int_tounixspec(const char *spec, char *rslt, int * utf8_fl)
       *(cp1++) = '/';
     }
     if ((*cp2 == '^')) {
-       /* EFS file escape, pass the next character as is */
-       /* Fix me: HEX encoding for Unicode not implemented */
-       cp2++;
+        cp2 += copy_expand_vms_filename_escape(cp1, cp2, &outchars_added);
+        cp1 += outchars_added;
     }
     else if ( *cp2 == '.') {
       if (*(cp2+1) == '.' && *(cp2+2) == '.') {
@@ -7265,13 +7126,11 @@ static char *int_tounixspec(const char *spec, char *rslt, int * utf8_fl)
   PerlMem_free(tmp);
   for (; cp2 <= dirend; cp2++) {
     if ((*cp2 == '^')) {
-       /* EFS file escape, pass the next character as is */
-       /* Fix me: HEX encoding for Unicode not implemented */
-       *(cp1++) = *(++cp2);
-        /* An escaped dot stays as is -- don't convert to slash */
-        if (*cp2 == '.') cp2++;
+        /* EFS file escape -- unescape it. */
+        cp2 += copy_expand_vms_filename_escape(cp1, cp2, &outchars_added) - 1;
+        cp1 += outchars_added;
     }
-    if (*cp2 == ':') {
+    else if (*cp2 == ':') {
       *(cp1++) = '/';
       if (*(cp2+1) == '[' || *(cp2+1) == '<') cp2++;
     }
@@ -7312,8 +7171,7 @@ static char *int_tounixspec(const char *spec, char *rslt, int * utf8_fl)
   }
   /* Translate the rest of the filename. */
   while (*cp2) {
-      int dot_seen;
-      dot_seen = 0;
+      int dot_seen = 0;
       switch(*cp2) {
       /* Fixme - for compatibility with the CRTL we should be removing */
       /* spaces from the file specifications, but this may show that */
@@ -7323,16 +7181,8 @@ static char *int_tounixspec(const char *spec, char *rslt, int * utf8_fl)
           *(cp1++) = '?';
           break;
       case '^':
-          /* Fix me hex expansions not implemented */
-          cp2++;  /* '^.' --> '.' and other. */
-          if (*cp2) {
-              if (*cp2 == '_') {
-                  cp2++;
-                  *(cp1++) = ' ';
-              } else {
-                  *(cp1++) = *(cp2++);
-              }
-          }
+          cp2 += copy_expand_vms_filename_escape(cp1, cp2, &outchars_added);
+          cp1 += outchars_added;
           break;
       case ';':
           if (decc_filename_unix_no_version) {
@@ -7388,8 +7238,8 @@ static char *int_tounixspec(const char *spec, char *rslt, int * utf8_fl)
    * VMS device root or concealed root.
    */
   {
-  int ulen;
-  char * zeros;
+      int ulen;
+      char * zeros;
 
       ulen = strlen(rslt);
 
@@ -7415,7 +7265,8 @@ static char *int_tounixspec(const char *spec, char *rslt, int * utf8_fl)
 
 
 /*{{{ char *tounixspec[_ts](char *spec, char *buf, int *)*/
-static char *mp_do_tounixspec(pTHX_ const char *spec, char *buf, int ts, int * utf8_fl)
+static char *
+mp_do_tounixspec(pTHX_ const char *spec, char *buf, int ts, int * utf8_fl)
 {
     static char __tounixspec_retbuf[VMS_MAXRSS];
     char * unixspec, *ret_spec, *ret_buf;
@@ -7446,16 +7297,31 @@ static char *mp_do_tounixspec(pTHX_ const char *spec, char *buf, int ts, int * u
 }  /* end of do_tounixspec() */
 /*}}}*/
 /* External entry points */
-char *Perl_tounixspec(pTHX_ const char *spec, char *buf)
-  { return do_tounixspec(spec,buf,0, NULL); }
-char *Perl_tounixspec_ts(pTHX_ const char *spec, char *buf)
-  { return do_tounixspec(spec,buf,1, NULL); }
-char *Perl_tounixspec_utf8(pTHX_ const char *spec, char *buf, int * utf8_fl)
-  { return do_tounixspec(spec,buf,0, utf8_fl); }
-char *Perl_tounixspec_utf8_ts(pTHX_ const char *spec, char *buf, int * utf8_fl)
-  { return do_tounixspec(spec,buf,1, utf8_fl); }
-
-#if __CRTL_VER >= 70200000 && !defined(__VAX)
+char *
+Perl_tounixspec(pTHX_ const char *spec, char *buf)
+{
+    return do_tounixspec(spec, buf, 0, NULL);
+}
+
+char *
+Perl_tounixspec_ts(pTHX_ const char *spec, char *buf)
+{
+    return do_tounixspec(spec,buf,1, NULL);
+}
+
+char *
+Perl_tounixspec_utf8(pTHX_ const char *spec, char *buf, int * utf8_fl)
+{
+    return do_tounixspec(spec,buf,0, utf8_fl);
+}
+
+char *
+Perl_tounixspec_utf8_ts(pTHX_ const char *spec, char *buf, int * utf8_fl)
+{
+    return do_tounixspec(spec,buf,1, utf8_fl);
+}
+
+#if __CRTL_VER >= 70200000 && !defined(__VAX)
 
 /*
  This procedure is used to identify if a path is based in either
@@ -7472,27 +7338,25 @@ char *Perl_tounixspec_utf8_ts(pTHX_ const char *spec, char *buf, int * utf8_fl)
  It is used only internally by posix_to_vmsspec_hardway().
  */
 
-static int posix_root_to_vms
-  (char *vmspath, int vmspath_len,
-   const char *unixpath,
-   const int * utf8_fl)
-{
-int sts;
-struct FAB myfab = cc$rms_fab;
-rms_setup_nam(mynam);
-struct dsc$descriptor_s dvidsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
-struct dsc$descriptor_s specdsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
-char * esa, * esal, * rsa, * rsal;
-char *vms_delim;
-int dir_flag;
-int unixlen;
-
-    dir_flag = 0;
-    vmspath[0] = '\0';
-    unixlen = strlen(unixpath);
-    if (unixlen == 0) {
-      return RMS$_FNF;
-    }
+static int
+posix_root_to_vms(char *vmspath, int vmspath_len,
+                  const char *unixpath, const int * utf8_fl)
+{
+  int sts;
+  struct FAB myfab = cc$rms_fab;
+  rms_setup_nam(mynam);
+  struct dsc$descriptor_s dvidsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
+  struct dsc$descriptor_s specdsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
+  char * esa, * esal, * rsa, * rsal;
+  int dir_flag;
+  int unixlen;
+
+  dir_flag = 0;
+  vmspath[0] = '\0';
+  unixlen = strlen(unixpath);
+  if (unixlen == 0) {
+    return RMS$_FNF;
+  }
 
 #if __CRTL_VER >= 80200000
   /* If not a posix spec already, convert it */
@@ -7503,14 +7367,14 @@ int unixlen;
     else {
       /* This is already a VMS specification, no conversion */
       unixlen--;
-      strncpy(vmspath,unixpath, vmspath_len);
+      my_strlcpy(vmspath, unixpath, vmspath_len + 1);
     }
   }
   else
 #endif
   {     
-  int path_len;
-  int i,j;
+     int path_len;
+     int i,j;
 
      /* Check to see if this is under the POSIX root */
      if (decc_disable_posix_root) {
@@ -7558,13 +7422,13 @@ int unixlen;
   vmspath[vmspath_len] = 0;
   if (unixpath[unixlen - 1] == '/')
   dir_flag = 1;
-  esal = PerlMem_malloc(VMS_MAXRSS);
+  esal = (char *)PerlMem_malloc(VMS_MAXRSS);
   if (esal == NULL) _ckvmssts_noperl(SS$_INSFMEM);
-  esa = PerlMem_malloc(NAM$C_MAXRSS + 1);
+  esa = (char *)PerlMem_malloc(NAM$C_MAXRSS + 1);
   if (esa == NULL) _ckvmssts_noperl(SS$_INSFMEM);
-  rsal = PerlMem_malloc(VMS_MAXRSS);
+  rsal = (char *)PerlMem_malloc(VMS_MAXRSS);
   if (rsal == NULL) _ckvmssts_noperl(SS$_INSFMEM);
-  rsa = PerlMem_malloc(NAM$C_MAXRSS + 1);
+  rsa = (char *)PerlMem_malloc(NAM$C_MAXRSS + 1);
   if (rsa == NULL) _ckvmssts_noperl(SS$_INSFMEM);
   rms_set_fna(myfab, mynam, (char *) vmspath, strlen(vmspath)); /* cast ok */
   rms_bind_fab_nam(myfab, mynam);
@@ -7615,7 +7479,7 @@ int unixlen;
      if (strncmp(unixpath,"\"^UP^",5) != 0)
        sprintf(vmspath,"\"^UP^%s\"",unixpath);
      else
-       strcpy(vmspath, unixpath);
+       my_strlcpy(vmspath, unixpath, vmspath_len + 1);
   }
   else {
     vmspath[specdsc.dsc$w_length] = 0;
@@ -7682,15 +7546,11 @@ int unixlen;
 */
 
 static int 
-slash_dev_special_to_vms
-   (const char * unixptr,
-    char * vmspath,
-    int vmspath_len)
+slash_dev_special_to_vms(const char *unixptr, char *vmspath, int vmspath_len)
 {
-char * nextslash;
-int len;
-int cmp;
-int islnm;
+    char * nextslash;
+    int len;
+    int cmp;
 
     unixptr += 4;
     nextslash = strchr(unixptr, '/');
@@ -7704,6 +7564,7 @@ int islnm;
            return SS$_NORMAL;
        }
     }
+    return 0;
 }
 
 
@@ -7717,25 +7578,24 @@ int islnm;
     through with out interpretation instead of being escaped.
 
   */
-static int posix_to_vmsspec_hardway
-  (char *vmspath, int vmspath_len,
-   const char *unixpath,
-   int dir_flag,
-   int * utf8_fl) {
-
-char *esa;
-const char *unixptr;
-const char *unixend;
-char *vmsptr;
-const char *lastslash;
-const char *lastdot;
-int unixlen;
-int vmslen;
-int dir_start;
-int dir_dot;
-int quoted;
-char * v_spec, * r_spec, * d_spec, * n_spec, * e_spec, * vs_spec;
-int sts, v_len, r_len, d_len, n_len, e_len, vs_len;
+static int
+posix_to_vmsspec_hardway(char *vmspath, int vmspath_len, const char *unixpath,
+                         int dir_flag, int * utf8_fl)
+{
+
+  char *esa;
+  const char *unixptr;
+  const char *unixend;
+  char *vmsptr;
+  const char *lastslash;
+  const char *lastdot;
+  int unixlen;
+  int vmslen;
+  int dir_start;
+  int dir_dot;
+  int quoted;
+  char * v_spec, * r_spec, * d_spec, * n_spec, * e_spec, * vs_spec;
+  int sts, v_len, r_len, d_len, n_len, e_len, vs_len;
 
   if (utf8_fl != NULL)
     *utf8_fl = 0;
@@ -7784,7 +7644,7 @@ int sts, v_len, r_len, d_len, n_len, e_len, vs_len;
       lastslash = unixptr + unixlen;
     }
 
-    /* Watch out for traiing ".." after last slash, still a directory */
+    /* Watch out for trailing ".." after last slash, still a directory */
     if ((lastslash[1] == '.')&&(lastslash[2] == '.')&&(lastslash[3] == '\0')) {
       lastslash = unixptr + unixlen;
     }
@@ -7816,21 +7676,20 @@ int sts, v_len, r_len, d_len, n_len, e_len, vs_len;
        /* Find the next slash */
        nextslash = strchr(unixptr,'/');
 
-       esa = PerlMem_malloc(vmspath_len);
+       esa = (char *)PerlMem_malloc(vmspath_len);
        if (esa == NULL) _ckvmssts_noperl(SS$_INSFMEM);
 
-       trn = PerlMem_malloc(VMS_MAXRSS);
+       trn = (char *)PerlMem_malloc(VMS_MAXRSS);
        if (trn == NULL) _ckvmssts_noperl(SS$_INSFMEM);
 
        if (nextslash != NULL) {
 
            seg_len = nextslash - unixptr;
-           strncpy(esa, unixptr, seg_len);
+           memcpy(esa, unixptr, seg_len);
            esa[seg_len] = 0;
        }
        else {
-           strcpy(esa, unixptr);
-           seg_len = strlen(unixptr);
+           seg_len = my_strlcpy(esa, unixptr, sizeof(esa));
        }
        /* trnlnm(section) */
        islnm = vmstrnenv(esa, trn, 0, fildev, 0);
@@ -7855,7 +7714,6 @@ int sts, v_len, r_len, d_len, n_len, e_len, vs_len;
                   &vs_len);
 
            while (sts == 0) {
-           char * strt;
            int cmp;
 
                /* A logical name must be a directory  or the full
@@ -7874,8 +7732,7 @@ int sts, v_len, r_len, d_len, n_len, e_len, vs_len;
                    if ((unixptr[seg_len] == '/') || (dir_flag != 0)) {
                        /* This must be a directory */
                        if (((n_len + e_len) == 0)&&(seg_len <= vmspath_len)) {
-                           strcpy(vmsptr, esa);
-                           vmslen=strlen(vmsptr);
+                           vmslen = my_strlcpy(vmsptr, esa, vmspath_len - 1);
                            vmsptr[vmslen] = ':';
                            vmslen++;
                            vmsptr[vmslen] = '\0';
@@ -7892,7 +7749,7 @@ int sts, v_len, r_len, d_len, n_len, e_len, vs_len;
 
                /* transfer the volume */
                if (v_len > 0 && ((v_len + vmslen) < vmspath_len)) {
-                   strncpy(vmsptr, v_spec, v_len);
+                   memcpy(vmsptr, v_spec, v_len);
                    vmsptr += v_len;
                    vmsptr[0] = '\0';
                    vmslen += v_len;
@@ -7915,7 +7772,7 @@ int sts, v_len, r_len, d_len, n_len, e_len, vs_len;
                        }
                    }
                    if (r_len > 0) {
-                       strncpy(vmsptr, r_spec, r_len);
+                       memcpy(vmsptr, r_spec, r_len);
                        vmsptr += r_len;
                        vmslen += r_len;
                        vmsptr[0] = '\0';
@@ -7946,7 +7803,7 @@ int sts, v_len, r_len, d_len, n_len, e_len, vs_len;
                            d_spec++;
                            d_len--;
                        }
-                       strncpy(vmsptr, d_spec, d_len);
+                       memcpy(vmsptr, d_spec, d_len);
                            vmsptr += d_len;
                            vmslen += d_len;
                            vmsptr[0] = '\0';
@@ -7988,7 +7845,7 @@ int sts, v_len, r_len, d_len, n_len, e_len, vs_len;
        else {
         if (dotdir_seen) {
           /* Perl wants an empty directory here to tell the difference
-           * between a DCL commmand and a filename
+           * between a DCL command and a filename
            */
          *vmsptr++ = '[';
          *vmsptr++ = ']';
@@ -8029,23 +7886,22 @@ int sts, v_len, r_len, d_len, n_len, e_len, vs_len;
      * here that are a VMS device name or concealed logical name instead.
      * So to make things work, this procedure must be tolerant.
      */
-    esa = PerlMem_malloc(vmspath_len);
+    esa = (char *)PerlMem_malloc(vmspath_len);
     if (esa == NULL) _ckvmssts_noperl(SS$_INSFMEM);
 
     sts = SS$_NORMAL;
     nextslash = strchr(&unixptr[1],'/');
     seg_len = 0;
     if (nextslash != NULL) {
-    int cmp;
+      int cmp;
       seg_len = nextslash - &unixptr[1];
-      strncpy(vmspath, unixptr, seg_len + 1);
-      vmspath[seg_len+1] = 0;
+      my_strlcpy(vmspath, unixptr, seg_len + 2);
       cmp = 1;
       if (seg_len == 3) {
        cmp = strncmp(vmspath, "dev", 4);
        if (cmp == 0) {
            sts = slash_dev_special_to_vms(unixptr, vmspath, vmspath_len);
-           if (sts = SS$_NORMAL)
+           if (sts == SS$_NORMAL)
                return SS$_NORMAL;
        }
       }
@@ -8057,8 +7913,7 @@ int sts, v_len, r_len, d_len, n_len, e_len, vs_len;
 
       sts = posix_root_to_vms(esa, vmspath_len, "/", NULL);
       if ($VMS_STATUS_SUCCESS(sts)) {
-       strcpy(vmspath, esa);
-       vmslen = strlen(vmspath);
+       vmslen = my_strlcpy(vmspath, esa, vmspath_len + 1);
        vmsptr = vmspath + vmslen;
        unixptr++;
        if (unixptr < lastslash) {
@@ -8103,9 +7958,8 @@ int sts, v_len, r_len, d_len, n_len, e_len, vs_len;
        */
 
       /* Posix to VMS destroyed this, so copy it again */
-      strncpy(vmspath, &unixptr[1], seg_len);
-      vmspath[seg_len] = 0;
-      vmslen = seg_len;
+      my_strlcpy(vmspath, &unixptr[1], seg_len + 1);
+      vmslen = strlen(vmspath); /* We know we're truncating. */
       vmsptr = &vmsptr[vmslen];
       islnm = 0;
 
@@ -8196,9 +8050,9 @@ int sts, v_len, r_len, d_len, n_len, e_len, vs_len;
   } /* End of relative/absolute path handling */
 
   while ((unixptr <= unixend) && (vmslen < vmspath_len)){
-  int dash_flag;
-  int in_cnt;
-  int out_cnt;
+    int dash_flag;
+    int in_cnt;
+    int out_cnt;
 
     dash_flag = 0;
 
@@ -8430,10 +8284,11 @@ int sts, v_len, r_len, d_len, n_len, e_len, vs_len;
 #endif
 
  /* Eventual routine to convert a UTF-8 specification to VTF-7. */
-static char * utf8_to_vtf7(char * rslt, const char * path, int *utf8_fl)
+static char *
+utf8_to_vtf7(char * rslt, const char * path, int *utf8_fl)
 {
-char * result;
-int utf8_flag;
+   char * result;
+   int utf8_flag;
 
    /* If a UTF8 flag is being passed, honor it */
    utf8_flag = 0;
@@ -8454,15 +8309,29 @@ int utf8_flag;
    return result;
 }
 
-
+/* A convenience macro for copying dots in filenames and escaping
+ * them when they haven't already been escaped, with guards to
+ * avoid checking before the start of the buffer or advancing
+ * beyond the end of it (allowing room for the NUL terminator).
+ */
+#define VMSEFS_DOT_WITH_ESCAPE(vmsefsdot,vmsefsbuf,vmsefsbufsiz) STMT_START { \
+    if ( ((vmsefsdot) > (vmsefsbuf) && *((vmsefsdot) - 1) != '^' \
+          || ((vmsefsdot) == (vmsefsbuf))) \
+         && (vmsefsdot) < (vmsefsbuf) + (vmsefsbufsiz) - 3 \
+       ) { \
+        *((vmsefsdot)++) = '^'; \
+    } \
+    if ((vmsefsdot) < (vmsefsbuf) + (vmsefsbufsiz) - 2) \
+        *((vmsefsdot)++) = '.'; \
+} STMT_END
 
 /*{{{ char *tovmsspec[_ts](char *path, char *buf, int * utf8_flag)*/
-static char *int_tovmsspec
-   (const char *path, char *rslt, int dir_flag, int * utf8_flag) {
+static char *
+int_tovmsspec(const char *path, char *rslt, int dir_flag, int * utf8_flag)
+{
   char *dirend;
   char *lastdot;
-  char *vms_delim;
-  register char *cp1;
+  char *cp1;
   const char *cp2;
   unsigned long int infront = 0, hasdir = 1;
   int rslt_len;
@@ -8544,7 +8413,7 @@ static char *int_tovmsspec
     if ((v_len != 0) || (r_len != 0) || (d_len != 0) || (vs_len != 0)) {
       if (utf8_flag != NULL)
        *utf8_flag = 0;
-      strcpy(rslt, path);
+      my_strlcpy(rslt, path, VMS_MAXRSS);
       if (vms_debug_fileify) {
           fprintf(stderr, "int_tovmsspec: rslt = %s\n", rslt);
       }
@@ -8565,7 +8434,7 @@ static char *int_tovmsspec
      */
     if (utf8_flag != NULL)
       *utf8_flag = 0;
-    strcpy(rslt, path);
+    my_strlcpy(rslt, path, VMS_MAXRSS);
     if (vms_debug_fileify) {
         fprintf(stderr, "int_tovmsspec: rslt = %s\n", rslt);
     }
@@ -8575,52 +8444,25 @@ static char *int_tovmsspec
   dirend = strrchr(path,'/');
 
   if (dirend == NULL) {
-     char *macro_start;
-     int has_macro;
-
-     /* If we get here with no UNIX directory delimiters, then this is
-        not a complete file specification, either garbage a UNIX glob
-       specification that can not be converted to a VMS wildcard, or
-       it a UNIX shell macro.  MakeMaker wants shell macros passed
-       through AS-IS,
-
-       utf8 flag setting needs to be preserved.
+     /* If we get here with no Unix directory delimiters, then this is an
+      * ambiguous file specification, such as a Unix glob specification, a
+      * shell or make macro, or a filespec that would be valid except for
+      * unescaped extended characters.  The safest thing if it's a macro
+      * is to pass it through as-is.
       */
-      hasdir = 0;
-
-      has_macro = 0;
-      macro_start = strchr(path,'$');
-      if (macro_start != NULL) {
-          if (macro_start[1] == '(') {
-              has_macro = 1;
-          }
-      }
-      if ((decc_efs_charset == 0) || (has_macro)) {
-          strcpy(rslt, path);
+      if (strstr(path, "$(")) {
+          my_strlcpy(rslt, path, VMS_MAXRSS);
           if (vms_debug_fileify) {
               fprintf(stderr, "int_tovmsspec: rslt = %s\n", rslt);
           }
           return rslt;
       }
+      hasdir = 0;
   }
-
-/* If EFS charset mode active, handle the conversion */
-#if __CRTL_VER >= 80200000 && !defined(__VAX)
-  if (decc_efs_charset) {
-    posix_to_vmsspec_hardway(rslt, rslt_len, path, dir_flag, utf8_flag);
-    if (vms_debug_fileify) {
-        fprintf(stderr, "int_tovmsspec: rslt = %s\n", rslt);
-    }
-    return rslt;
-  }
-#endif
-
-  if (*(dirend+1) == '.') {  /* do we have trailing "/." or "/.." or "/..."? */
+  else if (*(dirend+1) == '.') {  /* do we have trailing "/." or "/.." or "/..."? */
     if (!*(dirend+2)) dirend +=2;
     if (*(dirend+2) == '.' && !*(dirend+3)) dirend += 3;
-    if (decc_efs_charset == 0) {
-      if (*(dirend+2) == '.' && *(dirend+3) == '.' && !*(dirend+4)) dirend += 4;
-    }
+    if (*(dirend+2) == '.' && *(dirend+3) == '.' && !*(dirend+4)) dirend += 4;
   }
 
   cp1 = rslt;
@@ -8648,7 +8490,7 @@ static char *int_tovmsspec
     }
     while (*(++cp2) != '/' && *cp2) *(cp1++) = *cp2;
     *cp1 = '\0';
-    trndev = PerlMem_malloc(VMS_MAXRSS);
+    trndev = (char *)PerlMem_malloc(VMS_MAXRSS);
     if (trndev == NULL) _ckvmssts_noperl(SS$_INSFMEM);
     islnm =  simple_trnlnm(rslt,trndev,VMS_MAXRSS-1);
 
@@ -8700,7 +8542,7 @@ static char *int_tovmsspec
     }
     else {
       if (cp2 != dirend) {
-        strcpy(rslt,trndev);
+        my_strlcpy(rslt, trndev, VMS_MAXRSS);
         cp1 = rslt + trnend;
        if (*cp2 != 0) {
           *(cp1++) = '.';
@@ -8716,7 +8558,7 @@ static char *int_tovmsspec
     }
     PerlMem_free(trndev);
   }
-  else {
+  else if (hasdir) {
     *(cp1++) = '[';
     if (*cp2 == '.') {
       if (*(cp2+1) == '/' || *(cp2+1) == '\0') {
@@ -8744,29 +8586,24 @@ static char *int_tovmsspec
   for (; cp2 < dirend; cp2++) {
     if (*cp2 == '/') {
       if (*(cp2-1) == '/') continue;
-      if (*(cp1-1) != '.') *(cp1++) = '.';
+      if (cp1 > rslt && *(cp1-1) != '.') *(cp1++) = '.';
       infront = 0;
     }
     else if (!infront && *cp2 == '.') {
       if (cp2+1 == dirend || *(cp2+1) == '\0') { cp2++; break; }
       else if (*(cp2+1) == '/') cp2++;   /* skip over "./" - it's redundant */
       else if (*(cp2+1) == '.' && (*(cp2+2) == '/' || *(cp2+2) == '\0')) {
-        if (*(cp1-1) == '-' || *(cp1-1) == '[') *(cp1++) = '-'; /* handle "../" */
-        else if (*(cp1-2) == '[') *(cp1-1) = '-';
-        else {  /* back up over previous directory name */
-          cp1--;
-          while (*(cp1-1) != '.' && *(cp1-1) != '[') cp1--;
-          if (*(cp1-1) == '[') {
-            memcpy(cp1,"000000.",7);
-            cp1 += 7;
-          }
+        if (cp1 > rslt && (*(cp1-1) == '-' || *(cp1-1) == '[')) *(cp1++) = '-'; /* handle "../" */
+        else if (cp1 > rslt + 1 && *(cp1-2) == '[') *(cp1-1) = '-';
+        else {
+          *(cp1++) = '-';
         }
         cp2 += 2;
         if (cp2 == dirend) break;
       }
       else if ( *(cp2+1) == '.' && *(cp2+2) == '.' &&
                 (*(cp2+3) == '/' || *(cp2+3) == '\0') ) {
-        if (*(cp1-1) != '.') *(cp1++) = '.'; /* May already have 1 from '/' */
+        if (cp1 > rslt && *(cp1-1) != '.') *(cp1++) = '.'; /* May already have 1 from '/' */
         *(cp1++) = '.'; *(cp1++) = '.'; /* ".../" --> "..." */
         if (!*(cp2+3)) { 
           *(cp1++) = '.';  /* Simulate trailing '/' */
@@ -8775,32 +8612,40 @@ static char *int_tovmsspec
         else cp2 += 3;  /* Trailing '/' was there, so skip it, too */
       }
       else {
-        if (decc_efs_charset == 0)
+        if (decc_efs_charset == 0) {
+         if (cp1 > rslt && *(cp1-1) == '^')
+           cp1--;         /* remove the escape, if any */
          *(cp1++) = '_';  /* fix up syntax - '.' in name not allowed */
+       }
        else {
-         *(cp1++) = '^';  /* fix up syntax - '.' in name is allowed */
-         *(cp1++) = '.';
+         VMSEFS_DOT_WITH_ESCAPE(cp1, rslt, VMS_MAXRSS);
        }
       }
     }
     else {
-      if (!infront && *(cp1-1) == '-')  *(cp1++) = '.';
+      if (!infront && cp1 > rslt && *(cp1-1) == '-')  *(cp1++) = '.';
       if (*cp2 == '.') {
-        if (decc_efs_charset == 0)
+        if (decc_efs_charset == 0) {
+         if (cp1 > rslt && *(cp1-1) == '^')
+           cp1--;         /* remove the escape, if any */
          *(cp1++) = '_';
+       }
        else {
-         *(cp1++) = '^';
-         *(cp1++) = '.';
+         VMSEFS_DOT_WITH_ESCAPE(cp1, rslt, VMS_MAXRSS);
        }
       }
-      else                  *(cp1++) =  *cp2;
+      else {
+        int out_cnt;
+        cp2 += copy_expand_unix_filename_escape(cp1, cp2, &out_cnt, utf8_flag);
+        cp2--; /* we're in a loop that will increment this */
+        cp1 += out_cnt;
+      }
       infront = 1;
     }
   }
-  if (*(cp1-1) == '.') cp1--; /* Unix spec ending in '/' ==> trailing '.' */
+  if (cp1 > rslt && *(cp1-1) == '.') cp1--; /* Unix spec ending in '/' ==> trailing '.' */
   if (hasdir) *(cp1++) = ']';
-  if (*cp2) cp2++;  /* check in case we ended with trailing '..' */
-  /* fixme for ODS5 */
+  if (*cp2 && *cp2 == '/') cp2++;  /* check in case we ended with trailing '/' */
   no_type_seen = 0;
   if (cp2 > lastdot)
     no_type_seen = 1;
@@ -8813,15 +8658,15 @@ static char *int_tovmsspec
          *(cp1++) = '?';
        cp2++;
     case ' ':
-       *(cp1)++ = '^';
+       if (cp2 >= path && (cp2 == path || *(cp2-1) != '^')) /* not previously escaped */
+           *(cp1)++ = '^';
        *(cp1)++ = '_';
        cp2++;
        break;
     case '.':
        if (((cp2 < lastdot) || (cp2[1] == '\0')) &&
            decc_readdir_dropdotnotype) {
-         *(cp1)++ = '^';
-         *(cp1)++ = '.';
+         VMSEFS_DOT_WITH_ESCAPE(cp1, rslt, VMS_MAXRSS);
          cp2++;
 
          /* trailing dot ==> '^..' on VMS */
@@ -8898,20 +8743,23 @@ static char *int_tovmsspec
     case '|':
     case '<':
     case '>':
-       *(cp1++) = '^';
+       if (cp2 >= path && *(cp2-1) != '^') /* not previously escaped */
+           *(cp1++) = '^';
        *(cp1++) = *(cp2++);
        break;
     case ';':
-       /* FIXME: This needs fixing as Perl is putting ".dir;" on UNIX filespecs
-        * which is wrong.  UNIX notation should be ".dir." unless
-        * the DECC$FILENAME_UNIX_NO_VERSION is enabled.
-        * changing this behavior could break more things at this time.
-        * efs character set effectively does not allow "." to be a version
-        * delimiter as a further complication about changing this.
-        */
-       if (decc_filename_unix_report != 0) {
+        /* If it doesn't look like the beginning of a version number,
+         * or we've been promised there are no version numbers, then
+         * escape it.
+         */
+       if (decc_filename_unix_no_version) {
          *(cp1++) = '^';
        }
+       else {
+         size_t all_nums = strspn(cp2+1, "0123456789");
+         if (all_nums > 5 || *(cp2 + all_nums + 1) != '\0')
+           *(cp1++) = '^';
+       }
        *(cp1++) = *(cp2++);
        break;
     default:
@@ -8941,9 +8789,10 @@ static char *int_tovmsspec
 
 
 /*{{{ char *tovmsspec[_ts](char *path, char *buf, int * utf8_flag)*/
-static char *mp_do_tovmsspec
-   (pTHX_ const char *path, char *buf, int ts, int dir_flag, int * utf8_flag) {
-  static char __tovmsspec_retbuf[VMS_MAXRSS];
+static char *
+mp_do_tovmsspec(pTHX_ const char *path, char *buf, int ts, int dir_flag, int * utf8_flag)
+{
+    static char __tovmsspec_retbuf[VMS_MAXRSS];
     char * vmsspec, *ret_spec, *ret_buf;
 
     vmsspec = NULL;
@@ -8972,25 +8821,41 @@ static char *mp_do_tovmsspec
 }  /* end of mp_do_tovmsspec() */
 /*}}}*/
 /* External entry points */
-char *Perl_tovmsspec(pTHX_ const char *path, char *buf)
-  { return do_tovmsspec(path,buf,0,NULL); }
-char *Perl_tovmsspec_ts(pTHX_ const char *path, char *buf)
-  { return do_tovmsspec(path,buf,1,NULL); }
-char *Perl_tovmsspec_utf8(pTHX_ const char *path, char *buf, int * utf8_fl)
-  { return do_tovmsspec(path,buf,0,utf8_fl); }
-char *Perl_tovmsspec_utf8_ts(pTHX_ const char *path, char *buf, int * utf8_fl)
-  { return do_tovmsspec(path,buf,1,utf8_fl); }
+char *
+Perl_tovmsspec(pTHX_ const char *path, char *buf)
+{
+    return do_tovmsspec(path, buf, 0, NULL);
+}
 
-/*{{{ char *int_tovmspath(char *path, char *buf, const int *)*/
-/* Internal routine for use with out an explict context present */
-static char * int_tovmspath(const char *path, char *buf, int * utf8_fl) {
+char *
+Perl_tovmsspec_ts(pTHX_ const char *path, char *buf)
+{
+    return do_tovmsspec(path, buf, 1, NULL);
+}
 
+char *
+Perl_tovmsspec_utf8(pTHX_ const char *path, char *buf, int * utf8_fl)
+{
+    return do_tovmsspec(path, buf, 0, utf8_fl);
+}
+
+char *
+Perl_tovmsspec_utf8_ts(pTHX_ const char *path, char *buf, int * utf8_fl)
+{
+    return do_tovmsspec(path, buf, 1, utf8_fl);
+}
+
+/*{{{ char *int_tovmspath(char *path, char *buf, const int *)*/
+/* Internal routine for use with out an explicit context present */
+static char *
+int_tovmspath(const char *path, char *buf, int * utf8_fl)
+{
     char * ret_spec, *pathified;
 
     if (path == NULL)
         return NULL;
 
-    pathified = PerlMem_malloc(VMS_MAXRSS);
+    pathified = (char *)PerlMem_malloc(VMS_MAXRSS);
     if (pathified == NULL)
         _ckvmssts_noperl(SS$_INSFMEM);
 
@@ -9009,13 +8874,15 @@ static char * int_tovmspath(const char *path, char *buf, int * utf8_fl) {
 }
 
 /*{{{ char *tovmspath[_ts](char *path, char *buf, const int *)*/
-static char *mp_do_tovmspath(pTHX_ const char *path, char *buf, int ts, int * utf8_fl) {
+static char *
+mp_do_tovmspath(pTHX_ const char *path, char *buf, int ts, int * utf8_fl)
+{
   static char __tovmspath_retbuf[VMS_MAXRSS];
   int vmslen;
   char *pathified, *vmsified, *cp;
 
   if (path == NULL) return NULL;
-  pathified = PerlMem_malloc(VMS_MAXRSS);
+  pathified = (char *)PerlMem_malloc(VMS_MAXRSS);
   if (pathified == NULL) _ckvmssts(SS$_INSFMEM);
   if (int_pathify_dirspec(path, pathified) == NULL) {
     PerlMem_free(pathified);
@@ -9043,7 +8910,7 @@ static char *mp_do_tovmspath(pTHX_ const char *path, char *buf, int ts, int * ut
     return cp;
   }
   else {
-    strcpy(__tovmspath_retbuf,vmsified);
+    my_strlcpy(__tovmspath_retbuf, vmsified, sizeof(__tovmspath_retbuf));
     Safefree(vmsified);
     return __tovmspath_retbuf;
   }
@@ -9051,24 +8918,41 @@ static char *mp_do_tovmspath(pTHX_ const char *path, char *buf, int ts, int * ut
 }  /* end of do_tovmspath() */
 /*}}}*/
 /* External entry points */
-char *Perl_tovmspath(pTHX_ const char *path, char *buf)
-  { return do_tovmspath(path,buf,0, NULL); }
-char *Perl_tovmspath_ts(pTHX_ const char *path, char *buf)
-  { return do_tovmspath(path,buf,1, NULL); }
-char *Perl_tovmspath_utf8(pTHX_ const char *path, char *buf, int *utf8_fl) 
-  { return do_tovmspath(path,buf,0,utf8_fl); }
-char *Perl_tovmspath_utf8_ts(pTHX_ const char *path, char *buf, int *utf8_fl)
-  { return do_tovmspath(path,buf,1,utf8_fl); }
+char *
+Perl_tovmspath(pTHX_ const char *path, char *buf)
+{
+    return do_tovmspath(path, buf, 0, NULL);
+}
+
+char *
+Perl_tovmspath_ts(pTHX_ const char *path, char *buf)
+{
+    return do_tovmspath(path, buf, 1, NULL);
+}
+
+char *
+Perl_tovmspath_utf8(pTHX_ const char *path, char *buf, int *utf8_fl)
+{
+    return do_tovmspath(path, buf, 0, utf8_fl);
+}
+
+char *
+Perl_tovmspath_utf8_ts(pTHX_ const char *path, char *buf, int *utf8_fl)
+{
+    return do_tovmspath(path, buf, 1, utf8_fl);
+}
 
 
 /*{{{ char *tounixpath[_ts](char *path, char *buf, int * utf8_fl)*/
-static char *mp_do_tounixpath(pTHX_ const char *path, char *buf, int ts, int * utf8_fl) {
+static char *
+mp_do_tounixpath(pTHX_ const char *path, char *buf, int ts, int * utf8_fl)
+{
   static char __tounixpath_retbuf[VMS_MAXRSS];
   int unixlen;
   char *pathified, *unixified, *cp;
 
   if (path == NULL) return NULL;
-  pathified = PerlMem_malloc(VMS_MAXRSS);
+  pathified = (char *)PerlMem_malloc(VMS_MAXRSS);
   if (pathified == NULL) _ckvmssts(SS$_INSFMEM);
   if (int_pathify_dirspec(path, pathified) == NULL) {
     PerlMem_free(pathified);
@@ -9097,7 +8981,7 @@ static char *mp_do_tounixpath(pTHX_ const char *path, char *buf, int ts, int * u
     return cp;
   }
   else {
-    strcpy(__tounixpath_retbuf,unixified);
+    my_strlcpy(__tounixpath_retbuf, unixified, sizeof(__tounixpath_retbuf));
     Safefree(unixified);
     return __tounixpath_retbuf;
   }
@@ -9105,14 +8989,29 @@ static char *mp_do_tounixpath(pTHX_ const char *path, char *buf, int ts, int * u
 }  /* end of do_tounixpath() */
 /*}}}*/
 /* External entry points */
-char *Perl_tounixpath(pTHX_ const char *path, char *buf)
-  { return do_tounixpath(path,buf,0,NULL); }
-char *Perl_tounixpath_ts(pTHX_ const char *path, char *buf)
-  { return do_tounixpath(path,buf,1,NULL); }
-char *Perl_tounixpath_utf8(pTHX_ const char *path, char *buf, int * utf8_fl)
-  { return do_tounixpath(path,buf,0,utf8_fl); }
-char *Perl_tounixpath_utf8_ts(pTHX_ const char *path, char *buf, int * utf8_fl)
-  { return do_tounixpath(path,buf,1,utf8_fl); }
+char *
+Perl_tounixpath(pTHX_ const char *path, char *buf)
+{
+    return do_tounixpath(path, buf, 0, NULL);
+}
+
+char *
+Perl_tounixpath_ts(pTHX_ const char *path, char *buf)
+{
+    return do_tounixpath(path, buf, 1, NULL);
+}
+
+char *
+Perl_tounixpath_utf8(pTHX_ const char *path, char *buf, int * utf8_fl)
+{
+    return do_tounixpath(path, buf, 0, utf8_fl);
+}
+
+char *
+Perl_tounixpath_utf8_ts(pTHX_ const char *path, char *buf, int * utf8_fl)
+{
+    return do_tounixpath(path, buf, 1, utf8_fl);
+}
 
 /*
  * @(#)argproc.c 2.2 94/08/16  Mark Pizzolato (mark AT infocomm DOT com)
@@ -9373,12 +9272,12 @@ mp_getredirection(pTHX_ int *ac, char ***av)
        fprintf(stderr,"Can't open output file %s as stdout",out);
        exit(vaxc$errno);
        }
-       if (out != NULL) Perl_vmssetuserlnm(aTHX_ "SYS$OUTPUT",out);
+       if (out != NULL) vmssetuserlnm("SYS$OUTPUT", out);
 
     if (err != NULL) {
         if (strcmp(err,"&1") == 0) {
             dup2(fileno(stdout), fileno(stderr));
-            Perl_vmssetuserlnm(aTHX_ "SYS$ERROR","SYS$OUTPUT");
+            vmssetuserlnm("SYS$ERROR", "SYS$OUTPUT");
         } else {
        FILE *tmperr;
        if (NULL == (tmperr = fopen(err, errmode, "mbc=32", "mbf=2")))
@@ -9391,7 +9290,7 @@ mp_getredirection(pTHX_ int *ac, char ***av)
                {
                exit(vaxc$errno);
                }
-           Perl_vmssetuserlnm(aTHX_ "SYS$ERROR",err);
+           vmssetuserlnm("SYS$ERROR", err);
        }
         }
 #ifdef ARGPROC_DEBUG
@@ -9405,10 +9304,8 @@ mp_getredirection(pTHX_ int *ac, char ***av)
 }  /* end of getredirection() */
 /*}}}*/
 
-static void add_item(struct list_item **head,
-                    struct list_item **tail,
-                    char *value,
-                    int *count)
+static void
+add_item(struct list_item **head, struct list_item **tail, char *value, int *count)
 {
     if (*head == 0)
        {
@@ -9425,26 +9322,25 @@ static void add_item(struct list_item **head,
     ++(*count);
 }
 
-static void mp_expand_wild_cards(pTHX_ char *item,
-                             struct list_item **head,
-                             struct list_item **tail,
-                             int *count)
-{
-int expcount = 0;
-unsigned long int context = 0;
-int isunix = 0;
-int item_len = 0;
-char *had_version;
-char *had_device;
-int had_directory;
-char *devdir,*cp;
-char *vmsspec;
-$DESCRIPTOR(filespec, "");
-$DESCRIPTOR(defaultspec, "SYS$DISK:[]");
-$DESCRIPTOR(resultspec, "");
-unsigned long int lff_flags = 0;
-int sts;
-int rms_sts;
+static void 
+mp_expand_wild_cards(pTHX_ char *item, struct list_item **head,
+                     struct list_item **tail, int *count)
+{
+    int expcount = 0;
+    unsigned long int context = 0;
+    int isunix = 0;
+    int item_len = 0;
+    char *had_version;
+    char *had_device;
+    int had_directory;
+    char *devdir,*cp;
+    char *vmsspec;
+    $DESCRIPTOR(filespec, "");
+    $DESCRIPTOR(defaultspec, "SYS$DISK:[]");
+    $DESCRIPTOR(resultspec, "");
+    unsigned long int lff_flags = 0;
+    int sts;
+    int rms_sts;
 
 #ifdef VMS_LONGNAME_SUPPORT
     lff_flags = LIB$M_FIL_LONG_NAMES;
@@ -9476,7 +9372,7 @@ int rms_sts;
     resultspec.dsc$b_dtype = DSC$K_DTYPE_T;
     resultspec.dsc$b_class = DSC$K_CLASS_D;
     resultspec.dsc$a_pointer = NULL;
-    vmsspec = PerlMem_malloc(VMS_MAXRSS);
+    vmsspec = (char *)PerlMem_malloc(VMS_MAXRSS);
     if (vmsspec == NULL) _ckvmssts_noperl(SS$_INSFMEM);
     if ((isunix = (int) strchr(item,'/')) != (int) NULL)
       filespec.dsc$a_pointer = int_tovmsspec(item, vmsspec, 0, NULL);
@@ -9488,7 +9384,7 @@ int rms_sts;
      */
     had_version = strchr(item, ';');
     /*
-     * Only return device and directory specs, if the caller specifed either.
+     * Only return device and directory specs, if the caller specified either.
      */
     had_device = strchr(item, ':');
     had_directory = (isunix || NULL != strchr(item, '[')) || (NULL != strchr(item, '<'));
@@ -9500,17 +9396,16 @@ int rms_sts;
        char *string;
        char *c;
 
-       string = PerlMem_malloc(resultspec.dsc$w_length+1);
+       string = (char *)PerlMem_malloc(resultspec.dsc$w_length+1);
         if (string == NULL) _ckvmssts_noperl(SS$_INSFMEM);
-       strncpy(string, resultspec.dsc$a_pointer, resultspec.dsc$w_length);
-       string[resultspec.dsc$w_length] = '\0';
+       my_strlcpy(string, resultspec.dsc$a_pointer, resultspec.dsc$w_length+1);
        if (NULL == had_version)
            *(strrchr(string, ';')) = '\0';
        if ((!had_directory) && (had_device == NULL))
            {
            if (NULL == (devdir = strrchr(string, ']')))
                devdir = strrchr(string, '>');
-           strcpy(string, devdir + 1);
+           my_strlcpy(string, devdir + 1, resultspec.dsc$w_length+1);
            }
        /*
         * Be consistent with what the C RTL has already done to the rest of
@@ -9551,46 +9446,6 @@ int rms_sts;
     _ckvmssts_noperl(lib$find_file_end(&context));
 }
 
-static int child_st[2];/* Event Flag set when child process completes  */
-
-static unsigned short child_chan;/* I/O Channel for Pipe Mailbox               */
-
-static unsigned long int exit_handler(int *status)
-{
-short iosb[4];
-
-    if (0 == child_st[0])
-       {
-#ifdef ARGPROC_DEBUG
-       PerlIO_printf(Perl_debug_log, "Waiting for Child Process to Finish . . .\n");
-#endif
-       fflush(stdout);     /* Have to flush pipe for binary data to    */
-                           /* terminate properly -- <tp@mccall.com>    */
-       sys$qiow(0, child_chan, IO$_WRITEOF, iosb, 0, 0, 0, 0, 0, 0, 0, 0);
-       sys$dassgn(child_chan);
-       fclose(stdout);
-       sys$synch(0, child_st);
-       }
-    return(1);
-}
-
-static void sig_child(int chan)
-{
-#ifdef ARGPROC_DEBUG
-    PerlIO_printf(Perl_debug_log, "Child Completion AST\n");
-#endif
-    if (child_st[0] == 0)
-       child_st[0] = 1;
-}
-
-static struct exit_control_block exit_block =
-    {
-    0,
-    exit_handler,
-    1,
-    &exit_block.exit_status,
-    0
-    };
 
 static void 
 pipe_and_fork(pTHX_ char **cmargv)
@@ -9643,27 +9498,26 @@ pipe_and_fork(pTHX_ char **cmargv)
     }
 }
 
-static int background_process(pTHX_ int argc, char **argv)
-{
-char command[MAX_DCL_SYMBOL + 1] = "$";
-$DESCRIPTOR(value, "");
-static $DESCRIPTOR(cmd, "BACKGROUND$COMMAND");
-static $DESCRIPTOR(null, "NLA0:");
-static $DESCRIPTOR(pidsymbol, "SHELL_BACKGROUND_PID");
-char pidstring[80];
-$DESCRIPTOR(pidstr, "");
-int pid;
-unsigned long int flags = 17, one = 1, retsts;
-int len;
-
-    strcat(command, argv[0]);
-    len = strlen(command);
+static int
+background_process(pTHX_ int argc, char **argv)
+{
+    char command[MAX_DCL_SYMBOL + 1] = "$";
+    $DESCRIPTOR(value, "");
+    static $DESCRIPTOR(cmd, "BACKGROUND$COMMAND");
+    static $DESCRIPTOR(null, "NLA0:");
+    static $DESCRIPTOR(pidsymbol, "SHELL_BACKGROUND_PID");
+    char pidstring[80];
+    $DESCRIPTOR(pidstr, "");
+    int pid;
+    unsigned long int flags = 17, one = 1, retsts;
+    int len;
+
+    len = my_strlcat(command, argv[0], sizeof(command));
     while (--argc && (len < MAX_DCL_SYMBOL))
        {
-       strcat(command, " \"");
-       strcat(command, *(++argv));
-       strcat(command, "\"");
-       len = strlen(command);
+       my_strlcat(command, " \"", sizeof(command));
+       my_strlcat(command, *(++argv), sizeof(command));
+       len = my_strlcat(command, "\"", sizeof(command));
        }
     value.dsc$a_pointer = command;
     value.dsc$w_length = strlen(value.dsc$a_pointer);
@@ -9788,7 +9642,7 @@ vms_image_init(int *argcp, char ***argvp)
       _ckvmssts_noperl(sys$getjpiw(0,NULL,NULL,&jpilist[1],iosb,NULL,NULL));
       _ckvmssts_noperl(iosb[0]);
     }
-    mask = jpilist[1].bufadr;
+    mask = (unsigned long int *)jpilist[1].bufadr;
     /* Check attribute flags for each identifier (2nd longword); protected
      * subsystem identifiers trigger tainting.
      */
@@ -9806,8 +9660,8 @@ vms_image_init(int *argcp, char ***argvp)
    * directory.  This needs to be removed.
    */
   if (decc_filename_unix_report) {
-  char * zeros;
-  int ulen;
+    char * zeros;
+    int ulen;
     ulen = strlen(argvp[0][0]);
     if (ulen > 7) {
       zeros = strstr(argvp[0][0], "/000000/");
@@ -9837,7 +9691,7 @@ vms_image_init(int *argcp, char ***argvp)
     newargv = (char **) PerlMem_malloc(((*argcp)+2) * sizeof(char *));
     if (newargv == NULL) _ckvmssts_noperl(SS$_INSFMEM);
     newargv[0] = oldargv[0];
-    newargv[1] = PerlMem_malloc(3 * sizeof(char));
+    newargv[1] = (char *)PerlMem_malloc(3 * sizeof(char));
     if (newargv[1] == NULL) _ckvmssts_noperl(SS$_INSFMEM);
     strcpy(newargv[1], "-T");
     Copy(&oldargv[1],&newargv[2],(*argcp)-1,char **);
@@ -9877,11 +9731,12 @@ vms_image_init(int *argcp, char ***argvp)
     }
     tabvec[tabidx] = (struct dsc$descriptor_s *) PerlMem_malloc(sizeof(struct dsc$descriptor_s));
     if (tabvec[tabidx] == NULL) _ckvmssts_noperl(SS$_INSFMEM);
-    tabvec[tabidx]->dsc$w_length  = 0;
+    tabvec[tabidx]->dsc$w_length  = len;
     tabvec[tabidx]->dsc$b_dtype   = DSC$K_DTYPE_T;
-    tabvec[tabidx]->dsc$b_class   = DSC$K_CLASS_D;
-    tabvec[tabidx]->dsc$a_pointer = NULL;
-    _ckvmssts_noperl(lib$scopy_r_dx(&len,eqv,tabvec[tabidx]));
+    tabvec[tabidx]->dsc$b_class   = DSC$K_CLASS_S;
+    tabvec[tabidx]->dsc$a_pointer = (char *)PerlMem_malloc(len + 1);
+    if (tabvec[tabidx]->dsc$a_pointer == NULL) _ckvmssts_noperl(SS$_INSFMEM);
+    my_strlcpy(tabvec[tabidx]->dsc$a_pointer, eqv, len + 1);
   }
   if (tabidx) { tabvec[tabidx] = NULL; env_tables = tabvec; }
 
@@ -9916,15 +9771,14 @@ vms_image_init(int *argcp, char ***argvp)
 int
 Perl_trim_unixpath(pTHX_ char *fspec, const char *wildspec, int opts)
 {
-  char *unixified, *unixwild,
-       *template, *base, *end, *cp1, *cp2;
-  register int tmplen, reslen = 0, dirs = 0;
+  char *unixified, *unixwild, *tplate, *base, *end, *cp1, *cp2;
+  int tmplen, reslen = 0, dirs = 0;
 
   if (!wildspec || !fspec) return 0;
 
-  unixwild = PerlMem_malloc(VMS_MAXRSS);
+  unixwild = (char *)PerlMem_malloc(VMS_MAXRSS);
   if (unixwild == NULL) _ckvmssts_noperl(SS$_INSFMEM);
-  template = unixwild;
+  tplate = unixwild;
   if (strpbrk(wildspec,"]>:") != NULL) {
     if (int_tounixspec(wildspec, unixwild, NULL) == NULL) {
         PerlMem_free(unixwild);
@@ -9932,10 +9786,9 @@ Perl_trim_unixpath(pTHX_ char *fspec, const char *wildspec, int opts)
     }
   }
   else {
-    strncpy(unixwild, wildspec, VMS_MAXRSS-1);
-    unixwild[VMS_MAXRSS-1] = 0;
+    my_strlcpy(unixwild, wildspec, VMS_MAXRSS);
   }
-  unixified = PerlMem_malloc(VMS_MAXRSS);
+  unixified = (char *)PerlMem_malloc(VMS_MAXRSS);
   if (unixified == NULL) _ckvmssts_noperl(SS$_INSFMEM);
   if (strpbrk(fspec,"]>:") != NULL) {
     if (int_tounixspec(fspec, unixified, NULL) == NULL) {
@@ -9951,7 +9804,7 @@ Perl_trim_unixpath(pTHX_ char *fspec, const char *wildspec, int opts)
   else base = fspec;
 
   /* No prefix or absolute path on wildcard, so nothing to remove */
-  if (!*template || *template == '/') {
+  if (!*tplate || *tplate == '/') {
     PerlMem_free(unixwild);
     if (base == fspec) {
         PerlMem_free(unixified);
@@ -9969,8 +9822,8 @@ Perl_trim_unixpath(pTHX_ char *fspec, const char *wildspec, int opts)
   }
 
   for (end = base; *end; end++) ;  /* Find end of resultant filespec */
-  if ((cp1 = strstr(template,".../")) == NULL) { /* No ...; just count elts */
-    for (cp1 = template; *cp1; cp1++) if (*cp1 == '/') dirs++;
+  if ((cp1 = strstr(tplate,".../")) == NULL) { /* No ...; just count elts */
+    for (cp1 = tplate; *cp1; cp1++) if (*cp1 == '/') dirs++;
     for (cp1 = end ;cp1 >= base; cp1--)
       if ((*cp1 == '/') && !dirs--) /* postdec so we get front of rel path */
         { cp1++; break; }
@@ -9989,9 +9842,9 @@ Perl_trim_unixpath(pTHX_ char *fspec, const char *wildspec, int opts)
     while ((cp1 = strstr(ellipsis+4,".../")) != NULL) {ellipsis = cp1; ells++;}
     totells = ells;
     for (cp1 = ellipsis+4; *cp1; cp1++) if (*cp1 == '/') dirs++;
-    tpl = PerlMem_malloc(VMS_MAXRSS);
+    tpl = (char *)PerlMem_malloc(VMS_MAXRSS);
     if (tpl == NULL) _ckvmssts_noperl(SS$_INSFMEM);
-    if (ellipsis == template && opts & 1) {
+    if (ellipsis == tplate && 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
        * arbitrary starting point, we arbitrarily choose the current
@@ -10025,9 +9878,9 @@ Perl_trim_unixpath(pTHX_ char *fspec, const char *wildspec, int opts)
       for (front = end ; front >= base; front--)
          if (*front == '/' && !dirs--) { front++; break; }
     }
-    lcres = PerlMem_malloc(VMS_MAXRSS);
+    lcres = (char *)PerlMem_malloc(VMS_MAXRSS);
     if (lcres == NULL) _ckvmssts_noperl(SS$_INSFMEM);
-    for (cp1=template,cp2=lcres; *cp1 && cp2 <= lcres + (VMS_MAXRSS - 1);
+    for (cp1=tplate,cp2=lcres; *cp1 && cp2 <= lcres + (VMS_MAXRSS - 1);
          cp1++,cp2++) {
            if (!decc_efs_case_preserve) {
                *cp2 = _tolower(*cp1);  /* Make lc copy for match */
@@ -10048,10 +9901,10 @@ Perl_trim_unixpath(pTHX_ char *fspec, const char *wildspec, int opts)
     lcfront = lcres + (front - base);
     /* Now skip over each ellipsis and try to match the path in front of it. */
     while (ells--) {
-      for (cp1 = ellipsis - 2; cp1 >= template; cp1--)
+      for (cp1 = ellipsis - 2; cp1 >= tplate; cp1--)
         if (*(cp1)   == '.' && *(cp1+1) == '.' &&
             *(cp1+2) == '.' && *(cp1+3) == '/'    ) break;
-      if (cp1 < template) break; /* template started with an ellipsis */
+      if (cp1 < tplate) break; /* template started with an ellipsis */
       if (cp1 + 4 == ellipsis) { /* Consecutive ellipses */
         ellipsis = cp1; continue;
       }
@@ -10138,7 +9991,6 @@ Perl_trim_unixpath(pTHX_ char *fspec, const char *wildspec, int opts)
     PerlMem_free(unixwild);
     PerlMem_free(lcres);
     return 1;
-    ellipsis = nextell;
   }
 
 }  /* end of trim_unixpath() */
@@ -10187,7 +10039,8 @@ Perl_opendir(pTHX_ const char *name)
     /* Check access before stat; otherwise stat does not
      * accurately report whether it's a directory.
      */
-    if (!cando_by_name_int(S_IRUSR,0,dir,PERL_RMSEXPAND_M_VMS_IN)) {
+    if (!strstr(dir, "::") /* sys$check_access doesn't do remotes */
+        && !cando_by_name_int(S_IRUSR,0,dir,PERL_RMSEXPAND_M_VMS_IN)) {
       /* cando_by_name has already set errno */
       Safefree(dir);
       return NULL;
@@ -10208,12 +10061,12 @@ Perl_opendir(pTHX_ const char *name)
     dd->context = 0;
     dd->count = 0;
     dd->flags = 0;
-    /* By saying we always want the result of readdir() in unix format, we 
-     * are really saying we want all the escapes removed.  Otherwise the caller,
-     * having no way to know whether it's already in VMS format, might send it
-     * through tovmsspec again, thus double escaping.
+    /* By saying we want the result of readdir() in unix format, we are really
+     * saying we want all the escapes removed, translating characters that
+     * must be escaped in a VMS-format name to their unescaped form, which is
+     * presumably allowed in a Unix-format name.
      */
-    dd->flags = PERL_VMSDIR_M_UNIXSPECS;
+    dd->flags = decc_filename_unix_report ? PERL_VMSDIR_M_UNIXSPECS : 0;
     dd->pat.dsc$a_pointer = dd->pattern;
     dd->pat.dsc$w_length = strlen(dd->pattern);
     dd->pat.dsc$b_dtype = DSC$K_DTYPE_T;
@@ -10281,7 +10134,7 @@ collectversions(pTHX_ DIR *dd)
     /* Add the version wildcard, ignoring the "*.*" put on before */
     i = strlen(dd->pattern);
     Newx(text,i + e->d_namlen + 3,char);
-    strcpy(text, dd->pattern);
+    my_strlcpy(text, dd->pattern, i + 1);
     sprintf(&text[i - 3], "%s;*", e->d_name);
 
     /* Set up the pattern descriptor. */
@@ -10351,20 +10204,23 @@ Perl_readdir(pTHX_ DIR *dd)
 
     tmpsts = lib$find_file
        (&dd->pat, &res, &dd->context, NULL, NULL, &rsts, &flags);
-    if ( tmpsts == RMS$_NMF || dd->context == 0) return NULL;  /* None left. */
+    if (dd->context == 0)
+        tmpsts = RMS$_NMF;  /* None left. (should be set, but make sure) */
+
     if (!(tmpsts & 1)) {
-      set_vaxc_errno(tmpsts);
       switch (tmpsts) {
+        case RMS$_NMF:
+          break;  /* no more files considered success */
         case RMS$_PRV:
-          set_errno(EACCES); break;
+          SETERRNO(EACCES, tmpsts); break;
         case RMS$_DEV:
-          set_errno(ENODEV); break;
+          SETERRNO(ENODEV, tmpsts); break;
         case RMS$_DIR:
-          set_errno(ENOTDIR); break;
+          SETERRNO(ENOTDIR, tmpsts); break;
         case RMS$_FNF: case RMS$_DNF:
-          set_errno(ENOENT); break;
+          SETERRNO(ENOENT, tmpsts); break;
         default:
-          set_errno(EVMSERR);
+          SETERRNO(EVMSERR, tmpsts);
       }
       Safefree(buff);
       return NULL;
@@ -10399,7 +10255,7 @@ Perl_readdir(pTHX_ DIR *dd)
 
         /* In Unix report mode, remove the ".dir;1" from the name */
         /* if it is a real directory. */
-        if (decc_filename_unix_report || decc_efs_charset) {
+        if (decc_filename_unix_report && decc_efs_charset) {
             if (is_dir_ext(e_spec, e_len, vs_spec, vs_len)) {
                 Stat_t statbuf;
                 int ret_sts;
@@ -10419,9 +10275,9 @@ Perl_readdir(pTHX_ DIR *dd)
         }
     }
 
-    strncpy(dd->entry.d_name, n_spec, n_len + e_len);
+    memcpy(dd->entry.d_name, n_spec, n_len + e_len);
     dd->entry.d_name[n_len + e_len] = '\0';
-    dd->entry.d_namlen = strlen(dd->entry.d_name);
+    dd->entry.d_namlen = n_len + e_len;
 
     /* Convert the filename to UNIX format if needed */
     if (dd->flags & PERL_VMSDIR_M_UNIXSPECS) {
@@ -10444,8 +10300,7 @@ Perl_readdir(pTHX_ DIR *dd)
                /* counted strings apparently with a Unicode flag */
            }
            *q = 0;
-           strcpy(dd->entry.d_name, new_name);
-           dd->entry.d_namlen = strlen(dd->entry.d_name);
+           dd->entry.d_namlen = my_strlcpy(dd->entry.d_name, new_name, sizeof(dd->entry.d_name));
        }
     }
 
@@ -10550,9 +10405,9 @@ Perl_seekdir(pTHX_ DIR *dd, long count)
 
 static int vfork_called;
 
-/*{{{int my_vfork()*/
+/*{{{int my_vfork(void)*/
 int
-my_vfork()
+my_vfork(void)
 {
   vfork_called++;
   return vfork();
@@ -10575,9 +10430,9 @@ static char *
 setup_argstr(pTHX_ SV *really, SV **mark, SV **sp)
 {
   char *junk, *tmps = NULL;
-  register size_t cmdlen = 0;
+  size_t cmdlen = 0;
   size_t rlen;
-  register SV **idx;
+  SV **idx;
   STRLEN n_a;
 
   idx = mark;
@@ -10598,7 +10453,7 @@ setup_argstr(pTHX_ SV *really, SV **mark, SV **sp)
   Newx(PL_Cmd, cmdlen+1, char);
 
   if (tmps && *tmps) {
-    strcpy(PL_Cmd,tmps);
+    my_strlcpy(PL_Cmd, tmps, cmdlen + 1);
     mark++;
   }
   else *PL_Cmd = '\0';
@@ -10606,8 +10461,8 @@ setup_argstr(pTHX_ SV *really, SV **mark, SV **sp)
     if (*mark) {
       char *s = SvPVx(*mark,n_a);
       if (!*s) continue;
-      if (*PL_Cmd) strcat(PL_Cmd," ");
-      strcat(PL_Cmd,s);
+      if (*PL_Cmd) my_strlcat(PL_Cmd, " ", cmdlen+1);
+      my_strlcat(PL_Cmd, s, cmdlen+1);
     }
   }
   return PL_Cmd;
@@ -10629,29 +10484,28 @@ setup_cmddsc(pTHX_ const char *incmd, int check_img, int *suggest_quote,
   struct dsc$descriptor_s *vmscmd;
   struct dsc$descriptor_s imgdsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
   unsigned long int cxt = 0, flags = 1, retsts = SS$_NORMAL;
-  register char *s, *rest, *cp, *wordbreak;
+  char *s, *rest, *cp, *wordbreak;
   char * cmd;
   int cmdlen;
-  register int isdcl;
+  int isdcl;
 
-  vmscmd = PerlMem_malloc(sizeof(struct dsc$descriptor_s));
+  vmscmd = (struct dsc$descriptor_s *)PerlMem_malloc(sizeof(struct dsc$descriptor_s));
   if (vmscmd == NULL) _ckvmssts_noperl(SS$_INSFMEM);
 
   /* vmsspec is a DCL command buffer, not just a filename */
-  vmsspec = PerlMem_malloc(MAX_DCL_LINE_LENGTH + 1);
+  vmsspec = (char *)PerlMem_malloc(MAX_DCL_LINE_LENGTH + 1);
   if (vmsspec == NULL)
       _ckvmssts_noperl(SS$_INSFMEM);
 
-  resspec = PerlMem_malloc(VMS_MAXRSS);
+  resspec = (char *)PerlMem_malloc(VMS_MAXRSS);
   if (resspec == NULL)
       _ckvmssts_noperl(SS$_INSFMEM);
 
   /* Make a copy for modification */
   cmdlen = strlen(incmd);
-  cmd = PerlMem_malloc(cmdlen+1);
+  cmd = (char *)PerlMem_malloc(cmdlen+1);
   if (cmd == NULL) _ckvmssts_noperl(SS$_INSFMEM);
-  strncpy(cmd, incmd, cmdlen);
-  cmd[cmdlen] = 0;
+  my_strlcpy(cmd, incmd, cmdlen + 1);
   image_name[0] = 0;
   image_argv[0] = 0;
 
@@ -10684,6 +10538,68 @@ setup_cmddsc(pTHX_ const char *incmd, int check_img, int *suggest_quote,
     for (cp = &vmsspec[1]; *rest && isspace(*rest); rest++,cp++) *cp = *rest;
   }
   else { cp = vmsspec; rest = s; }
+
+  /* If the first word is quoted, then we need to unquote it and
+   * escape spaces within it.  We'll expand into the resspec buffer,
+   * then copy back into the cmd buffer, expanding the latter if
+   * necessary.
+   */
+  if (*rest == '"') {
+    char *cp2;
+    char *r = rest;
+    bool in_quote = 0;
+    int clen = cmdlen;
+    int soff = s - cmd;
+
+    for (cp2 = resspec;
+         *rest && cp2 - resspec < (VMS_MAXRSS - 1);
+         rest++) {
+
+      if (*rest == ' ') {    /* Escape ' ' to '^_'. */
+        *cp2 = '^';
+        *(++cp2) = '_';
+        cp2++;
+        clen++;
+      }
+      else if (*rest == '"') {
+        clen--;
+        if (in_quote) {     /* Must be closing quote. */
+          rest++;
+          break;
+        }
+        in_quote = 1;
+      }
+      else {
+        *cp2 = *rest;
+        cp2++;
+      }
+    }
+    *cp2 = '\0';
+
+    /* Expand the command buffer if necessary. */
+    if (clen > cmdlen) {
+      cmd = (char *)PerlMem_realloc(cmd, clen);
+      if (cmd == NULL)
+        _ckvmssts_noperl(SS$_INSFMEM);
+      /* Where we are may have changed, so recompute offsets */
+      r = cmd + (r - s - soff);
+      rest = cmd + (rest - s - soff);
+      s = cmd + soff;
+    }
+
+    /* Shift the non-verb portion of the command (if any) up or
+     * down as necessary.
+     */
+    if (*rest)
+      memmove(rest + clen - cmdlen, rest, s - soff + cmdlen - rest);
+
+    /* Copy the unquoted and escaped command verb into place. */
+    memcpy(r, resspec, cp2 - resspec); 
+    cmd[clen] = '\0';
+    cmdlen = clen;
+    rest = r;         /* Rewind for subsequent operations. */
+  }
+
   if (*rest == '.' || *rest == '/') {
     char *cp2;
     for (cp2 = resspec;
@@ -10724,7 +10640,7 @@ setup_cmddsc(pTHX_ const char *incmd, int check_img, int *suggest_quote,
       isdcl = 1;
       if (suggest_quote) *suggest_quote = 1;
   } else {
-    register char *filespec = strpbrk(s,":<[.;");
+    char *filespec = strpbrk(s,":<[.;");
     rest = wordbreak = strpbrk(s," \"\t/");
     if (!wordbreak) wordbreak = s + strlen(s);
     if (*s == '$') check_img = 0;
@@ -10860,7 +10776,7 @@ setup_cmddsc(pTHX_ const char *incmd, int check_img, int *suggest_quote,
                  else {
                    tchr = tmpspec;
                  }
-                 strcpy(image_name, tchr);
+                 my_strlcpy(image_name, tchr, sizeof(image_name));
                }
              }
            }
@@ -10876,33 +10792,33 @@ setup_cmddsc(pTHX_ const char *incmd, int check_img, int *suggest_quote,
       }
 
       if (cando_by_name(S_IXUSR,0,resspec)) {
-        vmscmd->dsc$a_pointer = PerlMem_malloc(MAX_DCL_LINE_LENGTH);
+        vmscmd->dsc$a_pointer = (char *)PerlMem_malloc(MAX_DCL_LINE_LENGTH);
        if (vmscmd->dsc$a_pointer == NULL) _ckvmssts_noperl(SS$_INSFMEM);
         if (!isdcl) {
-            strcpy(vmscmd->dsc$a_pointer,"$ MCR ");
+            my_strlcpy(vmscmd->dsc$a_pointer,"$ MCR ", MAX_DCL_LINE_LENGTH);
            if (image_name[0] != 0) {
-               strcat(vmscmd->dsc$a_pointer, image_name);
-               strcat(vmscmd->dsc$a_pointer, " ");
+               my_strlcat(vmscmd->dsc$a_pointer, image_name, MAX_DCL_LINE_LENGTH);
+               my_strlcat(vmscmd->dsc$a_pointer, " ", MAX_DCL_LINE_LENGTH);
            }
        } else if (image_name[0] != 0) {
-           strcpy(vmscmd->dsc$a_pointer, image_name);
-           strcat(vmscmd->dsc$a_pointer, " ");
+           my_strlcpy(vmscmd->dsc$a_pointer, image_name, MAX_DCL_LINE_LENGTH);
+           my_strlcat(vmscmd->dsc$a_pointer, " ", MAX_DCL_LINE_LENGTH);
         } else {
-            strcpy(vmscmd->dsc$a_pointer,"@");
+            my_strlcpy(vmscmd->dsc$a_pointer, "@", MAX_DCL_LINE_LENGTH);
         }
         if (suggest_quote) *suggest_quote = 1;
 
        /* If there is an image name, use original command */
        if (image_name[0] == 0)
-           strcat(vmscmd->dsc$a_pointer,resspec);
+           my_strlcat(vmscmd->dsc$a_pointer, resspec, MAX_DCL_LINE_LENGTH);
        else {
            rest = cmd;
            while (*rest && isspace(*rest)) rest++;
        }
 
        if (image_argv[0] != 0) {
-         strcat(vmscmd->dsc$a_pointer,image_argv);
-         strcat(vmscmd->dsc$a_pointer, " ");
+         my_strlcat(vmscmd->dsc$a_pointer, image_argv, MAX_DCL_LINE_LENGTH);
+         my_strlcat(vmscmd->dsc$a_pointer, " ", MAX_DCL_LINE_LENGTH);
        }
         if (rest) {
           int rest_len;
@@ -10911,7 +10827,7 @@ setup_cmddsc(pTHX_ const char *incmd, int check_img, int *suggest_quote,
           rest_len = strlen(rest);
           vmscmd_len = strlen(vmscmd->dsc$a_pointer);
           if ((rest_len + vmscmd_len) < MAX_DCL_LINE_LENGTH)
-             strcat(vmscmd->dsc$a_pointer,rest);
+             my_strlcat(vmscmd->dsc$a_pointer, rest, MAX_DCL_LINE_LENGTH);
           else
             retsts = CLI$_BUFOVF;
        }
@@ -10928,9 +10844,8 @@ setup_cmddsc(pTHX_ const char *incmd, int check_img, int *suggest_quote,
   /* It's either a DCL command or we couldn't find a suitable image */
   vmscmd->dsc$w_length = strlen(cmd);
 
-  vmscmd->dsc$a_pointer = PerlMem_malloc(vmscmd->dsc$w_length + 1);
-  strncpy(vmscmd->dsc$a_pointer,cmd,vmscmd->dsc$w_length);
-  vmscmd->dsc$a_pointer[vmscmd->dsc$w_length] = 0;
+  vmscmd->dsc$a_pointer = (char *)PerlMem_malloc(vmscmd->dsc$w_length + 1);
+  my_strlcpy(vmscmd->dsc$a_pointer, cmd, vmscmd->dsc$w_length + 1);
 
   PerlMem_free(cmd);
   PerlMem_free(resspec);
@@ -10963,8 +10878,8 @@ setup_cmddsc(pTHX_ const char *incmd, int check_img, int *suggest_quote,
 bool
 Perl_vms_do_aexec(pTHX_ SV *really,SV **mark,SV **sp)
 {
-bool exec_sts;
-char * cmd;
+  bool exec_sts;
+  char * cmd;
 
   if (sp > mark) {
     if (vfork_called) {           /* this follows a vfork - act Unixish */
@@ -11045,9 +10960,9 @@ int do_spawn2(pTHX_ const char *, int);
 int
 Perl_do_aspawn(pTHX_ SV* really, SV** mark, SV** sp)
 {
-unsigned long int sts;
-char * cmd;
-int flags = 0;
+  unsigned long int sts;
+  char * cmd;
+  int flags = 0;
 
   if (sp > mark) {
 
@@ -11147,7 +11062,11 @@ do_spawn2(pTHX_ const char *cmd, int flags)
     fp = safe_popen(aTHX_ cmd, mode, (int *)&sts);
     if (fp != NULL)
       my_pclose(fp);
-    /* sts will be the pid in the nowait case */
+    /* sts will be the pid in the nowait case, so leave a
+     * hint saying not to do any bit shifting to it.
+     */
+    if (flags & CLI$M_NOWAIT)
+        PL_statusvalue = -1;
   }
   return sts;
 }  /* end of do_spawn2() */
@@ -11163,7 +11082,8 @@ static unsigned int *sockflags, sockflagsize;
  * likely to be opened by a name.
  */
 /*{{{ FILE *my_fdopen(int fd, const char *mode)*/
-FILE *my_fdopen(int fd, const char *mode)
+FILE *
+my_fdopen(int fd, const char *mode)
 {
   FILE *fp = fdopen(fd, mode);
 
@@ -11191,7 +11111,8 @@ FILE *my_fdopen(int fd, const char *mode)
  * via freopen().  >> Todo
  */
 /*{{{ int my_fclose(FILE *fp)*/
-int my_fclose(FILE *fp) {
+int
+my_fclose(FILE *fp) {
   if (fp) {
     unsigned int fd = fileno(fp);
     unsigned int fdoff = fd / sizeof(unsigned int);
@@ -11216,10 +11137,10 @@ int my_fclose(FILE *fp) {
 int
 my_fwrite(const void *src, size_t itmsz, size_t nitm, FILE *dest)
 {
-  register char *cp, *end, *cpd;
+  char *cp, *end, *cpd;
   char *data;
-  register unsigned int fd = fileno(dest);
-  register unsigned int fdoff = fd / sizeof(unsigned int);
+  unsigned int fd = fileno(dest);
+  unsigned int fdoff = fd / sizeof(unsigned int);
   int retval;
   int bufsize = itmsz * nitm + 1;
 
@@ -11293,8 +11214,8 @@ Perl_my_fgetname(FILE *fp, char * buf) {
     }
 
     /* Convert this to Unix format */
-    vms_name = PerlMem_malloc(VMS_MAXRSS + 1);
-    strcpy(vms_name, retname);
+    vms_name = (char *)PerlMem_malloc(VMS_MAXRSS);
+    my_strlcpy(vms_name, retname, VMS_MAXRSS);
     retname = int_tounixspec(vms_name, buf, NULL);
     PerlMem_free(vms_name);
 
@@ -11362,7 +11283,8 @@ static char __pw_namecache[UAI$S_IDENT+1];
 /*
  * This routine does most of the work extracting the user information.
  */
-static int fillpasswd (pTHX_ const char *name, struct passwd *pwd)
+static int
+fillpasswd (pTHX_ const char *name, struct passwd *pwd)
 {
     static struct {
         unsigned char length;
@@ -11434,7 +11356,7 @@ static int fillpasswd (pTHX_ const char *name, struct passwd *pwd)
         if (pwd->pw_unixdir[ldir]=='/') pwd->pw_unixdir[ldir]= '\0';
     }
     else
-        strcpy(pwd->pw_unixdir, pwd->pw_dir);
+        my_strlcpy(pwd->pw_unixdir, pwd->pw_dir, sizeof(pwd->pw_unixdir));
     if (!decc_efs_case_preserve)
         __mystrtolower(pwd->pw_unixdir);
     return 1;
@@ -11444,11 +11366,12 @@ static int fillpasswd (pTHX_ const char *name, struct passwd *pwd)
  * Get information for a named user.
 */
 /*{{{struct passwd *getpwnam(char *name)*/
-struct passwd *Perl_my_getpwnam(pTHX_ const char *name)
+struct passwd *
+Perl_my_getpwnam(pTHX_ const char *name)
 {
     struct dsc$descriptor_s name_desc;
     union uicdef uic;
-    unsigned long int status, sts;
+    unsigned long int sts;
                                   
     __pwdcache = __passwd_empty;
     if (!fillpasswd(aTHX_ name, &__pwdcache)) {
@@ -11470,8 +11393,7 @@ struct passwd *Perl_my_getpwnam(pTHX_ const char *name)
         else { _ckvmssts(sts); }
       }
     }
-    strncpy(__pw_namecache, name, sizeof(__pw_namecache));
-    __pw_namecache[sizeof __pw_namecache - 1] = '\0';
+    my_strlcpy(__pw_namecache, name, sizeof(__pw_namecache));
     __pwdcache.pw_name= __pw_namecache;
     return &__pwdcache;
 }  /* end of my_getpwnam() */
@@ -11482,7 +11404,8 @@ struct passwd *Perl_my_getpwnam(pTHX_ const char *name)
  * Called by my_getpwent with uid=-1 to list all users.
 */
 /*{{{struct passwd *my_getpwuid(Uid_t uid)*/
-struct passwd *Perl_my_getpwuid(pTHX_ Uid_t uid)
+struct passwd *
+Perl_my_getpwuid(pTHX_ Uid_t uid)
 {
     const $DESCRIPTOR(name_desc,__pw_namecache);
     unsigned short lname;
@@ -11537,7 +11460,8 @@ struct passwd *Perl_my_getpwuid(pTHX_ Uid_t uid)
  * Get information for next user.
 */
 /*{{{struct passwd *my_getpwent()*/
-struct passwd *Perl_my_getpwent(pTHX)
+struct passwd *
+Perl_my_getpwent(pTHX)
 {
     return (my_getpwuid((unsigned int) -1));
 }
@@ -11547,7 +11471,8 @@ struct passwd *Perl_my_getpwent(pTHX)
  * Finish searching rights database for users.
 */
 /*{{{void my_endpwent()*/
-void Perl_my_endpwent(pTHX)
+void
+Perl_my_endpwent(pTHX)
 {
     if (contxt) {
       _ckvmssts(sys$finish_rdb(&contxt));
@@ -11556,105 +11481,6 @@ void Perl_my_endpwent(pTHX)
 }
 /*}}}*/
 
-#ifdef HOMEGROWN_POSIX_SIGNALS
-  /* Signal handling routines, pulled into the core from POSIX.xs.
-   *
-   * We need these for threads, so they've been rolled into the core,
-   * rather than left in POSIX.xs.
-   *
-   * (DRS, Oct 23, 1997)
-   */
-
-  /* sigset_t is atomic under VMS, so these routines are easy */
-/*{{{int my_sigemptyset(sigset_t *) */
-int my_sigemptyset(sigset_t *set) {
-    if (!set) { SETERRNO(EFAULT,SS$_ACCVIO); return -1; }
-    *set = 0; return 0;
-}
-/*}}}*/
-
-
-/*{{{int my_sigfillset(sigset_t *)*/
-int my_sigfillset(sigset_t *set) {
-    int i;
-    if (!set) { SETERRNO(EFAULT,SS$_ACCVIO); return -1; }
-    for (i = 0; i < NSIG; i++) *set |= (1 << i);
-    return 0;
-}
-/*}}}*/
-
-
-/*{{{int my_sigaddset(sigset_t *set, int sig)*/
-int my_sigaddset(sigset_t *set, int sig) {
-    if (!set) { SETERRNO(EFAULT,SS$_ACCVIO); return -1; }
-    if (sig > NSIG) { SETERRNO(EINVAL,LIB$_INVARG); return -1; }
-    *set |= (1 << (sig - 1));
-    return 0;
-}
-/*}}}*/
-
-
-/*{{{int my_sigdelset(sigset_t *set, int sig)*/
-int my_sigdelset(sigset_t *set, int sig) {
-    if (!set) { SETERRNO(EFAULT,SS$_ACCVIO); return -1; }
-    if (sig > NSIG) { SETERRNO(EINVAL,LIB$_INVARG); return -1; }
-    *set &= ~(1 << (sig - 1));
-    return 0;
-}
-/*}}}*/
-
-
-/*{{{int my_sigismember(sigset_t *set, int sig)*/
-int my_sigismember(sigset_t *set, int sig) {
-    if (!set) { SETERRNO(EFAULT,SS$_ACCVIO); return -1; }
-    if (sig > NSIG) { SETERRNO(EINVAL,LIB$_INVARG); return -1; }
-    return *set & (1 << (sig - 1));
-}
-/*}}}*/
-
-
-/*{{{int my_sigprocmask(int how, sigset_t *set, sigset_t *oset)*/
-int my_sigprocmask(int how, sigset_t *set, sigset_t *oset) {
-    sigset_t tempmask;
-
-    /* If set and oset are both null, then things are badly wrong. Bail out. */
-    if ((oset == NULL) && (set == NULL)) {
-      set_errno(EFAULT); set_vaxc_errno(SS$_ACCVIO);
-      return -1;
-    }
-
-    /* If set's null, then we're just handling a fetch. */
-    if (set == NULL) {
-        tempmask = sigblock(0);
-    }
-    else {
-      switch (how) {
-      case SIG_SETMASK:
-        tempmask = sigsetmask(*set);
-        break;
-      case SIG_BLOCK:
-        tempmask = sigblock(*set);
-        break;
-      case SIG_UNBLOCK:
-        tempmask = sigblock(0);
-        sigsetmask(*oset & ~tempmask);
-        break;
-      default:
-        set_errno(EINVAL); set_vaxc_errno(LIB$_INVARG);
-        return -1;
-      }
-    }
-
-    /* Did they pass us an oset? If so, stick our holding mask into it */
-    if (oset)
-      *oset = tempmask;
-  
-    return 0;
-}
-/*}}}*/
-#endif  /* HOMEGROWN_POSIX_SIGNALS */
-
-
 /* Used for UTC calculation in my_gmtime(), my_localtime(), my_time(),
  * my_utime(), and flex_stat(), all of which operate on UTC unless
  * VMSISH_TIMES is true.
@@ -11675,31 +11501,10 @@ static long int utc_offset_secs;
 #undef time
 
 
-/*
- * DEC C previous to 6.0 corrupts the behavior of the /prefix
- * qualifier with the extern prefix pragma.  This provisional
- * hack circumvents this prefix pragma problem in previous 
- * precompilers.
- */
-#if defined(__VMS_VER) && __VMS_VER >= 70000000 
-#  if defined(VMS_WE_ARE_CASE_SENSITIVE) && (__DECC_VER < 60000000)
-#    pragma __extern_prefix save
-#    pragma __extern_prefix ""  /* set to empty to prevent prefixing */
-#    define gmtime decc$__utctz_gmtime
-#    define localtime decc$__utctz_localtime
-#    define time decc$__utc_time
-#    pragma __extern_prefix restore
-
-     struct tm *gmtime(), *localtime();   
-
-#  endif
-#endif
-
-
 static time_t toutc_dst(time_t loc) {
   struct tm *rsltmp;
 
-  if ((rsltmp = localtime(&loc)) == NULL) return -1;
+  if ((rsltmp = localtime(&loc)) == NULL) return -1u;
   loc -= utc_offset_secs;
   if (rsltmp->tm_isdst) loc -= 3600;
   return loc;
@@ -11713,7 +11518,7 @@ static time_t toloc_dst(time_t utc) {
   struct tm *rsltmp;
 
   utc += utc_offset_secs;
-  if ((rsltmp = localtime(&utc)) == NULL) return -1;
+  if ((rsltmp = localtime(&utc)) == NULL) return -1u;
   if (rsltmp->tm_isdst) utc += 3600;
   return utc;
 }
@@ -11722,290 +11527,6 @@ static time_t toloc_dst(time_t utc) {
        (gmtime_emulation_type == 1 ? toloc_dst(secs) : \
        ((secs) + utc_offset_secs))))
 
-#ifndef RTL_USES_UTC
-/*
-  
-    ucx$tz = "EST5EDT4,M4.1.0,M10.5.0"  typical 
-        DST starts on 1st sun of april      at 02:00  std time
-            ends on last sun of october     at 02:00  dst time
-    see the UCX management command reference, SET CONFIG TIMEZONE
-    for formatting info.
-
-    No, it's not as general as it should be, but then again, NOTHING
-    will handle UK times in a sensible way. 
-*/
-
-
-/* 
-    parse the DST start/end info:
-    (Jddd|ddd|Mmon.nth.dow)[/hh:mm:ss]
-*/
-
-static char *
-tz_parse_startend(char *s, struct tm *w, int *past)
-{
-    int dinm[] = {31,28,31,30,31,30,31,31,30,31,30,31};
-    int ly, dozjd, d, m, n, hour, min, sec, j, k;
-    time_t g;
-
-    if (!s)    return 0;
-    if (!w) return 0;
-    if (!past) return 0;
-
-    ly = 0;
-    if (w->tm_year % 4        == 0) ly = 1;
-    if (w->tm_year % 100      == 0) ly = 0;
-    if (w->tm_year+1900 % 400 == 0) ly = 1;
-    if (ly) dinm[1]++;
-
-    dozjd = isdigit(*s);
-    if (*s == 'J' || *s == 'j' || dozjd) {
-        if (!dozjd && !isdigit(*++s)) return 0;
-        d = *s++ - '0';
-        if (isdigit(*s)) {
-            d = d*10 + *s++ - '0';
-            if (isdigit(*s)) {
-                d = d*10 + *s++ - '0';
-            }
-        }
-        if (d == 0) return 0;
-        if (d > 366) return 0;
-        d--;
-        if (!dozjd && d > 58 && ly) d++;  /* after 28 feb */
-        g = d * 86400;
-        dozjd = 1;
-    } else if (*s == 'M' || *s == 'm') {
-        if (!isdigit(*++s)) return 0;
-        m = *s++ - '0';
-        if (isdigit(*s)) m = 10*m + *s++ - '0';
-        if (*s != '.') return 0;
-        if (!isdigit(*++s)) return 0;
-        n = *s++ - '0';
-        if (n < 1 || n > 5) return 0;
-        if (*s != '.') return 0;
-        if (!isdigit(*++s)) return 0;
-        d = *s++ - '0';
-        if (d > 6) return 0;
-    }
-
-    if (*s == '/') {
-        if (!isdigit(*++s)) return 0;
-        hour = *s++ - '0';
-        if (isdigit(*s)) hour = 10*hour + *s++ - '0';
-        if (*s == ':') {
-            if (!isdigit(*++s)) return 0;
-            min = *s++ - '0';
-            if (isdigit(*s)) min = 10*min + *s++ - '0';
-            if (*s == ':') {
-                if (!isdigit(*++s)) return 0;
-                sec = *s++ - '0';
-                if (isdigit(*s)) sec = 10*sec + *s++ - '0';
-            }
-        }
-    } else {
-        hour = 2;
-        min = 0;
-        sec = 0;
-    }
-
-    if (dozjd) {
-        if (w->tm_yday < d) goto before;
-        if (w->tm_yday > d) goto after;
-    } else {
-        if (w->tm_mon+1 < m) goto before;
-        if (w->tm_mon+1 > m) goto after;
-
-        j = (42 + w->tm_wday - w->tm_mday)%7;   /*dow of mday 0 */
-        k = d - j; /* mday of first d */
-        if (k <= 0) k += 7;
-        k += 7 * ((n>4?4:n)-1);  /* mday of n'th d */
-        if (n == 5 && k+7 <= dinm[w->tm_mon]) k += 7;
-        if (w->tm_mday < k) goto before;
-        if (w->tm_mday > k) goto after;
-    }
-
-    if (w->tm_hour < hour) goto before;
-    if (w->tm_hour > hour) goto after;
-    if (w->tm_min  < min)  goto before;
-    if (w->tm_min  > min)  goto after;
-    if (w->tm_sec  < sec)  goto before;
-    goto after;
-
-before:
-    *past = 0;
-    return s;
-after:
-    *past = 1;
-    return s;
-}
-
-
-
-
-/*  parse the offset:   (+|-)hh[:mm[:ss]]  */
-
-static char *
-tz_parse_offset(char *s, int *offset)
-{
-    int hour = 0, min = 0, sec = 0;
-    int neg = 0;
-    if (!s) return 0;
-    if (!offset) return 0;
-
-    if (*s == '-') {neg++; s++;}
-    if (*s == '+') s++;
-    if (!isdigit(*s)) return 0;
-    hour = *s++ - '0';
-    if (isdigit(*s)) hour = hour*10+(*s++ - '0');
-    if (hour > 24) return 0;
-    if (*s == ':') {
-        if (!isdigit(*++s)) return 0;
-        min = *s++ - '0';
-        if (isdigit(*s)) min = min*10 + (*s++ - '0');
-        if (min > 59) return 0;
-        if (*s == ':') {
-            if (!isdigit(*++s)) return 0;
-            sec = *s++ - '0';
-            if (isdigit(*s)) sec = sec*10 + (*s++ - '0');
-            if (sec > 59) return 0;
-        }
-    }
-
-    *offset = (hour*60+min)*60 + sec;
-    if (neg) *offset = -*offset;
-    return s;
-}
-
-/*
-    input time is w, whatever type of time the CRTL localtime() uses.
-    sets dst, the zone, and the gmtoff (seconds)
-
-    caches the value of TZ and UCX$TZ env variables; note that 
-    my_setenv looks for these and sets a flag if they're changed
-    for efficiency. 
-
-    We have to watch out for the "australian" case (dst starts in
-    october, ends in april)...flagged by "reverse" and checked by
-    scanning through the months of the previous year.
-
-*/
-
-static int
-tz_parse(pTHX_ time_t *w, int *dst, char *zone, int *gmtoff)
-{
-    time_t when;
-    struct tm *w2;
-    char *s,*s2;
-    char *dstzone, *tz, *s_start, *s_end;
-    int std_off, dst_off, isdst;
-    int y, dststart, dstend;
-    static char envtz[1025];  /* longer than any logical, symbol, ... */
-    static char ucxtz[1025];
-    static char reversed = 0;
-
-    if (!w) return 0;
-
-    if (tz_updated) {
-        tz_updated = 0;
-        reversed = -1;  /* flag need to check  */
-        envtz[0] = ucxtz[0] = '\0';
-        tz = my_getenv("TZ",0);
-        if (tz) strcpy(envtz, tz);
-        tz = my_getenv("UCX$TZ",0);
-        if (tz) strcpy(ucxtz, tz);
-        if (!envtz[0] && !ucxtz[0]) return 0;  /* we give up */
-    }
-    tz = envtz;
-    if (!*tz) tz = ucxtz;
-
-    s = tz;
-    while (isalpha(*s)) s++;
-    s = tz_parse_offset(s, &std_off);
-    if (!s) return 0;
-    if (!*s) {                  /* no DST, hurray we're done! */
-        isdst = 0;
-        goto done;
-    }
-
-    dstzone = s;
-    while (isalpha(*s)) s++;
-    s2 = tz_parse_offset(s, &dst_off);
-    if (s2) {
-        s = s2;
-    } else {
-        dst_off = std_off - 3600;
-    }
-
-    if (!*s) {      /* default dst start/end?? */
-        if (tz != ucxtz) {          /* if TZ tells zone only, UCX$TZ tells rule */
-            s = strchr(ucxtz,',');
-        }
-        if (!s || !*s) s = ",M4.1.0,M10.5.0";   /* we know we do dst, default rule */
-    }
-    if (*s != ',') return 0;
-
-    when = *w;
-    when = _toutc(when);      /* convert to utc */
-    when = when - std_off;    /* convert to pseudolocal time*/
-
-    w2 = localtime(&when);
-    y = w2->tm_year;
-    s_start = s+1;
-    s = tz_parse_startend(s_start,w2,&dststart);
-    if (!s) return 0;
-    if (*s != ',') return 0;
-
-    when = *w;
-    when = _toutc(when);      /* convert to utc */
-    when = when - dst_off;    /* convert to pseudolocal time*/
-    w2 = localtime(&when);
-    if (w2->tm_year != y) {   /* spans a year, just check one time */
-        when += dst_off - std_off;
-        w2 = localtime(&when);
-    }
-    s_end = s+1;
-    s = tz_parse_startend(s_end,w2,&dstend);
-    if (!s) return 0;
-
-    if (reversed == -1) {  /* need to check if start later than end */
-        int j, ds, de;
-
-        when = *w;
-        if (when < 2*365*86400) {
-            when += 2*365*86400;
-        } else {
-            when -= 365*86400;
-        }
-        w2 =localtime(&when);
-        when = when + (15 - w2->tm_yday) * 86400;   /* jan 15 */
-
-        for (j = 0; j < 12; j++) {
-            w2 =localtime(&when);
-            tz_parse_startend(s_start,w2,&ds);
-            tz_parse_startend(s_end,w2,&de);
-            if (ds != de) break;
-            when += 30*86400;
-        }
-        reversed = 0;
-        if (de && !ds) reversed = 1;
-    }
-
-    isdst = dststart && !dstend;
-    if (reversed) isdst = dststart  || !dstend;
-
-done:
-    if (dst)    *dst = isdst;
-    if (gmtoff) *gmtoff = isdst ? dst_off : std_off;
-    if (isdst)  tz = dstzone;
-    if (zone) {
-        while(isalpha(*tz))  *zone++ = *tz++;
-        *zone = '\0';
-    }
-    return 1;
-}
-
-#endif /* !RTL_USES_UTC */
-
 /* my_time(), my_localtime(), my_gmtime()
  * By default traffic in UTC time values, using CRTL gmtime() or
  * SYS$TIMEZONE_DIFFERENTIAL to determine offset from local time zone.
@@ -12017,13 +11538,13 @@ done:
  */
 
 /*{{{time_t my_time(time_t *timep)*/
-time_t Perl_my_time(pTHX_ time_t *timep)
+time_t
+Perl_my_time(pTHX_ time_t *timep)
 {
   time_t when;
   struct tm *tm_p;
 
   if (gmtime_emulation_type == 0) {
-    int dstnow;
     time_t base = 15 * 86400; /* 15jan71; to avoid month/year ends between    */
                               /* results of calls to gmtime() and localtime() */
                               /* for same &base */
@@ -12055,11 +11576,7 @@ time_t Perl_my_time(pTHX_ time_t *timep)
 
   when = time(NULL);
 # ifdef VMSISH_TIME
-# ifdef RTL_USES_UTC
   if (VMSISH_TIME) when = _toloc(when);
-# else
-  if (!VMSISH_TIME) when = _toutc(when);
-# endif
 # endif
   if (timep != NULL) *timep = when;
   return when;
@@ -12072,7 +11589,6 @@ time_t Perl_my_time(pTHX_ time_t *timep)
 struct tm *
 Perl_my_gmtime(pTHX_ const time_t *timep)
 {
-  char *p;
   time_t when;
   struct tm *rsltmp;
 
@@ -12086,14 +11602,7 @@ Perl_my_gmtime(pTHX_ const time_t *timep)
 # ifdef VMSISH_TIME
   if (VMSISH_TIME) when = _toutc(when); /* Input was local time */
 #  endif
-# ifdef RTL_USES_UTC  /* this implies that the CRTL has a working gmtime() */
   return gmtime(&when);
-# else
-  /* CRTL localtime() wants local time as input, so does no tz correction */
-  rsltmp = localtime(&when);
-  if (rsltmp) rsltmp->tm_isdst = 0;  /* We already took DST into account */
-  return rsltmp;
-#endif
 }  /* end of my_gmtime() */
 /*}}}*/
 
@@ -12102,9 +11611,7 @@ Perl_my_gmtime(pTHX_ const time_t *timep)
 struct tm *
 Perl_my_localtime(pTHX_ const time_t *timep)
 {
-  time_t when, whenutc;
-  struct tm *rsltmp;
-  int dst, offset;
+  time_t when;
 
   if (timep == NULL) {
     set_errno(EINVAL); set_vaxc_errno(LIB$_INVARG);
@@ -12114,31 +11621,11 @@ Perl_my_localtime(pTHX_ const time_t *timep)
   if (gmtime_emulation_type == 0) my_time(NULL); /* Init UTC */
 
   when = *timep;
-# ifdef RTL_USES_UTC
 # ifdef VMSISH_TIME
   if (VMSISH_TIME) when = _toutc(when);
 # endif
   /* CRTL localtime() wants UTC as input, does tz correction itself */
   return localtime(&when);
-  
-# else /* !RTL_USES_UTC */
-  whenutc = when;
-# ifdef VMSISH_TIME
-  if (!VMSISH_TIME) when = _toloc(whenutc);  /*  input was UTC */
-  if (VMSISH_TIME) whenutc = _toutc(when);   /*  input was truelocal */
-# endif
-  dst = -1;
-#ifndef RTL_USES_UTC
-  if (tz_parse(aTHX_ &when, &dst, 0, &offset)) {   /* truelocal determines DST*/
-      when = whenutc - offset;                   /* pseudolocal time*/
-  }
-# endif
-  /* CRTL localtime() wants local time as input, so does no tz correction */
-  rsltmp = localtime(&when);
-  if (rsltmp && gmtime_emulation_type != 1) rsltmp->tm_isdst = dst;
-  return rsltmp;
-# endif
-
 } /*  end of my_localtime() */
 /*}}}*/
 
@@ -12174,7 +11661,8 @@ Perl_my_localtime(pTHX_ const time_t *timep)
 static const long int utime_baseadjust[2] = { 0x4beb4000, 0x7c9567 };
 
 /*{{{int my_utime(const char *path, const struct utimbuf *utimes)*/
-int Perl_my_utime(pTHX_ const char *file, const struct utimbuf *utimes)
+int
+Perl_my_utime(pTHX_ const char *file, const struct utimbuf *utimes)
 {
 #if __CRTL_VER >= 70300000
   struct utimbuf utc_utimes, *utc_utimesp;
@@ -12199,7 +11687,7 @@ int Perl_my_utime(pTHX_ const char *file, const struct utimbuf *utimes)
 
 #else /* __CRTL_VER < 70300000 */
 
-  register int i;
+  int i;
   int sts;
   long int bintime[2], len = 2, lowbit, unixtime,
            secscale = 10000000; /* seconds --> 100 ns intervals */
@@ -12390,7 +11878,8 @@ int Perl_my_utime(pTHX_ const char *file, const struct utimbuf *utimes)
  * on the first call.
  */
 #define LOCKID_MASK 0x80000000     /* Use 0 to force device name use only */
-static mydev_t encode_dev (pTHX_ const char *dev)
+static mydev_t
+encode_dev (pTHX_ const char *dev)
 {
   int i;
   unsigned long int f;
@@ -12454,8 +11943,7 @@ static mydev_t encode_dev (pTHX_ const char *dev)
 #endif
 
 static int
-is_null_device(name)
-    const char *name;
+is_null_device(const char *name)
 {
   if (decc_bug_devnull != 0) {
     if (strncmp("/dev/null", name, 9) == 0)
@@ -12481,8 +11969,7 @@ Perl_flex_stat_int(pTHX_ const char *fspec, Stat_t *statbufp, int lstat_flag);
 #define flex_stat_int(a,b,c)           Perl_flex_stat_int(aTHX_ a,b,c)
 
 static I32
-Perl_cando_by_name_int
-   (pTHX_ I32 bit, bool effective, const char *fname, int opts)
+Perl_cando_by_name_int(pTHX_ I32 bit, bool effective, const char *fname, int opts)
 {
   char usrname[L_cuserid];
   struct dsc$descriptor_s usrdsc =
@@ -12507,10 +11994,10 @@ Perl_cando_by_name_int
   if (!fname || !*fname) return FALSE;
 
   /* Make sure we expand logical names, since sys$check_access doesn't */
-  fileified = PerlMem_malloc(VMS_MAXRSS);
+  fileified = (char *)PerlMem_malloc(VMS_MAXRSS);
   if (fileified == NULL) _ckvmssts_noperl(SS$_INSFMEM);
   if (!strpbrk(fname,"/]>:")) {
-      strcpy(fileified,fname);
+      my_strlcpy(fileified, fname, VMS_MAXRSS);
       trnlnm_iter_count = 0;
       while (!strpbrk(fileified,"/]>:") && my_trnlnm(fileified,fileified,0)) {
         trnlnm_iter_count++; 
@@ -12519,7 +12006,7 @@ Perl_cando_by_name_int
       fname = fileified;
   }
 
-  vmsname = PerlMem_malloc(VMS_MAXRSS);
+  vmsname = (char *)PerlMem_malloc(VMS_MAXRSS);
   if (vmsname == NULL) _ckvmssts_noperl(SS$_INSFMEM);
   if ( !(opts & PERL_RMSEXPAND_M_VMS_IN) ) {
     /* Don't know if already in VMS format, so make sure */
@@ -12530,7 +12017,7 @@ Perl_cando_by_name_int
     }
   }
   else {
-    strcpy(vmsname,fname);
+    my_strlcpy(vmsname, fname, VMS_MAXRSS);
   }
 
   /* sys$check_access needs a file spec, not a directory spec.
@@ -12594,14 +12081,12 @@ Perl_cando_by_name_int
   _ckvmssts_noperl(sys$getjpiw(0,0,0,jpilst,iosb,0,0));
   _ckvmssts_noperl(iosb[0]);
 
-#if defined(__VMS_VER) && __VMS_VER >= 60000000
-
   /* find out the space required for the profile */
   _ckvmssts_noperl(sys$create_user_profile(&usrdsc,&usrprolst,0,0,
                                     &usrprodsc.dsc$w_length,&profile_context));
 
   /* allocate space for the profile and get it filled in */
-  usrprodsc.dsc$a_pointer = PerlMem_malloc(usrprodsc.dsc$w_length);
+  usrprodsc.dsc$a_pointer = (char *)PerlMem_malloc(usrprodsc.dsc$w_length);
   if (usrprodsc.dsc$a_pointer == NULL) _ckvmssts_noperl(SS$_INSFMEM);
   _ckvmssts_noperl(sys$create_user_profile(&usrdsc,&usrprolst,0,usrprodsc.dsc$a_pointer,
                                     &usrprodsc.dsc$w_length,&profile_context));
@@ -12611,12 +12096,6 @@ Perl_cando_by_name_int
   PerlMem_free(usrprodsc.dsc$a_pointer);
   if (retsts == SS$_NOCALLPRIV) retsts = SS$_NOPRIV; /* not really 3rd party */
 
-#else
-
-  retsts = sys$check_access(&objtyp,&namdsc,&usrdsc,armlst);
-
-#endif
-
   if (retsts == SS$_NOPRIV      || retsts == SS$_NOSUCHOBJECT ||
       retsts == SS$_INVFILFOROP || retsts == RMS$_FNF || retsts == RMS$_SYN ||
       retsts == RMS$_DIR        || retsts == RMS$_DEV || retsts == RMS$_DNF) {
@@ -12674,10 +12153,11 @@ Perl_cando_by_name(pTHX_ I32 bit, bool effective, const char *fname)
 int
 Perl_flex_fstat(pTHX_ int fd, Stat_t *statbufp)
 {
+  dSAVE_ERRNO; /* fstat may set this even on success */
   if (!fstat(fd, &statbufp->crtl_stat)) {
     char *cptr;
     char *vms_filename;
-    vms_filename = PerlMem_malloc(VMS_MAXRSS);
+    vms_filename = (char *)PerlMem_malloc(VMS_MAXRSS);
     if (vms_filename == NULL) _ckvmssts(SS$_INSFMEM);
 
     /* Save name for cando by name in VMS format */
@@ -12702,7 +12182,6 @@ Perl_flex_fstat(pTHX_ int fd, Stat_t *statbufp)
     VMS_DEVICE_ENCODE
        (statbufp->st_dev, statbufp->st_devnam, statbufp->crtl_stat.st_dev);
 
-#   ifdef RTL_USES_UTC
 #   ifdef VMSISH_TIME
     if (VMSISH_TIME) {
       statbufp->st_mtime = _toloc(statbufp->st_mtime);
@@ -12710,17 +12189,7 @@ Perl_flex_fstat(pTHX_ int fd, Stat_t *statbufp)
       statbufp->st_ctime = _toloc(statbufp->st_ctime);
     }
 #   endif
-#   else
-#   ifdef VMSISH_TIME
-    if (!VMSISH_TIME) { /* Return UTC instead of local time */
-#   else
-    if (1) {
-#   endif
-      statbufp->st_mtime = _toutc(statbufp->st_mtime);
-      statbufp->st_atime = _toutc(statbufp->st_atime);
-      statbufp->st_ctime = _toutc(statbufp->st_ctime);
-    }
-#endif
+    RESTORE_ERRNO;
     return 0;
   }
   return -1;
@@ -12731,12 +12200,13 @@ Perl_flex_fstat(pTHX_ int fd, Stat_t *statbufp)
 static int
 Perl_flex_stat_int(pTHX_ const char *fspec, Stat_t *statbufp, int lstat_flag)
 {
-    char *fileified;
-    char *temp_fspec;
+    char *temp_fspec = NULL;
+    char *fileified = NULL;
     const char *save_spec;
     char *ret_spec;
     int retval = -1;
-    int efs_hack = 0;
+    char efs_hack = 0;
+    char already_fileified = 0;
     dSAVEDERRNO;
 
     if (!fspec) {
@@ -12757,58 +12227,58 @@ Perl_flex_stat_int(pTHX_ const char *fspec, Stat_t *statbufp, int lstat_flag)
       }
     }
 
-    /* Try for a directory name first.  If fspec contains a filename without
+    SAVE_ERRNO;
+
+#if __CRTL_VER >= 80200000 && !defined(__VAX)
+  /*
+   * If we are in POSIX filespec mode, accept the filename as is.
+   */
+  if (decc_posix_compliant_pathnames == 0) {
+#endif
+
+    /* Try for a simple stat first.  If fspec contains a filename without
      * a type (e.g. sea:[wine.dark]water), and both sea:[wine.dark]water.dir
-     * and sea:[wine.dark]water. exist, we prefer the directory here.
+     * and sea:[wine.dark]water. exist, the CRTL prefers the directory here.
      * Similarly, sea:[wine.dark] returns the result for sea:[wine]dark.dir,
      * not sea:[wine.dark]., if the latter exists.  If the intended target is
      * the file with null type, specify this by calling flex_stat() with
      * a '.' at the end of fspec.
-     *
-     * If we are in Posix filespec mode, accept the filename as is.
      */
 
+    if (lstat_flag == 0)
+        retval = stat(fspec, &statbufp->crtl_stat);
+    else
+        retval = lstat(fspec, &statbufp->crtl_stat);
 
-    fileified = PerlMem_malloc(VMS_MAXRSS);
-    if (fileified == NULL)
-        _ckvmssts_noperl(SS$_INSFMEM);
-     
-    temp_fspec = PerlMem_malloc(VMS_MAXRSS);
-    if (temp_fspec == NULL)
-        _ckvmssts_noperl(SS$_INSFMEM);
-
-    strcpy(temp_fspec, fspec);
-
-    SAVE_ERRNO;
-
-#if __CRTL_VER >= 80200000 && !defined(__VAX)
-  if (decc_posix_compliant_pathnames == 0) {
-#endif
+    if (!retval) {
+        save_spec = fspec;
+    }
+    else {
+        /* In the odd case where we have write but not read access
+         * to a directory, stat('foo.DIR') works but stat('foo') doesn't.
+         */
+        fileified = (char *)PerlMem_malloc(VMS_MAXRSS);
+        if (fileified == NULL)
+              _ckvmssts_noperl(SS$_INSFMEM);
 
-    /* We may be able to optimize this, but in order for fileify_dirspec to
-     * always return a usuable answer, we have to call vmspath first to
-     * make sure that it is in VMS directory format, as stat/lstat on 8.3
-     * can not handle directories in unix format that it does not have read
-     * access to.  Vmspath handles the case where a bare name which could be
-     * a logical name gets passed.
-     */ 
-    ret_spec = int_tovmspath(fspec, temp_fspec, NULL);
-    if (ret_spec != NULL) {
-        ret_spec = int_fileify_dirspec(temp_fspec, fileified, NULL); 
+        ret_spec = int_fileify_dirspec(fspec, fileified, NULL); 
         if (ret_spec != NULL) {
             if (lstat_flag == 0)
                 retval = stat(fileified, &statbufp->crtl_stat);
             else
                 retval = lstat(fileified, &statbufp->crtl_stat);
             save_spec = fileified;
+            already_fileified = 1;
         }
     }
 
     if (retval && vms_bug_stat_filename) {
 
-        /* We should try again as a vmsified file specification */
-        /* However Perl traditionally has not done this, which  */
-        /* causes problems with existing tests */
+        temp_fspec = (char *)PerlMem_malloc(VMS_MAXRSS);
+        if (temp_fspec == NULL)
+            _ckvmssts_noperl(SS$_INSFMEM);
+
+        /* We should try again as a vmsified file specification. */
 
         ret_spec = int_tovmsspec(fspec, temp_fspec, 0, NULL);
         if (ret_spec != NULL) {
@@ -12821,7 +12291,7 @@ Perl_flex_stat_int(pTHX_ const char *fspec, Stat_t *statbufp, int lstat_flag)
     }
 
     if (retval) {
-        /* Last chance - allow multiple dots with out EFS CHARSET */
+        /* Last chance - allow multiple dots without EFS CHARSET */
         /* The CRTL stat() falls down hard on multi-dot filenames in unix
          * format unless * DECC$EFS_CHARSET is in effect, so temporarily
          * enable it if it isn't already.
@@ -12860,8 +12330,8 @@ Perl_flex_stat_int(pTHX_ const char *fspec, Stat_t *statbufp, int lstat_flag)
 #endif
 
     if (!retval) {
-    char * cptr;
-    int rmsex_flags = PERL_RMSEXPAND_M_VMS;
+      char *cptr;
+      int rmsex_flags = PERL_RMSEXPAND_M_VMS;
 
       /* If this is an lstat, do not follow the link */
       if (lstat_flag)
@@ -12874,7 +12344,27 @@ Perl_flex_stat_int(pTHX_ const char *fspec, Stat_t *statbufp, int lstat_flag)
           decc$feature_set_value(decc_efs_charset_index, 1, 1);
       }
 #endif
-      cptr = int_rmsexpand_tovms(save_spec, statbufp->st_devnam, rmsex_flags);
+
+      /* If we've got a directory, save a fileified, expanded version of it
+       * in st_devnam.  If not a directory, just an expanded version.
+       */
+      if (S_ISDIR(statbufp->st_mode) && !already_fileified) {
+          fileified = (char *)PerlMem_malloc(VMS_MAXRSS);
+          if (fileified == NULL)
+              _ckvmssts_noperl(SS$_INSFMEM);
+
+          cptr = do_fileify_dirspec(save_spec, fileified, 0, NULL);
+          if (cptr != NULL)
+              save_spec = fileified;
+      }
+
+      cptr = int_rmsexpand(save_spec, 
+                           statbufp->st_devnam,
+                           NULL,
+                           rmsex_flags,
+                           0,
+                           0);
+
 #if __CRTL_VER >= 70300000 && !defined(__VAX)
       if (efs_hack && (decc_efs_charset_index > 0)) {
           decc$feature_set_value(decc_efs_charset, 1, 0);
@@ -12889,7 +12379,6 @@ Perl_flex_stat_int(pTHX_ const char *fspec, Stat_t *statbufp, int lstat_flag)
       VMS_INO_T_COPY(statbufp->st_ino, statbufp->crtl_stat.st_ino);
       VMS_DEVICE_ENCODE
        (statbufp->st_dev, statbufp->st_devnam, statbufp->crtl_stat.st_dev);
-#     ifdef RTL_USES_UTC
 #     ifdef VMSISH_TIME
       if (VMSISH_TIME) {
         statbufp->st_mtime = _toloc(statbufp->st_mtime);
@@ -12897,20 +12386,13 @@ Perl_flex_stat_int(pTHX_ const char *fspec, Stat_t *statbufp, int lstat_flag)
         statbufp->st_ctime = _toloc(statbufp->st_ctime);
       }
 #     endif
-#     else
-#     ifdef VMSISH_TIME
-      if (!VMSISH_TIME) { /* Return UTC instead of local time */
-#     else
-      if (1) {
-#     endif
-        statbufp->st_mtime = _toutc(statbufp->st_mtime);
-        statbufp->st_atime = _toutc(statbufp->st_atime);
-        statbufp->st_ctime = _toutc(statbufp->st_ctime);
-      }
-#     endif
     }
     /* If we were successful, leave errno where we found it */
     if (retval == 0) RESTORE_ERRNO;
+    if (temp_fspec)
+        PerlMem_free(temp_fspec);
+    if (fileified)
+        PerlMem_free(fileified);
     return retval;
 
 }  /* end of flex_stat_int() */
@@ -12974,7 +12456,7 @@ Perl_rmscopy(pTHX_ const char *spec_in, const char *spec_out, int preserve_dates
 {
     char *vmsin, * vmsout, *esa, *esal, *esa_out, *esal_out,
          *rsa, *rsal, *rsa_out, *rsal_out, *ubf;
-    unsigned long int i, sts, sts2;
+    unsigned long int sts;
     int dna_len;
     struct FAB fab_in, fab_out;
     struct RAB rab_in, rab_out;
@@ -12985,9 +12467,9 @@ Perl_rmscopy(pTHX_ const char *spec_in, const char *spec_out, int preserve_dates
     struct XABRDT xabrdt;
     struct XABSUM xabsum;
 
-    vmsin = PerlMem_malloc(VMS_MAXRSS);
+    vmsin = (char *)PerlMem_malloc(VMS_MAXRSS);
     if (vmsin == NULL) _ckvmssts_noperl(SS$_INSFMEM);
-    vmsout = PerlMem_malloc(VMS_MAXRSS);
+    vmsout = (char *)PerlMem_malloc(VMS_MAXRSS);
     if (vmsout == NULL) _ckvmssts_noperl(SS$_INSFMEM);
     if (!spec_in  || !*spec_in  || !int_tovmsspec(spec_in, vmsin, 1, NULL) ||
         !spec_out || !*spec_out || !int_tovmsspec(spec_out, vmsout, 1, NULL)) {
@@ -12997,11 +12479,11 @@ Perl_rmscopy(pTHX_ const char *spec_in, const char *spec_out, int preserve_dates
       return 0;
     }
 
-    esa = PerlMem_malloc(VMS_MAXRSS);
+    esa = (char *)PerlMem_malloc(VMS_MAXRSS);
     if (esa == NULL) _ckvmssts_noperl(SS$_INSFMEM);
     esal = NULL;
 #if !defined(__VAX) && defined(NAML$C_MAXRSS)
-    esal = PerlMem_malloc(VMS_MAXRSS);
+    esal = (char *)PerlMem_malloc(VMS_MAXRSS);
     if (esal == NULL) _ckvmssts_noperl(SS$_INSFMEM);
 #endif
     fab_in = cc$rms_fab;
@@ -13012,11 +12494,11 @@ Perl_rmscopy(pTHX_ const char *spec_in, const char *spec_out, int preserve_dates
     rms_bind_fab_nam(fab_in, nam);
     fab_in.fab$l_xab = (void *) &xabdat;
 
-    rsa = PerlMem_malloc(VMS_MAXRSS);
+    rsa = (char *)PerlMem_malloc(VMS_MAXRSS);
     if (rsa == NULL) _ckvmssts_noperl(SS$_INSFMEM);
     rsal = NULL;
 #if !defined(__VAX) && defined(NAML$C_MAXRSS)
-    rsal = PerlMem_malloc(VMS_MAXRSS);
+    rsal = (char *)PerlMem_malloc(VMS_MAXRSS);
     if (rsal == NULL) _ckvmssts_noperl(SS$_INSFMEM);
 #endif
     rms_set_rsal(nam, rsa, NAM$C_MAXRSS, rsal, (VMS_MAXRSS - 1));
@@ -13075,16 +12557,16 @@ Perl_rmscopy(pTHX_ const char *spec_in, const char *spec_out, int preserve_dates
     rms_set_fna(fab_out, nam_out, vmsout, strlen(vmsout));
     dna_len = rms_nam_namel(nam) ? rms_nam_name_type_l_size(nam) : 0;
     rms_set_dna(fab_out, nam_out, rms_nam_namel(nam), dna_len);
-    esa_out = PerlMem_malloc(NAM$C_MAXRSS + 1);
+    esa_out = (char *)PerlMem_malloc(NAM$C_MAXRSS + 1);
     if (esa_out == NULL) _ckvmssts_noperl(SS$_INSFMEM);
-    rsa_out = PerlMem_malloc(NAM$C_MAXRSS + 1);
+    rsa_out = (char *)PerlMem_malloc(NAM$C_MAXRSS + 1);
     if (rsa_out == NULL) _ckvmssts_noperl(SS$_INSFMEM);
     esal_out = NULL;
     rsal_out = NULL;
 #if !defined(__VAX) && defined(NAML$C_MAXRSS)
-    esal_out = PerlMem_malloc(VMS_MAXRSS);
+    esal_out = (char *)PerlMem_malloc(VMS_MAXRSS);
     if (esal_out == NULL) _ckvmssts_noperl(SS$_INSFMEM);
-    rsal_out = PerlMem_malloc(VMS_MAXRSS);
+    rsal_out = (char *)PerlMem_malloc(VMS_MAXRSS);
     if (rsal_out == NULL) _ckvmssts_noperl(SS$_INSFMEM);
 #endif
     rms_set_rsal(nam_out, rsa_out, NAM$C_MAXRSS, rsal_out, (VMS_MAXRSS - 1));
@@ -13166,7 +12648,7 @@ Perl_rmscopy(pTHX_ const char *spec_in, const char *spec_out, int preserve_dates
       fab_out.fab$l_xab = (void *) &xabrdt;
     }
 
-    ubf = PerlMem_malloc(32256);
+    ubf = (char *)PerlMem_malloc(32256);
     if (ubf == NULL) _ckvmssts_noperl(SS$_INSFMEM);
     rab_in = cc$rms_rab;
     rab_in.rab$l_fab = &fab_in;
@@ -13454,7 +12936,7 @@ candelete_fromperl(pTHX_ CV *cv)
   mysv = SvROK(ST(0)) ? SvRV(ST(0)) : ST(0);
   Newx(fspec, VMS_MAXRSS, char);
   if (fspec == NULL) _ckvmssts(SS$_INSFMEM);
-  if (SvTYPE(mysv) == SVt_PVGV) {
+  if (isGV_with_GP(mysv)) {
     if (!(io = GvIOp(mysv)) || !PerlIO_getname(IoIFP(io),fspec)) {
       set_errno(EINVAL); set_vaxc_errno(LIB$_INVARG);
       ST(0) = &PL_sv_no;
@@ -13483,9 +12965,6 @@ rmscopy_fromperl(pTHX_ CV *cv)
   dXSARGS;
   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};
-  unsigned long int sts;
   SV *mysv;
   IO *io;
   STRLEN n_a;
@@ -13495,7 +12974,7 @@ rmscopy_fromperl(pTHX_ CV *cv)
 
   mysv = SvROK(ST(0)) ? SvRV(ST(0)) : ST(0);
   Newx(inspec, VMS_MAXRSS, char);
-  if (SvTYPE(mysv) == SVt_PVGV) {
+  if (isGV_with_GP(mysv)) {
     if (!(io = GvIOp(mysv)) || !PerlIO_getname(IoIFP(io),inspec)) {
       set_errno(EINVAL); set_vaxc_errno(LIB$_INVARG);
       ST(0) = sv_2mortal(newSViv(0));
@@ -13514,7 +12993,7 @@ rmscopy_fromperl(pTHX_ CV *cv)
   }
   mysv = SvROK(ST(1)) ? SvRV(ST(1)) : ST(1);
   Newx(outspec, VMS_MAXRSS, char);
-  if (SvTYPE(mysv) == SVt_PVGV) {
+  if (isGV_with_GP(mysv)) {
     if (!(io = GvIOp(mysv)) || !PerlIO_getname(IoIFP(io),outspec)) {
       set_errno(EINVAL); set_vaxc_errno(LIB$_INVARG);
       ST(0) = sv_2mortal(newSViv(0));
@@ -13550,12 +13029,12 @@ mod2fname(pTHX_ CV *cv)
   dXSARGS;
   char ultimate_name[NAM$C_MAXRSS+1], work_name[NAM$C_MAXRSS*8 + 1],
        workbuff[NAM$C_MAXRSS*1 + 1];
-  int total_namelen = 3, counter, num_entries;
+  SSize_t counter, num_entries;
   /* ODS-5 ups this, but we want to be consistent, so... */
   int max_name_len = 39;
   AV *in_array = (AV *)SvRV(ST(0));
 
-  num_entries = av_len(in_array);
+  num_entries = av_tindex(in_array);
 
   /* All the names start with PL_. */
   strcpy(ultimate_name, "PL_");
@@ -13567,14 +13046,14 @@ mod2fname(pTHX_ CV *cv)
   for(counter = 0; counter <= num_entries; counter++) {
     /* If it's not the first name then tack on a __ */
     if (counter) {
-      strcat(work_name, "__");
+      my_strlcat(work_name, "__", sizeof(work_name));
     }
-    strcat(work_name, SvPV_nolen(*av_fetch(in_array, counter, FALSE)));
+    my_strlcat(work_name, SvPV_nolen(*av_fetch(in_array, counter, FALSE)), sizeof(work_name));
   }
 
   /* Check to see if we actually have to bother...*/
   if (strlen(work_name) + 3 <= max_name_len) {
-    strcat(ultimate_name, work_name);
+    my_strlcat(ultimate_name, work_name, sizeof(ultimate_name));
   } else {
     /* It's too darned big, so we need to go strip. We use the same */
     /* algorithm as xsubpp does. First, strip out doubled __ */
@@ -13589,7 +13068,7 @@ mod2fname(pTHX_ CV *cv)
       last = *source;
     }
     /* Go put it back */
-    strcpy(work_name, workbuff);
+    my_strlcpy(work_name, workbuff, sizeof(work_name));
     /* Is it still too big? */
     if (strlen(work_name) + 3 > max_name_len) {
       /* Strip duplicate letters */
@@ -13602,7 +13081,7 @@ mod2fname(pTHX_ CV *cv)
        *dest++ = *source;
        last = toupper(*source);
       }
-      strcpy(work_name, workbuff);
+      my_strlcpy(work_name, workbuff, sizeof(work_name));
     }
 
     /* Is it *still* too big? */
@@ -13610,7 +13089,7 @@ mod2fname(pTHX_ CV *cv)
       /* Too bad, we truncate */
       work_name[max_name_len - 2] = 0;
     }
-    strcat(ultimate_name, work_name);
+    my_strlcat(ultimate_name, work_name, sizeof(ultimate_name));
   }
 
   /* Okay, return it */
@@ -13632,9 +13111,7 @@ hushexit_fromperl(pTHX_ CV *cv)
 
 
 PerlIO * 
-Perl_vms_start_glob
-   (pTHX_ SV *tmpglob,
-    IO *io)
+Perl_vms_start_glob(pTHX_ SV *tmpglob, IO *io)
 {
     PerlIO *fp;
     struct vs_str_st *rslt;
@@ -13725,7 +13202,7 @@ Perl_vms_start_glob
 
             /* Test to see if SvPVX_const(tmpglob) ends with a VMS */
             /* path delimiter of ':>]', if so, then the old behavior has */
-            /* obviously been specificially requested */
+            /* obviously been specifically requested */
 
             fname = SvPVX_const(tmpglob);
             fname_len = strlen(fname);
@@ -13757,7 +13234,7 @@ Perl_vms_start_glob
        for (cp=wilddsc.dsc$a_pointer; ok && cp && *cp; cp++) {
            if (*cp == '?') {
                 wildquery = 1;
-                if (!decc_efs_case_preserve)
+                if (!decc_efs_charset)
                     *cp = '%';
             } else if (*cp == '%') {
                 wildquery = 1;
@@ -13819,7 +13296,7 @@ Perl_vms_start_glob
 
                 /* In Unix report mode, remove the ".dir;1" from the name */
                 /* if it is a real directory */
-                if (decc_filename_unix_report || decc_efs_charset) {
+                if (decc_filename_unix_report && decc_efs_charset) {
                     if (is_dir_ext(e_spec, e_len, vs_spec, vs_len)) {
                         Stat_t statbuf;
                         int ret_sts;
@@ -13888,7 +13365,7 @@ Perl_vms_start_glob
 
        if (!found) {
            /* Be POSIXish: return the input pattern when no matches */
-           strcpy(rstr,SvPVX(tmpglob));
+           my_strlcpy(rstr, SvPVX(tmpglob), VMS_MAXRSS);
            strcat(rstr,"\n");
            ok = (PerlIO_puts(tmpfp,rstr) != EOF);
        }
@@ -13974,42 +13451,28 @@ vmsrealpath_fromperl(pTHX_ CV *cv)
 #ifdef HAS_SYMLINK
 /*
  * A thin wrapper around decc$symlink to make sure we follow the 
- * standard and do not create a symlink with a zero-length name.
- *
- * Also in ODS-2 mode, existing tests assume that the link target
- * will be converted to UNIX format.
+ * standard and do not create a symlink with a zero-length name,
+ * and convert the target to Unix format, as the CRTL can't handle
+ * targets in VMS format.
  */
 /*{{{ int my_symlink(pTHX_ const char *contents, const char *link_name)*/
-int Perl_my_symlink(pTHX_ const char *contents, const char *link_name) {
-  if (!link_name || !*link_name) {
-    SETERRNO(ENOENT, SS$_NOSUCHFILE);
-    return -1;
-  }
-
-  if (decc_efs_charset) {
-      return symlink(contents, link_name);
-  } else {
-      int sts;
-      char * utarget;
-
-      /* Unless we are in ODS-5 mode, convert the symlink target to UNIX */
-      /* because in order to work, the symlink target must be in UNIX format */
-
-      /* As symbolic links can hold things other than files, we will only do */
-      /* the conversion in in ODS-2 mode */
-
-      utarget = PerlMem_malloc(VMS_MAXRSS + 1);
-      if (int_tounixspec(contents, utarget, NULL) == NULL) {
+int
+Perl_my_symlink(pTHX_ const char *contents, const char *link_name)
+{
+    int sts;
+    char * utarget;
 
-          /* This should not fail, as an untranslatable filename */
-          /* should be passed through */
-          utarget = (char *)contents;
-      }
-      sts = symlink(utarget, link_name);
-      PerlMem_free(utarget);
-      return sts;
-  }
+    if (!link_name || !*link_name) {
+      SETERRNO(ENOENT, SS$_NOSUCHFILE);
+      return -1;
+    }
 
+    utarget = (char *)PerlMem_malloc(VMS_MAXRSS + 1);
+    /* An untranslatable filename should be passed through. */
+    (void) int_tounixspec(contents, utarget, NULL);
+    sts = symlink(utarget, link_name);
+    PerlMem_free(utarget);
+    return sts;
 }
 /*}}}*/
 
@@ -14100,6 +13563,10 @@ char *realpath(const char *file_name, char * resolved_name, ...);
  * on OpenVMS.
  */
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* Hack, use old stat() as fastest way of getting ino_t and device */
 int decc$stat(const char *name, void * statbuf);
 #if !defined(__VAX) && __CRTL_VER >= 80200000
@@ -14108,6 +13575,10 @@ int decc$lstat(const char *name, void * statbuf);
 #define decc$lstat decc$stat
 #endif
 
+#ifdef __cplusplus
+}
+#endif
+
 
 /* Realpath is fragile.  In 8.3 it does not work if the feature
  * DECC$POSIX_COMPLIANT_PATHNAMES is not enabled, even though symbolic
@@ -14125,12 +13596,12 @@ int vms_fid_to_name(char * outname, int outlen,
 #pragma message disable MISALGNDMEM
 #pragma member_alignment save
 #pragma nomember_alignment
-struct statbuf_t {
-    char          * st_dev;
-    unsigned short st_ino[3];
-    unsigned short old_st_mode;
-    unsigned long  padl[30];  /* plenty of room */
-} statbuf;
+    struct statbuf_t {
+        char      * st_dev;
+        unsigned short st_ino[3];
+        unsigned short old_st_mode;
+        unsigned long  padl[30];  /* plenty of room */
+    } statbuf;
 #pragma message restore
 #pragma member_alignment restore
 
@@ -14145,11 +13616,11 @@ struct statbuf_t {
      * unexpected answers
      */
 
-    fileified = PerlMem_malloc(VMS_MAXRSS);
+    fileified = (char *)PerlMem_malloc(VMS_MAXRSS);
     if (fileified == NULL)
         _ckvmssts_noperl(SS$_INSFMEM);
      
-    temp_fspec = PerlMem_malloc(VMS_MAXRSS);
+    temp_fspec = (char *)PerlMem_malloc(VMS_MAXRSS);
     if (temp_fspec == NULL)
         _ckvmssts_noperl(SS$_INSFMEM);
 
@@ -14230,9 +13701,10 @@ struct statbuf_t {
             if (mode) {
                 *mode = statbuf.old_st_mode;
             }
-           return 0;
        }
     }
+    PerlMem_free(temp_fspec);
+    PerlMem_free(fileified);
     return sts;
 }
 
@@ -14258,7 +13730,6 @@ mp_do_vms_realpath(pTHX_ const char *filespec, char *outbuf,
         char * vms_spec;
         char * v_spec, * r_spec, * d_spec, * n_spec, * e_spec, * vs_spec;
         int sts, v_len, r_len, d_len, n_len, e_len, vs_len;
-        int file_len;
         mode_t my_mode;
 
        /* Fall back to fid_to_name */
@@ -14324,7 +13795,7 @@ mp_do_vms_realpath(pTHX_ const char *filespec, char *outbuf,
        } else {
 
            /* Now for some hacks to deal with backwards and forward */
-           /* compatibilty */
+           /* compatibility */
            if (!decc_efs_charset) {
 
                /* 1. ODS-2 mode wants to do a syntax only translation */
@@ -14340,7 +13811,7 @@ mp_do_vms_realpath(pTHX_ const char *filespec, char *outbuf,
                    /* 2. ODS-5 / UNIX report mode should return a failure */
                    /*    if the parent directory also does not exist */
                    /*    Otherwise, get the real path for the parent */
-                   /*    and add the child to it.
+                   /*    and add the child to it. */
 
                    /* basename / dirname only available for VMS 7.0+ */
                    /* So we may need to implement them as common routines */
@@ -14371,7 +13842,7 @@ mp_do_vms_realpath(pTHX_ const char *filespec, char *outbuf,
 
                        int dir_len = v_len + r_len + d_len + n_len;
                        if (dir_len > 0) {
-                          strncpy(dir_name, filespec, dir_len);
+                          memcpy(dir_name, filespec, dir_len);
                           dir_name[dir_len] = '\0';
                           file_name = (char *)&filespec[dir_len + 1];
                        }
@@ -14383,7 +13854,7 @@ mp_do_vms_realpath(pTHX_ const char *filespec, char *outbuf,
 
                        if (tchar != NULL) {
                            int dir_len = tchar - filespec;
-                           strncpy(dir_name, filespec, dir_len);
+                           memcpy(dir_name, filespec, dir_len);
                            dir_name[dir_len] = '\0';
                            file_name = (char *) &filespec[dir_len + 1];
                        }
@@ -14401,13 +13872,13 @@ mp_do_vms_realpath(pTHX_ const char *filespec, char *outbuf,
                                          dir_name, 0, NULL);
 
                    if (sts == 0) {
-                       /* Now need to pathify it.
+                       /* Now need to pathify it. */
                        char *tdir = int_pathify_dirspec(vms_dir_name,
                                                         outbuf);
 
                        /* And now add the original filespec to it */
                        if (file_name != NULL) {
-                           strcat(outbuf, file_name);
+                           my_strlcat(outbuf, file_name, VMS_MAXRSS);
                        }
                        return outbuf;
                    }
@@ -14427,7 +13898,6 @@ mp_do_vms_realname(pTHX_ const char *filespec, char *outbuf,
 {
     char * v_spec, * r_spec, * d_spec, * n_spec, * e_spec, * vs_spec;
     int sts, v_len, r_len, d_len, n_len, e_len, vs_len;
-    int file_len;
 
     /* Fall back to fid_to_name */
 
@@ -14480,11 +13950,17 @@ mp_do_vms_realname(pTHX_ const char *filespec, char *outbuf,
 
 /*}}}*/
 /* External entry points */
-char *Perl_vms_realpath(pTHX_ const char *filespec, char *outbuf, int *utf8_fl)
-{ return do_vms_realpath(filespec, outbuf, utf8_fl); }
+char *
+Perl_vms_realpath(pTHX_ const char *filespec, char *outbuf, int *utf8_fl)
+{
+    return do_vms_realpath(filespec, outbuf, utf8_fl);
+}
 
-char *Perl_vms_realname(pTHX_ const char *filespec, char *outbuf, int *utf8_fl)
-{ return do_vms_realname(filespec, outbuf, utf8_fl); }
+char *
+Perl_vms_realname(pTHX_ const char *filespec, char *outbuf, int *utf8_fl)
+{
+    return do_vms_realname(filespec, outbuf, utf8_fl);
+}
 
 /* case_tolerant */
 
@@ -14492,101 +13968,81 @@ char *Perl_vms_realname(pTHX_ const char *filespec, char *outbuf, int *utf8_fl)
 /* OpenVMS provides a case sensitive implementation of ODS-5 and this is
  * controlled by a process setting.
  */
-int do_vms_case_tolerant(void)
+int
+do_vms_case_tolerant(void)
 {
     return vms_process_case_tolerant;
 }
 /*}}}*/
 /* External entry points */
+int
+Perl_vms_case_tolerant(void)
+{
 #if __CRTL_VER >= 70301000 && !defined(__VAX)
-int Perl_vms_case_tolerant(void)
-{ return do_vms_case_tolerant(); }
+    return do_vms_case_tolerant();
 #else
-int Perl_vms_case_tolerant(void)
-{ return vms_process_case_tolerant; }
+    return vms_process_case_tolerant;
 #endif
-
+}
 
  /* Start of DECC RTL Feature handling */
 
-static int sys_trnlnm
-   (const char * logname,
-    char * value,
-    int value_len)
+#if __CRTL_VER >= 70300000 && !defined(__VAX)
+
+static int
+set_feature_default(const char *name, int value)
 {
-    const $DESCRIPTOR(table_dsc, "LNM$FILE_DEV");
-    const unsigned long attr = LNM$M_CASE_BLIND;
-    struct dsc$descriptor_s name_dsc;
     int status;
-    unsigned short result;
-    struct itmlst_3 itlst[2] = {{value_len, LNM$_STRING, value, &result},
-                                {0, 0, 0, 0}};
-
-    name_dsc.dsc$w_length = strlen(logname);
-    name_dsc.dsc$a_pointer = (char *)logname;
-    name_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
-    name_dsc.dsc$b_class = DSC$K_CLASS_S;
+    int index;
+    char val_str[10];
 
-    status = sys$trnlnm(&attr, &table_dsc, &name_dsc, 0, itlst);
+    /* If the feature has been explicitly disabled in the environment,
+     * then don't enable it here.
+     */
+    if (value > 0) {
+        status = simple_trnlnm(name, val_str, sizeof(val_str));
+        if (status) {
+            val_str[0] = _toupper(val_str[0]);
+            if (val_str[0] == 'D' || val_str[0] == '0' || val_str[0] == 'F')
+               return 0;
+        }
+    }
 
-    if ($VMS_STATUS_SUCCESS(status)) {
+    index = decc$feature_get_index(name);
 
-        /* Null terminate and return the string */
-       /*--------------------------------------*/
-       value[result] = 0;
+    status = decc$feature_set_value(index, 1, value);
+    if (index == -1 || (status == -1)) {
+      return -1;
     }
 
-    return status;
-}
+    status = decc$feature_get_value(index, 1);
+    if (status != value) {
+      return -1;
+    }
 
-static int sys_crelnm
-   (const char * logname,
-    const char * value)
-{
-    int ret_val;
-    const char * proc_table = "LNM$PROCESS_TABLE";
-    struct dsc$descriptor_s proc_table_dsc;
-    struct dsc$descriptor_s logname_dsc;
-    struct itmlst_3 item_list[2];
-
-    proc_table_dsc.dsc$a_pointer = (char *) proc_table;
-    proc_table_dsc.dsc$w_length = strlen(proc_table);
-    proc_table_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
-    proc_table_dsc.dsc$b_class = DSC$K_CLASS_S;
-
-    logname_dsc.dsc$a_pointer = (char *) logname;
-    logname_dsc.dsc$w_length = strlen(logname);
-    logname_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
-    logname_dsc.dsc$b_class = DSC$K_CLASS_S;
-
-    item_list[0].buflen = strlen(value);
-    item_list[0].itmcode = LNM$_STRING;
-    item_list[0].bufadr = (char *)value;
-    item_list[0].retlen = NULL;
-
-    item_list[1].buflen = 0;
-    item_list[1].itmcode = 0;
-
-    ret_val = sys$crelnm
-                      (NULL,
-                       (const struct dsc$descriptor_s *)&proc_table_dsc,
-                       (const struct dsc$descriptor_s *)&logname_dsc,
-                       NULL,
-                       (const struct item_list_3 *) item_list);
+    /* Various things may check for an environment setting
+     * rather than the feature directly, so set that too.
+     */
+    vmssetuserlnm(name, value ? "ENABLE" : "DISABLE");
 
-    return ret_val;
+    return 0;
 }
+#endif
+
 
 /* C RTL Feature settings */
 
-static int set_features
-   (int (* init_coroutine)(int *, int *, void *),  /* Needs casts if used */
-    int (* cli_routine)(void), /* Not documented */
-    void *image_info)          /* Not documented */
+#if defined(__DECC) || defined(__DECCXX)
+
+#ifdef __cplusplus 
+extern "C" { 
+#endif 
+extern void
+vmsperl_set_features(void)
 {
     int status;
     int s;
-    char* str;
     char val_str[10];
 #if defined(JPI$_CASE_LOOKUP_PERM) && !defined(__VAX)
     const unsigned long int jpicode1 = JPI$_CASE_LOOKUP_PERM;
@@ -14597,8 +14053,8 @@ static int set_features
 
     /* Allow an exception to bring Perl into the VMS debugger */
     vms_debug_on_exception = 0;
-    status = sys_trnlnm("PERL_VMS_EXCEPTION_DEBUG", val_str, sizeof(val_str));
-    if ($VMS_STATUS_SUCCESS(status)) {
+    status = simple_trnlnm("PERL_VMS_EXCEPTION_DEBUG", val_str, sizeof(val_str));
+    if (status) {
        val_str[0] = _toupper(val_str[0]);
        if ((val_str[0] == 'E') || (val_str[0] == '1') || (val_str[0] == 'T'))
         vms_debug_on_exception = 1;
@@ -14608,8 +14064,8 @@ static int set_features
 
     /* Debug unix/vms file translation routines */
     vms_debug_fileify = 0;
-    status = sys_trnlnm("PERL_VMS_FILEIFY_DEBUG", val_str, sizeof(val_str));
-    if ($VMS_STATUS_SUCCESS(status)) {
+    status = simple_trnlnm("PERL_VMS_FILEIFY_DEBUG", val_str, sizeof(val_str));
+    if (status) {
        val_str[0] = _toupper(val_str[0]);
         if ((val_str[0] == 'E') || (val_str[0] == '1') || (val_str[0] == 'T'))
            vms_debug_fileify = 1;
@@ -14628,8 +14084,8 @@ static int set_features
     /* This should really be fixed, but for now, set up a feature to    */
     /* enable it so that the impact can be studied.                     */
     vms_bug_stat_filename = 0;
-    status = sys_trnlnm("PERL_VMS_BUG_STAT_FILENAME", val_str, sizeof(val_str));
-    if ($VMS_STATUS_SUCCESS(status)) {
+    status = simple_trnlnm("PERL_VMS_BUG_STAT_FILENAME", val_str, sizeof(val_str));
+    if (status) {
        val_str[0] = _toupper(val_str[0]);
         if ((val_str[0] == 'E') || (val_str[0] == '1') || (val_str[0] == 'T'))
            vms_bug_stat_filename = 1;
@@ -14640,8 +14096,8 @@ static int set_features
 
     /* Create VTF-7 filenames from Unicode instead of UTF-8 */
     vms_vtf7_filenames = 0;
-    status = sys_trnlnm("PERL_VMS_VTF7_FILENAMES", val_str, sizeof(val_str));
-    if ($VMS_STATUS_SUCCESS(status)) {
+    status = simple_trnlnm("PERL_VMS_VTF7_FILENAMES", val_str, sizeof(val_str));
+    if (status) {
        val_str[0] = _toupper(val_str[0]);
        if ((val_str[0] == 'E') || (val_str[0] == '1') || (val_str[0] == 'T'))
         vms_vtf7_filenames = 1;
@@ -14651,9 +14107,8 @@ static int set_features
 
     /* unlink all versions on unlink() or rename() */
     vms_unlink_all_versions = 0;
-    status = sys_trnlnm
-       ("PERL_VMS_UNLINK_ALL_VERSIONS", val_str, sizeof(val_str));
-    if ($VMS_STATUS_SUCCESS(status)) {
+    status = simple_trnlnm("PERL_VMS_UNLINK_ALL_VERSIONS", val_str, sizeof(val_str));
+    if (status) {
        val_str[0] = _toupper(val_str[0]);
        if ((val_str[0] == 'E') || (val_str[0] == '1') || (val_str[0] == 'T'))
         vms_unlink_all_versions = 1;
@@ -14661,29 +14116,34 @@ static int set_features
         vms_unlink_all_versions = 0;
     }
 
-    /* Dectect running under GNV Bash or other UNIX like shell */
 #if __CRTL_VER >= 70300000 && !defined(__VAX)
+    /* Detect running under GNV Bash or other UNIX like shell */
     gnv_unix_shell = 0;
-    status = sys_trnlnm("GNV$UNIX_SHELL", val_str, sizeof(val_str));
-    if ($VMS_STATUS_SUCCESS(status)) {
+    status = simple_trnlnm("GNV$UNIX_SHELL", val_str, sizeof(val_str));
+    if (status) {
         gnv_unix_shell = 1;
-        set_feature_default("DECC$EFS_CASE_PRESERVE", 1);
-        set_feature_default("DECC$EFS_CHARSET", 1);
         set_feature_default("DECC$FILENAME_UNIX_NO_VERSION", 1);
         set_feature_default("DECC$FILENAME_UNIX_REPORT", 1);
         set_feature_default("DECC$READDIR_DROPDOTNOTYPE", 1);
         set_feature_default("DECC$DISABLE_POSIX_ROOT", 0);
         vms_unlink_all_versions = 1;
         vms_posix_exit = 1;
+        /* Reverse default ordering of PERL_ENV_TABLES. */
+        defenv[0] = &crtlenvdsc;
+        defenv[1] = &fildevdsc;
     }
+    /* Some reasonable defaults that are not CRTL defaults */
+    set_feature_default("DECC$EFS_CASE_PRESERVE", 1);
+    set_feature_default("DECC$ARGV_PARSE_STYLE", 1);     /* Requires extended parse. */
+    set_feature_default("DECC$EFS_CHARSET", 1);
 #endif
 
     /* hacks to see if known bugs are still present for testing */
 
     /* PCP mode requires creating /dev/null special device file */
     decc_bug_devnull = 0;
-    status = sys_trnlnm("DECC_BUG_DEVNULL", val_str, sizeof(val_str));
-    if ($VMS_STATUS_SUCCESS(status)) {
+    status = simple_trnlnm("DECC_BUG_DEVNULL", val_str, sizeof(val_str));
+    if (status) {
        val_str[0] = _toupper(val_str[0]);
        if ((val_str[0] == 'E') || (val_str[0] == '1') || (val_str[0] == 'T'))
           decc_bug_devnull = 1;
@@ -14691,17 +14151,6 @@ static int set_features
          decc_bug_devnull = 0;
     }
 
-    /* UNIX directory names with no paths are broken in a lot of places */
-    decc_dir_barename = 1;
-    status = sys_trnlnm("DECC_DIR_BARENAME", val_str, sizeof(val_str));
-    if ($VMS_STATUS_SUCCESS(status)) {
-      val_str[0] = _toupper(val_str[0]);
-      if ((val_str[0] == 'E') || (val_str[0] == '1') || (val_str[0] == 'T'))
-       decc_dir_barename = 1;
-      else
-       decc_dir_barename = 0;
-    }
-
 #if __CRTL_VER >= 70300000 && !defined(__VAX)
     s = decc$feature_get_index("DECC$DISABLE_TO_VMS_LOGNAME_TRANSLATION");
     if (s >= 0) {
@@ -14773,9 +14222,9 @@ static int set_features
 
 #endif
 #else
-    status = sys_trnlnm
+    status = simple_trnlnm
        ("DECC$DISABLE_TO_VMS_LOGNAME_TRANSLATION", val_str, sizeof(val_str));
-    if ($VMS_STATUS_SUCCESS(status)) {
+    if (status) {
        val_str[0] = _toupper(val_str[0]);
        if ((val_str[0] == 'E') || (val_str[0] == '1') || (val_str[0] == 'T')) {
           decc_disable_to_vms_logname_translation = 1;
@@ -14783,8 +14232,8 @@ static int set_features
     }
 
 #ifndef __VAX
-    status = sys_trnlnm("DECC$EFS_CASE_PRESERVE", val_str, sizeof(val_str));
-    if ($VMS_STATUS_SUCCESS(status)) {
+    status = simple_trnlnm("DECC$EFS_CASE_PRESERVE", val_str, sizeof(val_str));
+    if (status) {
        val_str[0] = _toupper(val_str[0]);
        if ((val_str[0] == 'E') || (val_str[0] == '1') || (val_str[0] == 'T')) {
           decc_efs_case_preserve = 1;
@@ -14792,30 +14241,30 @@ static int set_features
     }
 #endif
 
-    status = sys_trnlnm("DECC$FILENAME_UNIX_REPORT", val_str, sizeof(val_str));
-    if ($VMS_STATUS_SUCCESS(status)) {
+    status = simple_trnlnm("DECC$FILENAME_UNIX_REPORT", val_str, sizeof(val_str));
+    if (status) {
        val_str[0] = _toupper(val_str[0]);
        if ((val_str[0] == 'E') || (val_str[0] == '1') || (val_str[0] == 'T')) {
           decc_filename_unix_report = 1;
        }
     }
-    status = sys_trnlnm("DECC$FILENAME_UNIX_ONLY", val_str, sizeof(val_str));
-    if ($VMS_STATUS_SUCCESS(status)) {
+    status = simple_trnlnm("DECC$FILENAME_UNIX_ONLY", val_str, sizeof(val_str));
+    if (status) {
        val_str[0] = _toupper(val_str[0]);
        if ((val_str[0] == 'E') || (val_str[0] == '1') || (val_str[0] == 'T')) {
           decc_filename_unix_only = 1;
           decc_filename_unix_report = 1;
        }
     }
-    status = sys_trnlnm("DECC$FILENAME_UNIX_NO_VERSION", val_str, sizeof(val_str));
-    if ($VMS_STATUS_SUCCESS(status)) {
+    status = simple_trnlnm("DECC$FILENAME_UNIX_NO_VERSION", val_str, sizeof(val_str));
+    if (status) {
        val_str[0] = _toupper(val_str[0]);
        if ((val_str[0] == 'E') || (val_str[0] == '1') || (val_str[0] == 'T')) {
           decc_filename_unix_no_version = 1;
        }
     }
-    status = sys_trnlnm("DECC$READDIR_DROPDOTNOTYPE", val_str, sizeof(val_str));
-    if ($VMS_STATUS_SUCCESS(status)) {
+    status = simple_trnlnm("DECC$READDIR_DROPDOTNOTYPE", val_str, sizeof(val_str));
+    if (status) {
        val_str[0] = _toupper(val_str[0]);
        if ((val_str[0] == 'E') || (val_str[0] == '1') || (val_str[0] == 'T')) {
           decc_readdir_dropdotnotype = 1;
@@ -14840,54 +14289,47 @@ static int set_features
 #endif
 
     /* USE POSIX/DCL Exit codes - Recommended, but needs to default to  */
-    /* for strict backward compatibilty */
-    status = sys_trnlnm
-       ("PERL_VMS_POSIX_EXIT", val_str, sizeof(val_str));
-    if ($VMS_STATUS_SUCCESS(status)) {
+    /* for strict backward compatibility */
+    status = simple_trnlnm("PERL_VMS_POSIX_EXIT", val_str, sizeof(val_str));
+    if (status) {
        val_str[0] = _toupper(val_str[0]);
        if ((val_str[0] == 'E') || (val_str[0] == '1') || (val_str[0] == 'T'))
         vms_posix_exit = 1;
        else
         vms_posix_exit = 0;
     }
-
-
-    /* CRTL can be initialized past this point, but not before. */
-/*    DECC$CRTL_INIT(); */
-
-    return SS$_NORMAL;
 }
 
-#ifdef __DECC
-#pragma nostandard
-#pragma extern_model save
-#pragma extern_model strict_refdef "LIB$INITIALIZ" nowrt
-       const __align (LONGWORD) int spare[8] = {0};
-
-/* .psect LIB$INITIALIZE, NOPIC, USR, CON, REL, GBL, NOSHR, NOEXE, RD, NOWRT, LONG */
-#if __DECC_VER >= 60560002
-#pragma extern_model strict_refdef "LIB$INITIALIZE" nopic, con, rel, gbl, noshr, noexe, nowrt, long
-#else
-#pragma extern_model strict_refdef "LIB$INITIALIZE" nopic, con, gbl, noshr, nowrt, long
-#endif
-#endif /* __DECC */
-
-const long vms_cc_features = (const long)set_features;
-
-/*
-** Force a reference to LIB$INITIALIZE to ensure it
-** exists in the image.
-*/
-#define lib$initialize LIB$INITIALIZE
-int lib$initialize(void);
-#ifdef __DECC
-#pragma extern_model strict_refdef
-#endif
-    int lib_init_ref = (int) lib$initialize;
-
-#ifdef __DECC
-#pragma extern_model restore
-#pragma standard
+/* Use 32-bit pointers because that's what the image activator
+ * assumes for the LIB$INITIALZE psect.
+ */ 
+#if __INITIAL_POINTER_SIZE 
+#pragma pointer_size save 
+#pragma pointer_size 32 
+#endif 
+/* Create a reference to the LIB$INITIALIZE function. */ 
+extern void LIB$INITIALIZE(void); 
+extern void (*vmsperl_unused_global_1)(void) = LIB$INITIALIZE; 
+/* Create an array of pointers to the init functions in the special 
+ * LIB$INITIALIZE section. In our case, the array only has one entry.
+ */ 
+#pragma extern_model save 
+#pragma extern_model strict_refdef "LIB$INITIALIZE" nopic,gbl,nowrt,noshr,long 
+extern void (* const vmsperl_unused_global_2[])() = 
+{ 
+   vmsperl_set_features,
+}; 
+#pragma extern_model restore 
+#if __INITIAL_POINTER_SIZE 
+#pragma pointer_size restore 
+#endif 
+#ifdef __cplusplus 
+} 
 #endif
 
+#endif /* defined(__DECC) || defined(__DECCXX) */
 /*  End of vms.c */