ccflags, not ldflags.
[p5sagit/p5-mst-13.2.git] / perlio.c
index 21aa151..f74e569 100644 (file)
--- a/perlio.c
+++ b/perlio.c
@@ -175,6 +175,7 @@ PerlIO_binmode(pTHX_ PerlIO *fp, int iotype, int mode, const char *names)
 PerlIO *
 PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param)
 {
+#ifndef PERL_MICRO
     if (f) {
        int fd = PerlLIO_dup(PerlIO_fileno(f));
        if (fd >= 0) {
@@ -189,6 +190,7 @@ PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param)
     else {
        SETERRNO(EBADF, SS$_IVCHAN);
     }
+#endif
     return NULL;
 }
 
@@ -517,13 +519,16 @@ PerlIO_list_push(pTHX_ PerlIO_list_t *list, PerlIO_funcs *funcs, SV *arg)
 PerlIO_list_t *
 PerlIO_clone_list(pTHX_ PerlIO_list_t *proto, CLONE_PARAMS *param)
 {
-    int i;
-    PerlIO_list_t *list = PerlIO_list_alloc(aTHX);
-    for (i=0; i < proto->cur; i++) {
-       SV *arg = Nullsv;
-       if (proto->array[i].arg)
-           arg = PerlIO_sv_dup(aTHX_ proto->array[i].arg,param);
-       PerlIO_list_push(aTHX_ list, proto->array[i].funcs, arg);
+    PerlIO_list_t *list = (PerlIO_list_t *) NULL;
+    if (proto) {
+       int i;
+       list = PerlIO_list_alloc(aTHX);
+       for (i=0; i < proto->cur; i++) {
+           SV *arg = Nullsv;
+           if (proto->array[i].arg)
+               arg = PerlIO_sv_dup(aTHX_ proto->array[i].arg,param);
+           PerlIO_list_push(aTHX_ list, proto->array[i].funcs, arg);
+       }
     }
     return list;
 }
@@ -538,6 +543,7 @@ PerlIO_clone(pTHX_ PerlInterpreter *proto, CLONE_PARAMS *param)
     PL_known_layers = PerlIO_clone_list(aTHX_ proto->Iknown_layers, param);
     PL_def_layerlist = PerlIO_clone_list(aTHX_ proto->Idef_layerlist, param);
     PerlIO_allocate(aTHX); /* root slot is never used */
+    PerlIO_debug("Clone %p from %p\n",aTHX,proto);
     while ((f = *table)) {
            int i;
            table = (PerlIO **) (f++);
@@ -552,16 +558,13 @@ PerlIO_clone(pTHX_ PerlInterpreter *proto, CLONE_PARAMS *param)
 }
 
 void
-PerlIO_cleanup(pTHX)
-{
-    PerlIO_cleantable(aTHX_ &PL_perlio);
-}
-
-void
 PerlIO_destruct(pTHX)
 {
     PerlIO **table = &PL_perlio;
     PerlIO *f;
+#ifdef USE_ITHREADS
+    PerlIO_debug("Destruct %p\n",aTHX);
+#endif
     while ((f = *table)) {
        int i;
        table = (PerlIO **) (f++);
@@ -1992,20 +1995,70 @@ PerlIOBase_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param)
 }
 
 #define PERLIO_MAX_REFCOUNTABLE_FD 2048
-#ifdef USE_ITHREADS
+#ifdef USE_THREADS
 perl_mutex PerlIO_mutex;
-int PerlIO_fd_refcnt[PERLIO_MAX_REFCOUNTABLE_FD] = {1,1,1};
 #endif
+int PerlIO_fd_refcnt[PERLIO_MAX_REFCOUNTABLE_FD];
 
 void
 PerlIO_init(pTHX)
 {
  /* Place holder for stdstreams call ??? */
-#ifdef USE_ITHREADS
+#ifdef USE_THREADS
  MUTEX_INIT(&PerlIO_mutex);
 #endif
 }
 
+void
+PerlIOUnix_refcnt_inc(int fd)
+{
+    if (fd >= 0 && fd < PERLIO_MAX_REFCOUNTABLE_FD) {
+#ifdef USE_THREADS
+       MUTEX_LOCK(&PerlIO_mutex);
+#endif
+       PerlIO_fd_refcnt[fd]++;
+       PerlIO_debug("fd %d refcnt=%d\n",fd,PerlIO_fd_refcnt[fd]);
+#ifdef USE_THREADS
+       MUTEX_UNLOCK(&PerlIO_mutex);
+#endif
+    }
+}
+
+int
+PerlIOUnix_refcnt_dec(int fd)
+{
+    int cnt = 0;
+    if (fd >= 0 && fd < PERLIO_MAX_REFCOUNTABLE_FD) {
+#ifdef USE_THREADS
+       MUTEX_LOCK(&PerlIO_mutex);
+#endif
+       cnt = --PerlIO_fd_refcnt[fd];
+       PerlIO_debug("fd %d refcnt=%d\n",fd,cnt);
+#ifdef USE_THREADS
+       MUTEX_UNLOCK(&PerlIO_mutex);
+#endif
+    }
+    return cnt;
+}
+
+void
+PerlIO_cleanup(pTHX)
+{
+    int i;
+#ifdef USE_ITHREADS
+    PerlIO_debug("Cleanup %p\n",aTHX);
+#endif
+    /* Raise STDIN..STDERR refcount so we don't close them */
+    for (i=0; i < 3; i++)
+       PerlIOUnix_refcnt_inc(i);
+    PerlIO_cleantable(aTHX_ &PL_perlio);
+    /* Restore STDIN..STDERR refcount */
+    for (i=0; i < 3; i++)
+       PerlIOUnix_refcnt_dec(i);
+}
+
+
+
 /*--------------------------------------------------------------------------------------*/
 /*
  * Bottom-most level for UNIX-like case
@@ -2079,20 +2132,6 @@ PerlIOUnix_fileno(PerlIO *f)
     return PerlIOSelf(f, PerlIOUnix)->fd;
 }
 
-void
-PerlIOUnix_refcnt_inc(int fd)
-{
-#ifdef USE_ITHREADS
-    if (fd >= 0 && fd < PERLIO_MAX_REFCOUNTABLE_FD) {
-       MUTEX_LOCK(&PerlIO_mutex);
-       PerlIO_fd_refcnt[fd]++;
-       PerlIO_debug("fd %d refcnt=%d\n",fd,PerlIO_fd_refcnt[fd]);
-       MUTEX_UNLOCK(&PerlIO_mutex);
-    }
-#endif
-}
-
-
 IV
 PerlIOUnix_pushed(PerlIO *f, const char *mode, SV *arg)
 {
@@ -2238,23 +2277,16 @@ PerlIOUnix_close(PerlIO *f)
     dTHX;
     int fd = PerlIOSelf(f, PerlIOUnix)->fd;
     int code = 0;
-#ifdef USE_ITHREADS
-    if ((PerlIOBase(f)->flags & PERLIO_F_OPEN) && fd >= 0 && fd < PERLIO_MAX_REFCOUNTABLE_FD) {
-       MUTEX_LOCK(&PerlIO_mutex); 
-       if (--PerlIO_fd_refcnt[fd] > 0) {
-           PerlIO_debug("fd %d refcnt=%d\n",fd,PerlIO_fd_refcnt[fd]);
-           MUTEX_UNLOCK(&PerlIO_mutex); 
+    if (PerlIOBase(f)->flags & PERLIO_F_OPEN) {
+       if (PerlIOUnix_refcnt_dec(fd) > 0) {
            PerlIOBase(f)->flags &= ~PERLIO_F_OPEN;
            return 0;
         }
-       PerlIO_debug("fd %d refcnt=%d\n",fd,PerlIO_fd_refcnt[fd]);
-       MUTEX_UNLOCK(&PerlIO_mutex); 
     }
     else {
        SETERRNO(EBADF,SS$_IVCHAN);
        return -1;
     }
-#endif
     while (PerlLIO_close(fd) != 0) {
        if (errno != EINTR) {
            code = -1;
@@ -2374,12 +2406,14 @@ PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
     if (f) {
        char *path = SvPV_nolen(*args);
        PerlIOStdio *s = PerlIOSelf(f, PerlIOStdio);
-       FILE *stdio =
-           PerlSIO_freopen(path, (mode = PerlIOStdio_mode(mode, tmode)),
+       FILE *stdio;
+       PerlIOUnix_refcnt_dec(fileno(s->stdio));
+       stdio = PerlSIO_freopen(path, (mode = PerlIOStdio_mode(mode, tmode)),
                            s->stdio);
        if (!s->stdio)
            return NULL;
        s->stdio = stdio;
+       PerlIOUnix_refcnt_inc(fileno(s->stdio));
        return f;
     }
     else {
@@ -2399,6 +2433,7 @@ PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
                                    PerlIOArg),
                                   PerlIOStdio);
                    s->stdio = stdio;
+                   PerlIOUnix_refcnt_inc(fileno(s->stdio));
                }
                return f;
            }
@@ -2433,6 +2468,7 @@ PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
                               (aTHX_(f = PerlIO_allocate(aTHX)), self,
                                mode, PerlIOArg), PerlIOStdio);
                s->stdio = stdio;
+               PerlIOUnix_refcnt_inc(fileno(s->stdio));
                return f;
            }
        }
@@ -2440,6 +2476,49 @@ PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
     return NULL;
 }
 
+PerlIO *
+PerlIOStdio_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param)
+{
+    /* This assumes no layers underneath - which is what
+       happens, but is not how I remember it. NI-S 2001/10/16
+     */
+    if ((f = PerlIOBase_dup(aTHX_ f, o, param))) {
+       FILE *stdio = PerlIOSelf(o, PerlIOStdio)->stdio;
+       PerlIOSelf(f, PerlIOStdio)->stdio = stdio;
+       PerlIOUnix_refcnt_inc(fileno(stdio));
+    }
+    return f;
+}
+
+IV
+PerlIOStdio_close(PerlIO *f)
+{
+    dSYS;
+#ifdef SOCKS5_VERSION_NAME
+    int optval;
+    Sock_size_t optlen = sizeof(int);
+#endif
+    FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
+    if (PerlIOUnix_refcnt_dec(fileno(stdio)) > 0) {
+       /* Do not close it but do flush any buffers */
+       PerlIO_flush(f);
+       return 0;
+    }
+    return (
+#ifdef SOCKS5_VERSION_NAME
+              (getsockopt
+               (PerlIO_fileno(f), SOL_SOCKET, SO_TYPE, (void *) &optval,
+                &optlen) <
+               0) ? PerlSIO_fclose(stdio) : close(PerlIO_fileno(f))
+#else
+              PerlSIO_fclose(stdio)
+#endif
+       );
+
+}
+
+
+
 SSize_t
 PerlIOStdio_read(PerlIO *f, void *vbuf, Size_t count)
 {
@@ -2505,28 +2584,6 @@ PerlIOStdio_tell(PerlIO *f)
 }
 
 IV
-PerlIOStdio_close(PerlIO *f)
-{
-    dSYS;
-#ifdef SOCKS5_VERSION_NAME
-    int optval;
-    Sock_size_t optlen = sizeof(int);
-#endif
-    FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
-    return (
-#ifdef SOCKS5_VERSION_NAME
-              (getsockopt
-               (PerlIO_fileno(f), SOL_SOCKET, SO_TYPE, (void *) &optval,
-                &optlen) <
-               0) ? PerlSIO_fclose(stdio) : close(PerlIO_fileno(f))
-#else
-              PerlSIO_fclose(stdio)
-#endif
-       );
-
-}
-
-IV
 PerlIOStdio_flush(PerlIO *f)
 {
     dSYS;
@@ -2681,32 +2738,6 @@ PerlIOStdio_set_ptrcnt(PerlIO *f, STDCHAR * ptr, SSize_t cnt)
 
 #endif
 
-PerlIO *
-PerlIOStdio_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param)
-{
-    /* This assumes no layers underneath - which is what
-       happens, but is not how I remember it. NI-S 2001/10/16
-     */
-    int fd = PerlLIO_dup(PerlIO_fileno(o));
-    if (fd >= 0) {
-       char buf[8];
-       FILE *stdio = PerlSIO_fdopen(fd, PerlIO_modestr(o, buf));
-       if (stdio) {
-           if ((f = PerlIOBase_dup(aTHX_ f, o, param))) {
-               PerlIOSelf(f, PerlIOStdio)->stdio = stdio;
-           }
-           else {
-               PerlSIO_fclose(stdio);
-           }
-       }
-       else {
-           PerlLIO_close(fd);
-           f = NULL;
-       }
-    }
-    return f;
-}
-
 PerlIO_funcs PerlIO_stdio = {
     "stdio",
     sizeof(PerlIOStdio),
@@ -2841,19 +2872,26 @@ PerlIOBuf_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
        f = (*tab->Open) (aTHX_ tab, layers, n - 1, mode, fd, imode, perm,
                          NULL, narg, args);
        if (f) {
-           PerlIO_push(aTHX_ f, self, mode, PerlIOArg);
-           fd = PerlIO_fileno(f);
-#if O_BINARY != O_TEXT
-           /*
-            * do something about failing setmode()? --jhi
-            */
-           PerlLIO_setmode(fd, O_BINARY);
-#endif
-           if (init && fd == 2) {
+            if (PerlIO_push(aTHX_ f, self, mode, PerlIOArg) == 0) {
+               /*
+                * if push fails during open, open fails. close will pop us.
+                */
+               PerlIO_close (f);
+               return NULL;
+           } else {
+               fd = PerlIO_fileno(f);
+#if (O_BINARY != O_TEXT) && !defined(__BEOS__)
                /*
-                * Initial stderr is unbuffered
+                * do something about failing setmode()? --jhi
                 */
-               PerlIOBase(f)->flags |= PERLIO_F_UNBUF;
+               PerlLIO_setmode(fd, O_BINARY);
+#endif
+               if (init && fd == 2) {
+                   /*
+                    * Initial stderr is unbuffered
+                    */
+                   PerlIOBase(f)->flags |= PERLIO_F_UNBUF;
+               }
            }
        }
     }
@@ -3675,8 +3713,8 @@ PerlIOMmap_map(PerlIO *f)
     if (flags & PERLIO_F_CANREAD) {
        PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
        int fd = PerlIO_fileno(f);
-       struct stat st;
-       code = fstat(fd, &st);
+       Stat_t st;
+       code = Fstat(fd, &st);
        if (code == 0 && S_ISREG(st.st_mode)) {
            SSize_t len = st.st_size - b->posn;
            if (len > 0) {