This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
PATCH for small bug in scan_bin
[perl5.git] / util.c
diff --git a/util.c b/util.c
index 77dd842..d69b084 100644 (file)
--- a/util.c
+++ b/util.c
@@ -1,6 +1,6 @@
 /*    util.c
  *
- *    Copyright (c) 1991-1997, Larry Wall
+ *    Copyright (c) 1991-1999, Larry Wall
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
@@ -62,9 +62,7 @@ long lastxycount[MAXXCOUNT][MAXYCOUNT];
 
 #endif
 
-#ifndef MYMALLOC
-
-/* paranoid version of malloc */
+/* paranoid version of system's malloc() */
 
 /* NOTE:  Do not call the next three routines directly.  Use the macros
  * in handy.h, so that we can easily redefine everything to do tracking of
@@ -73,7 +71,7 @@ long lastxycount[MAXXCOUNT][MAXYCOUNT];
  */
 
 Malloc_t
-safemalloc(MEM_SIZE size)
+safesysmalloc(MEM_SIZE size)
 {
     Malloc_t ptr;
 #ifdef HAS_64K_LIMIT
@@ -104,10 +102,10 @@ safemalloc(MEM_SIZE size)
     /*NOTREACHED*/
 }
 
-/* paranoid version of realloc */
+/* paranoid version of system's realloc() */
 
 Malloc_t
-saferealloc(Malloc_t where,MEM_SIZE size)
+safesysrealloc(Malloc_t where,MEM_SIZE size)
 {
     Malloc_t ptr;
 #if !defined(STANDARD_C) && !defined(HAS_REALLOC_PROTOTYPE)
@@ -122,12 +120,12 @@ saferealloc(Malloc_t where,MEM_SIZE size)
     }
 #endif /* HAS_64K_LIMIT */
     if (!size) {
-       safefree(where);
+       safesysfree(where);
        return NULL;
     }
 
     if (!where)
-       return safemalloc(size);
+       return safesysmalloc(size);
 #ifdef DEBUGGING
     if ((long)size < 0)
        croak("panic: realloc");
@@ -158,10 +156,10 @@ saferealloc(Malloc_t where,MEM_SIZE size)
     /*NOTREACHED*/
 }
 
-/* safe version of free */
+/* safe version of system's free() */
 
 Free_t
-safefree(Malloc_t where)
+safesysfree(Malloc_t where)
 {
 #if !(defined(I286) || defined(atarist))
     DEBUG_m( PerlIO_printf(Perl_debug_log, "0x%x: (%05d) free\n",(char *) where,PL_an++));
@@ -174,10 +172,10 @@ safefree(Malloc_t where)
     }
 }
 
-/* safe version of calloc */
+/* safe version of system's calloc() */
 
 Malloc_t
-safecalloc(MEM_SIZE count, MEM_SIZE size)
+safesyscalloc(MEM_SIZE count, MEM_SIZE size)
 {
     Malloc_t ptr;
 
@@ -213,8 +211,6 @@ safecalloc(MEM_SIZE count, MEM_SIZE size)
     /*NOTREACHED*/
 }
 
-#endif /* !MYMALLOC */
-
 #ifdef LEAKTEST
 
 struct mem_test_strut {
@@ -389,16 +385,16 @@ delimcpy(register char *to, register char *toend, register char *from, register
 /* This routine was donated by Corey Satten. */
 
 char *
-instr(register char *big, register char *little)
+instr(register const char *big, register const char *little)
 {
-    register char *s, *x;
+    register const char *s, *x;
     register I32 first;
 
     if (!little)
-       return big;
+       return (char*)big;
     first = *little++;
     if (!first)
-       return big;
+       return (char*)big;
     while (*big) {
        if (*big++ != first)
            continue;
@@ -411,7 +407,7 @@ instr(register char *big, register char *little)
            }
        }
        if (!*s)
-           return big-1;
+           return (char*)(big-1);
     }
     return Nullch;
 }
@@ -419,14 +415,14 @@ instr(register char *big, register char *little)
 /* same as instr but allow embedded nulls */
 
 char *
-ninstr(register char *big, register char *bigend, char *little, char *lend)
+ninstr(register const char *big, register const char *bigend, const char *little, const char *lend)
 {
-    register char *s, *x;
+    register const char *s, *x;
     register I32 first = *little;
-    register char *littleend = lend;
+    register const char *littleend = lend;
 
     if (!first && little >= littleend)
-       return big;
+       return (char*)big;
     if (bigend - big < littleend - little)
        return Nullch;
     bigend -= littleend - little++;
@@ -440,7 +436,7 @@ ninstr(register char *big, register char *bigend, char *little, char *lend)
            }
        }
        if (s >= littleend)
-           return big-1;
+           return (char*)(big-1);
     }
     return Nullch;
 }
@@ -448,15 +444,15 @@ ninstr(register char *big, register char *bigend, char *little, char *lend)
 /* reverse of the above--find last substring */
 
 char *
-rninstr(register char *big, char *bigend, char *little, char *lend)
+rninstr(register const char *big, const char *bigend, const char *little, const char *lend)
 {
-    register char *bigbeg;
-    register char *s, *x;
+    register const char *bigbeg;
+    register const char *s, *x;
     register I32 first = *little;
-    register char *littleend = lend;
+    register const char *littleend = lend;
 
     if (!first && little >= littleend)
-       return bigend;
+       return (char*)bigend;
     bigbeg = big;
     big = bigend - (littleend - little++);
     while (big >= bigbeg) {
@@ -469,7 +465,7 @@ rninstr(register char *big, char *bigend, char *little, char *lend)
            }
        }
        if (s >= littleend)
-           return big+1;
+           return (char*)(big+1);
     }
     return Nullch;
 }
@@ -478,7 +474,7 @@ rninstr(register char *big, char *bigend, char *little, char *lend)
  * Set up for a new ctype locale.
  */
 void
-perl_new_ctype(char *newctype)
+perl_new_ctype(const char *newctype)
 {
 #ifdef USE_LOCALE_CTYPE
 
@@ -500,7 +496,7 @@ perl_new_ctype(char *newctype)
  * Set up for a new collation locale.
  */
 void
-perl_new_collate(char *newcoll)
+perl_new_collate(const char *newcoll)
 {
 #ifdef USE_LOCALE_COLLATE
 
@@ -544,7 +540,7 @@ perl_new_collate(char *newcoll)
  * Set up for a new numeric locale.
  */
 void
-perl_new_numeric(char *newnum)
+perl_new_numeric(const char *newnum)
 {
 #ifdef USE_LOCALE_NUMERIC
 
@@ -1131,7 +1127,7 @@ screaminstr(SV *bigstr, SV *littlestr, I32 start_shift, I32 end_shift, I32 *old_
 }
 
 I32
-ibcmp(char *s1, char *s2, register I32 len)
+ibcmp(const char *s1, const char *s2, register I32 len)
 {
     register U8 *a = (U8 *)s1;
     register U8 *b = (U8 *)s2;
@@ -1144,7 +1140,7 @@ ibcmp(char *s1, char *s2, register I32 len)
 }
 
 I32
-ibcmp_locale(char *s1, char *s2, register I32 len)
+ibcmp_locale(const char *s1, const char *s2, register I32 len)
 {
     register U8 *a = (U8 *)s1;
     register U8 *b = (U8 *)s2;
@@ -1159,7 +1155,7 @@ ibcmp_locale(char *s1, char *s2, register I32 len)
 /* copy a string to a safe spot */
 
 char *
-savepv(char *sv)
+savepv(const char *sv)
 {
     register char *newaddr;
 
@@ -1171,7 +1167,7 @@ savepv(char *sv)
 /* same thing but with a known length */
 
 char *
-savepvn(char *sv, register I32 len)
+savepvn(const char *sv, register I32 len)
 {
     register char *newaddr;
 
@@ -1217,7 +1213,7 @@ form(const char* pat, ...)
     return SvPVX(sv);
 }
 
-char *
+SV *
 mess(const char *pat, va_list *args)
 {
     SV *sv = mess_alloc();
@@ -1226,24 +1222,20 @@ mess(const char *pat, va_list *args)
     sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*));
     if (!SvCUR(sv) || *(SvEND(sv) - 1) != '\n') {
        dTHR;
-       if (PL_dirty)
-           sv_catpv(sv, dgd);
-       else {
-           if (PL_curcop->cop_line)
-               sv_catpvf(sv, " at %_ line %ld",
-                         GvSV(PL_curcop->cop_filegv), (long)PL_curcop->cop_line);
-           if (GvIO(PL_last_in_gv) && IoLINES(GvIOp(PL_last_in_gv))) {
-               bool line_mode = (RsSIMPLE(PL_rs) &&
-                                 SvLEN(PL_rs) == 1 && *SvPVX(PL_rs) == '\n');
-               sv_catpvf(sv, ", <%s> %s %ld",
-                         PL_last_in_gv == PL_argvgv ? "" : GvNAME(PL_last_in_gv),
-                         line_mode ? "line" : "chunk", 
-                         (long)IoLINES(GvIOp(PL_last_in_gv)));
-           }
-           sv_catpv(sv, ".\n");
+       if (PL_curcop->cop_line)
+           sv_catpvf(sv, " at %_ line %ld",
+                     GvSV(PL_curcop->cop_filegv), (long)PL_curcop->cop_line);
+       if (GvIO(PL_last_in_gv) && IoLINES(GvIOp(PL_last_in_gv))) {
+           bool line_mode = (RsSIMPLE(PL_rs) &&
+                             SvCUR(PL_rs) == 1 && *SvPVX(PL_rs) == '\n');
+           sv_catpvf(sv, ", <%s> %s %ld",
+                     PL_last_in_gv == PL_argvgv ? "" : GvNAME(PL_last_in_gv),
+                     line_mode ? "line" : "chunk", 
+                     (long)IoLINES(GvIOp(PL_last_in_gv)));
        }
+       sv_catpv(sv, PL_dirty ? dgd : ".\n");
     }
-    return SvPVX(sv);
+    return sv;
 }
 
 OP *
@@ -1256,13 +1248,21 @@ die(const char* pat, ...)
     HV *stash;
     GV *gv;
     CV *cv;
+    SV *msv;
+    STRLEN msglen;
 
     DEBUG_S(PerlIO_printf(PerlIO_stderr(),
                          "%p: die: curstack = %p, mainstack = %p\n",
                          thr, PL_curstack, PL_mainstack));
 
     va_start(args, pat);
-    message = pat ? mess(pat, &args) : Nullch;
+    if (pat) {
+       msv = mess(pat, &args);
+       message = SvPV(msv,msglen);
+    }
+    else {
+       message = Nullch;
+    }
     va_end(args);
 
     DEBUG_S(PerlIO_printf(PerlIO_stderr(),
@@ -1281,8 +1281,8 @@ die(const char* pat, ...)
            SV *msg;
 
            ENTER;
-           if(message) {
-               msg = newSVpv(message, 0);
+           if (message) {
+               msg = newSVpvn(message, msglen);
                SvREADONLY_on(msg);
                SAVEFREESV(msg);
            }
@@ -1300,7 +1300,7 @@ die(const char* pat, ...)
        }
     }
 
-    PL_restartop = die_where(message);
+    PL_restartop = die_where(message, msglen);
     DEBUG_S(PerlIO_printf(PerlIO_stderr(),
          "%p: die: restartop = %p, was_in_eval = %d, top_env = %p\n",
          thr, PL_restartop, was_in_eval, PL_top_env));
@@ -1318,9 +1318,12 @@ croak(const char* pat, ...)
     HV *stash;
     GV *gv;
     CV *cv;
+    SV *msv;
+    STRLEN msglen;
 
     va_start(args, pat);
-    message = mess(pat, &args);
+    msv = mess(pat, &args);
+    message = SvPV(msv,msglen);
     va_end(args);
     DEBUG_S(PerlIO_printf(PerlIO_stderr(), "croak: 0x%lx %s", (unsigned long) thr, message));
     if (PL_diehook) {
@@ -1336,7 +1339,7 @@ croak(const char* pat, ...)
            SV *msg;
 
            ENTER;
-           msg = newSVpv(message, 0);
+           msg = newSVpvn(message, msglen);
            SvREADONLY_on(msg);
            SAVEFREESV(msg);
 
@@ -1350,11 +1353,20 @@ croak(const char* pat, ...)
        }
     }
     if (PL_in_eval) {
-       PL_restartop = die_where(message);
+       PL_restartop = die_where(message, msglen);
        JMPENV_JUMP(3);
     }
-    PerlIO_puts(PerlIO_stderr(),message);
-    (void)PerlIO_flush(PerlIO_stderr());
+    {
+#ifdef USE_SFIO
+       /* SFIO can really mess with your errno */
+       int e = errno;
+#endif
+       PerlIO_write(PerlIO_stderr(), message, msglen);
+       (void)PerlIO_flush(PerlIO_stderr());
+#ifdef USE_SFIO
+       errno = e;
+#endif
+    }
     my_failure_exit();
 }
 
@@ -1366,9 +1378,12 @@ warn(const char* pat,...)
     HV *stash;
     GV *gv;
     CV *cv;
+    SV *msv;
+    STRLEN msglen;
 
     va_start(args, pat);
-    message = mess(pat, &args);
+    msv = mess(pat, &args);
+    message = SvPV(msv, msglen);
     va_end(args);
 
     if (PL_warnhook) {
@@ -1385,7 +1400,7 @@ warn(const char* pat,...)
            SV *msg;
 
            ENTER;
-           msg = newSVpv(message, 0);
+           msg = newSVpvn(message, msglen);
            SvREADONLY_on(msg);
            SAVEFREESV(msg);
 
@@ -1399,7 +1414,7 @@ warn(const char* pat,...)
            return;
        }
     }
-    PerlIO_puts(PerlIO_stderr(),message);
+    PerlIO_write(PerlIO_stderr(), message, msglen);
 #ifdef LEAKTEST
     DEBUG_L(*message == '!' 
            ? (xstat(message[1]=='!'
@@ -1420,9 +1435,12 @@ warner(U32  err, const char* pat,...)
     HV *stash;
     GV *gv;
     CV *cv;
+    SV *msv;
+    STRLEN msglen;
 
     va_start(args, pat);
-    message = mess(pat, &args);
+    msv = mess(pat, &args);
+    message = SvPV(msv, msglen);
     va_end(args);
 
     if (ckDEAD(err)) {
@@ -1442,7 +1460,7 @@ warner(U32  err, const char* pat,...)
                 SV *msg;
  
                 ENTER;
-                msg = newSVpv(message, 0);
+                msg = newSVpvn(message, msglen);
                 SvREADONLY_on(msg);
                 SAVEFREESV(msg);
  
@@ -1455,10 +1473,10 @@ warner(U32  err, const char* pat,...)
             }
         }
         if (PL_in_eval) {
-            PL_restartop = die_where(message);
+            PL_restartop = die_where(message, msglen);
             JMPENV_JUMP(3);
         }
-        PerlIO_puts(PerlIO_stderr(),message);
+        PerlIO_write(PerlIO_stderr(), message, msglen);
         (void)PerlIO_flush(PerlIO_stderr());
         my_failure_exit();
 
@@ -1478,7 +1496,7 @@ warner(U32  err, const char* pat,...)
                 SV *msg;
  
                 ENTER;
-                msg = newSVpv(message, 0);
+                msg = newSVpvn(message, msglen);
                 SvREADONLY_on(msg);
                 SAVEFREESV(msg);
  
@@ -1491,7 +1509,7 @@ warner(U32  err, const char* pat,...)
                 return;
             }
         }
-        PerlIO_puts(PerlIO_stderr(),message);
+        PerlIO_write(PerlIO_stderr(), message, msglen);
 #ifdef LEAKTEST
         DEBUG_L(xstat());
 #endif
@@ -1504,6 +1522,8 @@ warner(U32  err, const char* pat,...)
 void
 my_setenv(char *nam, char *val)
 {
+#ifndef PERL_USE_SAFE_PUTENV
+    /* most putenv()s leak, so we manipulate environ directly */
     register I32 i=setenv_getix(nam);          /* where does it go? */
 
     if (environ == PL_origenviron) {   /* need we copy environment? */
@@ -1513,14 +1533,16 @@ my_setenv(char *nam, char *val)
 
        /*SUPPRESS 530*/
        for (max = i; environ[max]; max++) ;
-       New(901,tmpenv, max+2, char*);
-       for (j=0; j<max; j++)           /* copy environment */
-           tmpenv[j] = savepv(environ[j]);
+       tmpenv = (char**)safesysmalloc((max+2) * sizeof(char*));
+       for (j=0; j<max; j++) {         /* copy environment */
+           tmpenv[j] = (char*)safesysmalloc((strlen(environ[j])+1)*sizeof(char));
+           strcpy(tmpenv[j], environ[j]);
+       }
        tmpenv[max] = Nullch;
        environ = tmpenv;               /* tell exec where it is now */
     }
     if (!val) {
-       Safefree(environ[i]);
+       safesysfree(environ[i]);
        while (environ[i]) {
            environ[i] = environ[i+1];
            i++;
@@ -1528,12 +1550,13 @@ my_setenv(char *nam, char *val)
        return;
     }
     if (!environ[i]) {                 /* does not exist yet */
-       Renew(environ, i+2, char*);     /* just expand it a bit */
+       environ = (char**)safesysrealloc(environ, (i+2) * sizeof(char*));
        environ[i+1] = Nullch;  /* make sure it's null terminated */
     }
     else
-       Safefree(environ[i]);
-    New(904, environ[i], strlen(nam) + strlen(val) + 2, char);
+       safesysfree(environ[i]);
+    environ[i] = (char*)safesysmalloc((strlen(nam)+strlen(val)+2) * sizeof(char));
+
 #ifndef MSDOS
     (void)sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
 #else
@@ -1545,6 +1568,19 @@ my_setenv(char *nam, char *val)
     strcpy(environ[i],nam); strupr(environ[i]);
     (void)sprintf(environ[i] + strlen(nam),"=%s",val);
 #endif /* MSDOS */
+
+#else   /* PERL_USE_SAFE_PUTENV */
+    char *new_env;
+
+    new_env = (char*)safesysmalloc((strlen(nam) + strlen(val) + 2) * sizeof(char));
+#ifndef MSDOS
+    (void)sprintf(new_env,"%s=%s",nam,val);/* all that work just for this */
+#else
+    strcpy(new_env,nam); strupr(new_env);
+    (void)sprintf(new_env + strlen(nam),"=%s",val);
+#endif
+    (void)putenv(new_env);
+#endif  /* PERL_USE_SAFE_PUTENV */
 }
 
 #else /* if WIN32 */
@@ -1582,32 +1618,27 @@ my_setenv(char *nam,char *val)
     }
     else
        vallen = strlen(val);
-    New(904, envstr, namlen + vallen + 3, char);
+    envstr = (char*)safesysmalloc((namlen + vallen + 3) * sizeof(char));
     (void)sprintf(envstr,"%s=%s",nam,val);
     (void)PerlEnv_putenv(envstr);
     if (oldstr)
-       Safefree(oldstr);
+       safesysfree(oldstr);
 #ifdef _MSC_VER
-    Safefree(envstr);          /* MSVCRT leaks without this */
+    safesysfree(envstr);       /* MSVCRT leaks without this */
 #endif
 
 #else /* !USE_WIN32_RTL_ENV */
 
-    /* The sane way to deal with the environment.
-     * Has these advantages over putenv() & co.:
-     *  * enables us to store a truly empty value in the
-     *    environment (like in UNIX).
-     *  * we don't have to deal with RTL globals, bugs and leaks.
-     *  * Much faster.
-     * Why you may want to enable USE_WIN32_RTL_ENV:
-     *  * environ[] and RTL functions will not reflect changes,
-     *    which might be an issue if extensions want to access
-     *    the env. via RTL.  This cuts both ways, since RTL will
-     *    not see changes made by extensions that call the Win32
-     *    functions directly, either.
-     * GSAR 97-06-07
-     */
-    SetEnvironmentVariable(nam,val);
+    register char *envstr;
+    STRLEN len = strlen(nam) + 3;
+    if (!val) {
+       val = "";
+    }
+    len += strlen(val);
+    New(904, envstr, len, char);
+    (void)sprintf(envstr,"%s=%s",nam,val);
+    (void)PerlEnv_putenv(envstr);
+    Safefree(envstr);
 
 #endif
 }
@@ -1648,7 +1679,7 @@ char *f;
 
 #if !defined(HAS_BCOPY) || !defined(HAS_SAFE_BCOPY)
 char *
-my_bcopy(register char *from,register char *to,register I32 len)
+my_bcopy(register const char *from,register char *to,register I32 len)
 {
     char *retval = to;
 
@@ -1668,10 +1699,7 @@ my_bcopy(register char *from,register char *to,register I32 len)
 
 #ifndef HAS_MEMSET
 void *
-my_memset(loc,ch,len)
-register char *loc;
-register I32 ch;
-register I32 len;
+my_memset(register char *loc, register I32 ch, register I32 len)
 {
     char *retval = loc;
 
@@ -1683,9 +1711,7 @@ register I32 len;
 
 #if !defined(HAS_BZERO) && !defined(HAS_MEMSET)
 char *
-my_bzero(loc,len)
-register char *loc;
-register I32 len;
+my_bzero(register char *loc, register I32 len)
 {
     char *retval = loc;
 
@@ -1697,10 +1723,7 @@ register I32 len;
 
 #if !defined(HAS_MEMCMP) || !defined(HAS_SANE_MEMCMP)
 I32
-my_memcmp(s1,s2,len)
-char *s1;
-char *s2;
-register I32 len;
+my_memcmp(const char *s1, const char *s2, register I32 len)
 {
     register U8 *a = (U8 *)s1;
     register U8 *b = (U8 *)s2;
@@ -1721,10 +1744,7 @@ char *
 #else
 int
 #endif
-vsprintf(dest, pat, args)
-char *dest;
-const char *pat;
-char *args;
+vsprintf(char *dest, const char *pat, char *args)
 {
     FILE fakebuf;
 
@@ -1891,6 +1911,7 @@ my_popen(char *cmd, char *mode)
     SV *sv;
     I32 doexec = strNE(cmd,"-");
 
+    PERL_FLUSHALL_FOR_CHILD;
 #ifdef OS2
     if (doexec) {
        return my_syspopen(cmd,mode);
@@ -1964,12 +1985,11 @@ my_popen(char *cmd, char *mode)
 #if defined(atarist) || defined(DJGPP)
 FILE *popen();
 PerlIO *
-my_popen(cmd,mode)
-char   *cmd;
-char   *mode;
+my_popen(char *cmd, char *mode)
 {
     /* Needs work for PerlIO ! */
     /* used 0 for 2nd parameter to PerlIO-exportFILE; apparently not used */
+    PERL_FLUSHALL_FOR_CHILD;
     return popen(PerlIO_exportFILE(cmd, 0), mode);
 }
 #endif
@@ -2284,13 +2304,13 @@ PerlIO *ptr;
 #endif
 
 void
-repeatcpy(register char *to, register char *from, I32 len, register I32 count)
+repeatcpy(register char *to, register const char *from, I32 len, register I32 count)
 {
     register I32 todo;
-    register char *frombase = from;
+    register const char *frombase = from;
 
     if (len == 1) {
-       register char c = *from;
+       register const char c = *from;
        while (count-- > 0)
            *to++ = c;
        return;
@@ -2420,10 +2440,10 @@ scan_bin(char *start, I32 len, I32 *retlen)
       retval = n | (*s++ - '0');
       len--;
     }
-    if (len && (*s >= '2' || *s <= '9')) {
+    if (len && (*s >= '2' && *s <= '9')) {
       dTHR;
       if (ckWARN(WARN_UNSAFE))
-          warner(WARN_UNSAFE, "Illegal binary digit ignored");
+          warner(WARN_UNSAFE, "Illegal binary digit '%c' ignored", *s);
     }
     *retlen = s - start;
     return retval;
@@ -2447,7 +2467,7 @@ scan_oct(char *start, I32 len, I32 *retlen)
     if (len && (*s == '8' || *s == '9')) {
        dTHR;
        if (ckWARN(WARN_OCTAL))
-           warner(WARN_OCTAL, "Illegal octal digit ignored");
+           warner(WARN_OCTAL, "Illegal octal digit '%c' ignored", *s);
     }
     *retlen = s - start;
     return retval;
@@ -2471,7 +2491,7 @@ scan_hex(char *start, I32 len, I32 *retlen)
                dTHR;
                --s;
                if (ckWARN(WARN_UNSAFE))
-                   warner(WARN_UNSAFE,"Illegal hex digit ignored");
+                   warner(WARN_UNSAFE,"Illegal hex digit '%c' ignored", *s);
                break;
            }
        }
@@ -2804,11 +2824,11 @@ condpair_magic(SV *sv)
        COND_INIT(&cp->owner_cond);
        COND_INIT(&cp->cond);
        cp->owner = 0;
-       LOCK_SV_MUTEX;
+       MUTEX_LOCK(&PL_cred_mutex);             /* XXX need separate mutex? */
        mg = mg_find(sv, 'm');
        if (mg) {
            /* someone else beat us to initialising it */
-           UNLOCK_SV_MUTEX;
+           MUTEX_UNLOCK(&PL_cred_mutex);       /* XXX need separate mutex? */
            MUTEX_DESTROY(&cp->mutex);
            COND_DESTROY(&cp->owner_cond);
            COND_DESTROY(&cp->cond);
@@ -2819,7 +2839,7 @@ condpair_magic(SV *sv)
            mg = SvMAGIC(sv);
            mg->mg_ptr = (char *)cp;
            mg->mg_len = sizeof(cp);
-           UNLOCK_SV_MUTEX;
+           MUTEX_UNLOCK(&PL_cred_mutex);       /* XXX need separate mutex? */
            DEBUG_S(WITH_THR(PerlIO_printf(PerlIO_stderr(),
                                           "%p: condpair_magic %p\n", thr, sv));)
        }
@@ -2842,7 +2862,7 @@ new_struct_thread(struct perl_thread *t)
     SV **svp;
     I32 i;
 
-    sv = newSVpv("", 0);
+    sv = newSVpvn("", 0);
     SvGROW(sv, sizeof(struct perl_thread) + 1);
     SvCUR_set(sv, sizeof(struct perl_thread));
     thr = (Thread) SvPVX(sv);
@@ -2866,7 +2886,7 @@ new_struct_thread(struct perl_thread *t)
     thr->cvcache = newHV();
     thr->threadsv = newAV();
     thr->specific = newAV();
-    thr->errsv = newSVpv("", 0);
+    thr->errsv = newSVpvn("", 0);
     thr->errhv = newHV();
     thr->flags = THRf_R_JOINABLE;
     MUTEX_INIT(&thr->mutex);
@@ -3002,6 +3022,21 @@ get_specialsv_list(void)
  return PL_specialsv_list;
 }
 
+#ifndef HAS_GETENV_SV
+SV *
+getenv_sv(char *env_elem)
+{
+  char *env_trans;
+  SV *temp_sv;
+  if ((env_trans = PerlEnv_getenv(env_elem)) != Nullch) {
+    temp_sv = newSVpv(env_trans, strlen(env_trans));
+    return temp_sv;
+  } else {
+    return &PL_sv_undef;
+  }
+}
+#endif
+
 
 MGVTBL*
 get_vtbl(int vtbl_id)