AIX tweak from Merijn Brand.
[p5sagit/p5-mst-13.2.git] / util.c
diff --git a/util.c b/util.c
index 7a7d5f1..ab8356e 100644 (file)
--- a/util.c
+++ b/util.c
@@ -56,14 +56,14 @@ long lastxycount[MAXXCOUNT][MAXYCOUNT];
 #  define FD_CLOEXEC 1                 /* NeXT needs this */
 #endif
 
-/* 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
  * allocated hunks back to the original New to track down any memory leaks.
  * XXX This advice seems to be widely ignored :-(   --AD  August 1996.
  */
 
+/* paranoid version of system's malloc() */
+
 Malloc_t
 Perl_safesysmalloc(MEM_SIZE size)
 {
@@ -742,7 +742,7 @@ Perl_fbm_instr(pTHX_ unsigned char *big, register unsigned char *bigend, SV *lit
  */
 
 /* If SvTAIL is actually due to \Z or \z, this gives false positives
-   if PL_multiline.  In fact if !PL_multiline the autoritative answer
+   if PL_multiline.  In fact if !PL_multiline the authoritative answer
    is not supported yet. */
 
 char *
@@ -781,8 +781,14 @@ Perl_screaminstr(pTHX_ SV *bigstr, SV *littlestr, I32 start_shift, I32 end_shift
     /* The value of pos we can stop at: */
     stop_pos = SvCUR(bigstr) - end_shift - (SvCUR(littlestr) - 1 - previous);
     if (previous + start_shift > stop_pos) {
+/*
+  stop_pos does not include SvTAIL in the count, so this check is incorrect
+  (I think) - see [ID 20010618.006] and t/op/study.t. HVDS 2001/06/19
+*/
+#if 0
        if (previous + start_shift == stop_pos + 1) /* A fake '\n'? */
            goto check_tail;
+#endif
        return Nullch;
     }
     while (pos < previous + start_shift) {
@@ -2045,7 +2051,7 @@ Perl_my_popen(pTHX_ char *cmd, char *mode)
     return PerlIO_fdopen(p[This], mode);
 }
 #else
-#if defined(atarist) || defined(DJGPP)
+#if defined(atarist)
 FILE *popen();
 PerlIO *
 Perl_my_popen(pTHX_ char *cmd, char *mode)
@@ -2057,6 +2063,20 @@ Perl_my_popen(pTHX_ char *cmd, char *mode)
     */
     return PerlIO_importFILE(popen(cmd, mode), 0);
 }
+#else
+#if defined(DJGPP)
+FILE *djgpp_popen();
+PerlIO *
+Perl_my_popen(pTHX_ char *cmd, char *mode)
+{
+    PERL_FLUSHALL_FOR_CHILD;
+    /* Call system's popen() to get a FILE *, then import it.
+       used 0 for 2nd parameter to PerlIO_importFILE;
+       apparently not used
+    */
+    return PerlIO_importFILE(djgpp_popen(cmd, mode), 0);
+}
+#endif
 #endif
 
 #endif /* !DOSISH */
@@ -2361,7 +2381,7 @@ Perl_pidgone(pTHX_ Pid_t pid, int status)
     return;
 }
 
-#if defined(atarist) || defined(OS2) || defined(DJGPP)
+#if defined(atarist) || defined(OS2)
 int pclose();
 #ifdef HAS_FORK
 int                                    /* Cannot prototype with I32
@@ -2375,9 +2395,20 @@ Perl_my_pclose(pTHX_ PerlIO *ptr)
     /* Needs work for PerlIO ! */
     FILE *f = PerlIO_findFILE(ptr);
     I32 result = pclose(f);
+    PerlIO_releaseFILE(ptr,f);
+    return result;
+}
+#endif
+
 #if defined(DJGPP)
+int djgpp_pclose();
+I32
+Perl_my_pclose(pTHX_ PerlIO *ptr)
+{
+    /* Needs work for PerlIO ! */
+    FILE *f = PerlIO_findFILE(ptr);
+    I32 result = djgpp_pclose(f);
     result = (result << 8) & 0xff00;
-#endif
     PerlIO_releaseFILE(ptr,f);
     return result;
 }
@@ -3598,33 +3629,39 @@ Fill the sv with current working directory
  *     because you might chdir out of a directory that you can't chdir
  *     back into. */
 
-/* XXX: this needs more porting #ifndef HAS_GETCWD */
 int
 Perl_sv_getcwd(pTHX_ register SV *sv)
 {
 #ifndef PERL_MICRO
 
-#ifndef HAS_GETCWD
+#ifdef HAS_GETCWD
+    {
+       char buf[MAXPATHLEN];
+
+        /* Some getcwd()s automatically allocate a buffer of the given
+        * size from the heap if they are given a NULL buffer pointer.
+        * The problem is that this behaviour is not portable. */
+        if (getcwd(buf, sizeof(buf) - 1)) {
+            STRLEN len = strlen(buf);
+            sv_setpvn(sv, buf, len);
+            return TRUE;
+        }
+        else {
+            sv_setsv(sv, &PL_sv_undef);
+            return FALSE;
+        }
+    }
+
+#else
+
     struct stat statbuf;
     int orig_cdev, orig_cino, cdev, cino, odev, oino, tdev, tino;
     int namelen, pathlen=0;
     DIR *dir;
     Direntry_t *dp;
-#endif
 
     (void)SvUPGRADE(sv, SVt_PV);
 
-#ifdef HAS_GETCWD
-
-    SvGROW(sv, 128);
-    while ((getcwd(SvPVX(sv), SvLEN(sv)-1) == NULL) && errno == ERANGE) {
-        SvGROW(sv, SvLEN(sv) + 128);
-    }
-    SvCUR_set(sv, strlen(SvPVX(sv)));
-    SvPOK_only(sv);
-
-#else
-
     if (PerlLIO_lstat(".", &statbuf) < 0) {
         SV_CWD_RETURN_UNDEF;
     }
@@ -3681,6 +3718,10 @@ Perl_sv_getcwd(pTHX_ register SV *sv)
             SV_CWD_RETURN_UNDEF;
         }
 
+        if (pathlen + namelen + 1 >= MAXPATHLEN) {
+            SV_CWD_RETURN_UNDEF;
+       }
+
         SvGROW(sv, pathlen + namelen + 1);
 
         if (pathlen) {
@@ -3702,12 +3743,14 @@ Perl_sv_getcwd(pTHX_ register SV *sv)
 #endif
     }
 
-    SvCUR_set(sv, pathlen);
-    *SvEND(sv) = '\0';
-    SvPOK_only(sv);
+    if (pathlen) {
+        SvCUR_set(sv, pathlen);
+        *SvEND(sv) = '\0';
+        SvPOK_only(sv);
 
-    if (PerlDir_chdir(SvPVX(sv)) < 0) {
-        SV_CWD_RETURN_UNDEF;
+       if (PerlDir_chdir(SvPVX(sv)) < 0) {
+            SV_CWD_RETURN_UNDEF;
+        }
     }
     if (PerlLIO_stat(".", &statbuf) < 0) {
         SV_CWD_RETURN_UNDEF;
@@ -3728,166 +3771,3 @@ Perl_sv_getcwd(pTHX_ register SV *sv)
 #endif
 }
 
-/*
-=for apidoc sv_realpath
-
-Wrap or emulate realpath(3).
-
-=cut
- */
-int
-Perl_sv_realpath(pTHX_ SV *sv, char *path, STRLEN len)
-{
-#ifndef PERL_MICRO
-    char name[MAXPATHLEN] = { 0 }, *s;
-    STRLEN pathlen, namelen;
-
-    /* Don't use strlen() to avoid running off the end. */
-    s = memchr(path, '\0', MAXPATHLEN);
-    pathlen = s ? s - path : MAXPATHLEN;
-
-#ifdef HAS_REALPATH
-
-    /* Be paranoid about the use of realpath(),
-     * it is an infamous source of buffer overruns. */
-
-    /* Is the source buffer too long? */
-    if (pathlen == MAXPATHLEN) {
-        Perl_warn(aTHX_ "sv_realpath: realpath(\"%s\"): %c= (MAXPATHLEN = %d)",
-                  path, s ? '=' : '>', MAXPATHLEN);
-        SV_CWD_RETURN_UNDEF;
-    }
-
-    /* Here goes nothing. */
-    if (realpath(path, name) == NULL) {
-        Perl_warn(aTHX_ "sv_realpath: realpath(\"%s\"): %s",
-                  path, Strerror(errno));
-        SV_CWD_RETURN_UNDEF;
-    }
-
-    /* Is the destination buffer too long?
-     * Don't use strlen() to avoid running off the end. */
-    s = memchr(name, '\0', MAXPATHLEN);
-    namelen = s ? s - name : MAXPATHLEN;
-    if (namelen == MAXPATHLEN) {
-        Perl_warn(aTHX_ "sv_realpath: realpath(\"%s\"): %c= (MAXPATHLEN = %d)",
-                  path, s ? '=' : '>', MAXPATHLEN);
-        SV_CWD_RETURN_UNDEF;
-    }
-
-    /* The coast is clear? */
-    sv_setpvn(sv, name, namelen);
-    SvPOK_only(sv);
-
-    return TRUE;
-#else
-    {
-    DIR *parent;
-    Direntry_t *dp;
-    char dotdots[MAXPATHLEN] = { 0 };
-    struct stat cst, pst, tst;
-
-    if (PerlLIO_stat(path, &cst) < 0) {
-        Perl_warn(aTHX_ "sv_realpath: stat(\"%s\"): %s",
-                  path, Strerror(errno));
-        SV_CWD_RETURN_UNDEF;
-    }
-
-    (void)SvUPGRADE(sv, SVt_PV);
-
-    if (!len) {
-        len = strlen(path);
-    }
-    Copy(path, dotdots, len, char);
-
-    for (;;) {
-        strcat(dotdots, "/..");
-        StructCopy(&cst, &pst, struct stat);
-
-        if (PerlLIO_stat(dotdots, &cst) < 0) {
-            Perl_warn(aTHX_ "sv_realpath: stat(\"%s\"): %s",
-                      dotdots, Strerror(errno));
-            SV_CWD_RETURN_UNDEF;
-        }
-
-        if (pst.st_dev == cst.st_dev && pst.st_ino == cst.st_ino) {
-            /* We've reached the root: previous is same as current */
-            break;
-        } else {
-            STRLEN dotdotslen = strlen(dotdots);
-
-            /* Scan through the dir looking for name of previous */
-            if (!(parent = PerlDir_open(dotdots))) {
-                Perl_warn(aTHX_ "sv_realpath: opendir(\"%s\"): %s",
-                          dotdots, Strerror(errno));
-                SV_CWD_RETURN_UNDEF;
-            }
-
-            SETERRNO(0,SS$_NORMAL); /* for readdir() */
-            while ((dp = PerlDir_read(parent)) != NULL) {
-                if (SV_CWD_ISDOT(dp)) {
-                    continue;
-                }
-
-                Copy(dotdots, name, dotdotslen, char);
-                name[dotdotslen] = '/';
-#ifdef DIRNAMLEN
-                namelen = dp->d_namlen;
-#else
-                namelen = strlen(dp->d_name);
-#endif
-                Copy(dp->d_name, name + dotdotslen + 1, namelen, char);
-                name[dotdotslen + 1 + namelen] = 0;
-
-                if (PerlLIO_lstat(name, &tst) < 0) {
-                    PerlDir_close(parent);
-                    Perl_warn(aTHX_ "sv_realpath: lstat(\"%s\"): %s",
-                              name, Strerror(errno));
-                    SV_CWD_RETURN_UNDEF;
-                }
-
-                if (tst.st_dev == pst.st_dev && tst.st_ino == pst.st_ino)
-                    break;
-
-                SETERRNO(0,SS$_NORMAL); /* for readdir() */
-            }
-
-            if (!dp && errno) {
-                Perl_warn(aTHX_ "sv_realpath: readdir(\"%s\"): %s",
-                          dotdots, Strerror(errno));
-                SV_CWD_RETURN_UNDEF;
-            }
-
-            SvGROW(sv, pathlen + namelen + 1);
-            if (pathlen) {
-                /* shift down */
-                Move(SvPVX(sv), SvPVX(sv) + namelen + 1, pathlen, char);
-            }
-
-            *SvPVX(sv) = '/';
-            Move(dp->d_name, SvPVX(sv)+1, namelen, char);
-            pathlen += (namelen + 1);
-
-#ifdef VOID_CLOSEDIR
-            PerlDir_close(parent);
-#else
-            if (PerlDir_close(parent) < 0) {
-                Perl_warn(aTHX_ "sv_realpath: closedir(\"%s\"): %s",
-                          dotdots, Strerror(errno));
-                SV_CWD_RETURN_UNDEF;
-            }
-#endif
-        }
-    }
-
-    SvCUR_set(sv, pathlen);
-    SvPOK_only(sv);
-
-    return TRUE;
-    }
-#endif
-#else
-    return FALSE;
-#endif
-}
-