Comment on comment.
[p5sagit/p5-mst-13.2.git] / doio.c
diff --git a/doio.c b/doio.c
index 7c4d3c9..094bf84 100644 (file)
--- a/doio.c
+++ b/doio.c
 #include <signal.h>
 #endif
 
-/* XXX If this causes problems, set i_unistd=undef in the hint file.  */
-#ifdef I_UNISTD
-#  include <unistd.h>
-#endif
-
-#if defined(HAS_SOCKET) && !defined(VMS) /* VMS handles sockets via vmsish.h */
-# include <sys/socket.h>
-# if defined(USE_SOCKS) && defined(I_SOCKS)
-#   include <socks.h>
-# endif 
-# ifdef I_NETBSD
-#  include <netdb.h>
-# endif
-# ifndef ENOTSOCK
-#  ifdef I_NET_ERRNO
-#   include <net/errno.h>
-#  endif
-# endif
-#endif
-
 bool
 Perl_do_open(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
             int rawmode, int rawperm, PerlIO *supplied_fp)
@@ -94,9 +74,14 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
     int result;
     bool was_fdopen = FALSE;
     bool in_raw = 0, in_crlf = 0, out_raw = 0, out_crlf = 0;
+    char *type  = NULL;
+    char *deftype = NULL;
+    char mode[4];              /* stdio file mode ("r\0", "rb\0", "r+b\0" etc.) */
 
+    Zero(mode,sizeof(mode),char);
     PL_forkprocess = 1;                /* assume true if no fork */
 
+    /* Collect default raw/crlf info from the op */
     if (PL_op && PL_op->op_type == OP_OPEN) {
        /* set up disciplines */
        U8 flags = PL_op->op_private;
@@ -106,6 +91,7 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
        out_crlf = (flags & OPpOPEN_OUT_CRLF);
     }
 
+    /* If currently open - close before we re-open */
     if (IoIFP(io)) {
        fd = PerlIO_fileno(IoIFP(io));
        if (IoTYPE(io) == IoTYPE_STD)
@@ -136,6 +122,8 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
     }
 
     if (as_raw) {
+        /* sysopen style args, i.e. integer mode and permissions */
+
 #if defined(USE_64_BIT_RAWIO) && defined(O_LARGEFILE)
        rawmode |= O_LARGEFILE;
 #endif
@@ -163,75 +151,79 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
        if (fd == -1)
            fp = NULL;
        else {
-           char fpmode[4];
            STRLEN ix = 0;
-           if (result == O_RDONLY)
-               fpmode[ix++] = 'r';
+           if (result == O_RDONLY) {
+               mode[ix++] = 'r';
+           }
 #ifdef O_APPEND
            else if (rawmode & O_APPEND) {
-               fpmode[ix++] = 'a';
+               mode[ix++] = 'a';
                if (result != O_WRONLY)
-                   fpmode[ix++] = '+';
+                   mode[ix++] = '+';
            }
 #endif
            else {
                if (result == O_WRONLY)
-                   fpmode[ix++] = 'w';
+                   mode[ix++] = 'w';
                else {
-                   fpmode[ix++] = 'r';
-                   fpmode[ix++] = '+';
+                   mode[ix++] = 'r';
+                   mode[ix++] = '+';
                }
            }
            if (rawmode & O_BINARY)
-               fpmode[ix++] = 'b';
-           fpmode[ix] = '\0';
-           fp = PerlIO_fdopen(fd, fpmode);
+               mode[ix++] = 'b';
+           mode[ix] = '\0';
+           fp = PerlIO_fdopen(fd, mode);
            if (!fp)
                PerlLIO_close(fd);
        }
     }
     else {
-       char *type;
+       /* Regular (non-sys) open */
        char *oname = name;
-       STRLEN tlen;
        STRLEN olen = len;
-       char mode[4];           /* stdio file mode ("r\0", "rb\0", "r+b\0" etc.) */
-       int dodup;
+       char *tend;
+       int dodup = 0;
 
        type = savepvn(name, len);
-       tlen = len;
+       tend = type+len;
        SAVEFREEPV(type);
+       /* Loose trailing white space */
+       while (tend > type && isSPACE(tend[-1]))
+           *tend-- = '\0';
        if (num_svs) {
+           /* New style explict name, type is just mode and discipline/layer info */
            STRLEN l;
            name = SvPV(svs, l) ;
            len = (I32)l;
            name = savepvn(name, len);
            SAVEFREEPV(name);
+           /*SUPPRESS 530*/
+           for (; isSPACE(*type); type++) ;
        }
        else {
-           while (tlen && isSPACE(type[tlen-1]))
-               type[--tlen] = '\0';
            name = type;
-           len = tlen;
+           len  = tend-type;
        }
-       mode[0] = mode[1] = mode[2] = mode[3] = '\0';
        IoTYPE(io) = *type;
-       if (*type == IoTYPE_RDWR && tlen > 1 && type[tlen-1] != IoTYPE_PIPE) { /* scary */
+       if (*type == IoTYPE_RDWR && (!num_svs || tend > type+1 && tend[-1] != IoTYPE_PIPE)) { /* scary */
            mode[1] = *type++;
-           --tlen;
            writing = 1;
        }
 
        if (*type == IoTYPE_PIPE) {
-           if (num_svs && (tlen != 2 || type[1] != IoTYPE_STD)) {
-             unknown_desr:
-               Perl_croak(aTHX_ "Unknown open() mode '%.*s'", (int)olen, oname);
+           if (num_svs) {
+               if (type[1] != IoTYPE_STD) {
+                 unknown_desr:
+                   Perl_croak(aTHX_ "Unknown open() mode '%.*s'", (int)olen, oname);
+               }
+               type++;
            }
            /*SUPPRESS 530*/
-           for (type++, tlen--; isSPACE(*type); type++, tlen--) ;
+           for (type++; isSPACE(*type); type++) ;
            if (!num_svs) {
                name = type;
-               len = tlen;
+               len = tend-type;
            }
            if (*name == '\0') { /* command is missing 19990114 */
                dTHR;
@@ -243,23 +235,19 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
            if (strNE(name,"-") || num_svs)
                TAINT_ENV();
            TAINT_PROPER("piped open");
-           if (name[len-1] == '|') {
+           if (!num_svs && name[len-1] == '|') {
                dTHR;
                name[--len] = '\0' ;
                if (ckWARN(WARN_PIPE))
                    Perl_warner(aTHX_ WARN_PIPE, "Can't open bidirectional pipe");
            }
-           {
-               char *mode;
-               if (out_raw)
-                   mode = "wb";
-               else if (out_crlf)
-                   mode = "wt";
-               else
-                   mode = "w";
-               fp = PerlProc_popen(name,mode);
-           }
+           mode[0] = 'w';
            writing = 1;
+           if (out_raw)
+               strcat(mode, "b");
+           else if (out_crlf)
+               strcat(mode, "t");
+           fp = PerlProc_popen(name,mode);
        }
        else if (*type == IoTYPE_WRONLY) {
            TAINT_PROPER("open");
@@ -268,7 +256,6 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
                /* Two IoTYPE_WRONLYs in a row make for an IoTYPE_APPEND. */
                mode[0] = IoTYPE(io) = IoTYPE_APPEND;
                type++;
-               tlen--;
            }
            else
                mode[0] = 'w';
@@ -279,11 +266,11 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
            else if (out_crlf)
                strcat(mode, "t");
 
-           if (num_svs && tlen != 1)
-               goto unknown_desr;
            if (*type == '&') {
                name = type;
              duplicity:
+               if (num_svs)
+                   goto unknown_desr;
                dodup = 1;
                name++;
                if (*name == '=') {
@@ -355,7 +342,9 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
            else {
                /*SUPPRESS 530*/
                for (; isSPACE(*type); type++) ;
-               if (*type == IoTYPE_STD && !type[1]) {
+               if (*type == IoTYPE_STD && (!type[1] || isSPACE(type[1]) || type[1] == ':')) {
+                   /*SUPPRESS 530*/
+                   type++;
                    fp = PerlIO_stdout();
                    IoTYPE(io) = IoTYPE_STD;
                }
@@ -365,8 +354,6 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
            }
        }
        else if (*type == IoTYPE_RDONLY) {
-           if (num_svs && tlen != 1)
-               goto unknown_desr;
            /*SUPPRESS 530*/
            for (type++; isSPACE(*type); type++) ;
            mode[0] = 'r';
@@ -379,25 +366,28 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
                name = type;
                goto duplicity;
            }
-           if (*type == IoTYPE_STD && !type[1]) {
+           if (*type == IoTYPE_STD && (!type[1] || isSPACE(type[1]) || type[1] == ':')) {
+               /*SUPPRESS 530*/
+               type++;
                fp = PerlIO_stdin();
                IoTYPE(io) = IoTYPE_STD;
            }
            else
                fp = PerlIO_open((num_svs ? name : type), mode);
        }
-       else if (tlen > 1 && type[tlen-1] == IoTYPE_PIPE) {
+       else if ((num_svs && type[0] == IoTYPE_STD && type[1] == IoTYPE_PIPE) ||
+                (!num_svs && tend > type+1 && tend[-1] == IoTYPE_PIPE)) {
            if (num_svs) {
-               if (tlen != 2 || type[0] != IoTYPE_STD)
-                   goto unknown_desr;
+               type += 2;   /* skip over '-|' */
            }
            else {
-               type[--tlen] = '\0';
-               while (tlen && isSPACE(type[tlen-1]))
-                   type[--tlen] = '\0';
+               *--tend = '\0';
+               while (tend > type && isSPACE(tend[-1]))
+                   *--tend = '\0';
                /*SUPPRESS 530*/
                for (; isSPACE(*type); type++) ;
                name = type;
+               len  = tend-type;
            }
            if (*name == '\0') { /* command is missing 19990114 */
                dTHR;
@@ -409,16 +399,12 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
            if (strNE(name,"-") || num_svs)
                TAINT_ENV();
            TAINT_PROPER("piped open");
-           {
-               char *mode;
-               if (in_raw)
-                   mode = "rb";
-               else if (in_crlf)
-                   mode = "rt";
-               else
-                   mode = "r";
-               fp = PerlProc_popen(name,mode);
-           }
+           mode[0] = 'r';
+           if (in_raw)
+               strcat(mode, "b");
+           else if (in_crlf)
+               strcat(mode, "t");
+           fp = PerlProc_popen(name,mode);
            IoTYPE(io) = IoTYPE_PIPE;
        }
        else {
@@ -428,18 +414,16 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
            IoTYPE(io) = IoTYPE_RDONLY;
            /*SUPPRESS 530*/
            for (; isSPACE(*name); name++) ;
+           mode[0] = 'r';
+           if (in_raw)
+               strcat(mode, "b");
+           else if (in_crlf)
+               strcat(mode, "t");
            if (strEQ(name,"-")) {
                fp = PerlIO_stdin();
                IoTYPE(io) = IoTYPE_STD;
            }
            else {
-               char *mode;
-               if (in_raw)
-                   mode = "rb";
-               else if (in_crlf)
-                   mode = "rt";
-               else
-                   mode = "r";
                fp = PerlIO_open(name,mode);
            }
        }
@@ -450,8 +434,7 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
            Perl_warner(aTHX_ WARN_NEWLINE, PL_warn_nl, "open");
        goto say_false;
     }
-    if (IoTYPE(io) &&
-      IoTYPE(io) != IoTYPE_PIPE && IoTYPE(io) != IoTYPE_STD) {
+    if (IoTYPE(io) && IoTYPE(io) != IoTYPE_PIPE && IoTYPE(io) != IoTYPE_STD) {
        dTHR;
        if (PerlLIO_fstat(PerlIO_fileno(fp),&PL_statbuf) < 0) {
            (void)PerlIO_close(fp);
@@ -480,13 +463,17 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
 #endif
     }
     if (saveifp) {             /* must use old fp? */
+        /* If fd is less that PL_maxsysfd i.e. STDIN..STDERR
+           then dup the new fileno down
+         */
        fd = PerlIO_fileno(saveifp);
        if (saveofp) {
-           PerlIO_flush(saveofp);              /* emulate PerlIO_close() */
+           PerlIO_flush(saveofp);      /* emulate PerlIO_close() */
            if (saveofp != saveifp) {   /* was a socket? */
                PerlIO_close(saveofp);
+                /* This looks very suspect - NI-S 24 Nov 2000 */
                if (fd > 2)
-                   Safefree(saveofp);
+                   Safefree(saveofp);  /* ??? */
            }
        }
        if (fd != PerlIO_fileno(fp)) {
@@ -519,25 +506,52 @@ Perl_do_open9(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
     }
 #endif
     IoIFP(io) = fp;
+    if (!num_svs) {
+       /* Need to supply default type info from open.pm */
+       SV *layers = PL_curcop->cop_io;
+       type = NULL;
+       if (layers) {
+           STRLEN len;
+           type = SvPV(layers,len);
+           if (type && mode[0] != 'r') {
+               /* Skip to write part */
+               char *s = strchr(type,0);
+               if (s && (s-type) < len) {
+                   type = s+1;
+               }
+           }
+       }
+    }
+    if (type) {
+       while (isSPACE(*type)) type++;
+       if (*type) {
+          if (PerlIO_apply_layers(aTHX_ IoIFP(io),mode,type) != 0) {
+               goto say_false;
+          }
+       }
+    }
+
     IoFLAGS(io) &= ~IOf_NOLINE;
     if (writing) {
        dTHR;
        if (IoTYPE(io) == IoTYPE_SOCKET
            || (IoTYPE(io) == IoTYPE_WRONLY && S_ISCHR(PL_statbuf.st_mode)) )
        {
-           char *mode;
-           if (out_raw)
-               mode = "wb";
-           else if (out_crlf)
-               mode = "wt";
-           else
-               mode = "w";
-
+           mode[0] = 'w';
            if (!(IoOFP(io) = PerlIO_fdopen(PerlIO_fileno(fp),mode))) {
                PerlIO_close(fp);
                IoIFP(io) = Nullfp;
                goto say_false;
            }
+           if (type && *type) {
+               if (PerlIO_apply_layers(aTHX_ IoOFP(io),mode,type) != 0) {
+                   PerlIO_close(IoOFP(io));
+                   PerlIO_close(fp);
+                   IoIFP(io) = Nullfp;
+                   IoOFP(io) = Nullfp;
+                   goto say_false;
+               }
+           }
        }
        else
            IoOFP(io) = fp;
@@ -649,7 +663,7 @@ Perl_nextargv(pTHX_ register GV *gv)
 #if !defined(DOSISH) && !defined(__CYGWIN__)
                    if (PerlLIO_rename(PL_oldname,SvPVX(sv)) < 0) {
                        if (ckWARN_d(WARN_INPLACE))     
-                           Perl_warner(aTHX_ WARN_INPLACE, 
+                           Perl_warner(aTHX_ WARN_INPLACE,
                              "Can't rename %s to %s: %s, skipping file",
                              PL_oldname, SvPVX(sv), Strerror(errno) );
                        do_close(gv,FALSE);
@@ -896,7 +910,7 @@ Perl_do_eof(pTHX_ GV *gv)
                 || IoIFP(io) == PerlIO_stderr()))
     {
        /* integrate to report_evil_fh()? */
-        char *name = NULL; 
+        char *name = NULL;
        if (isGV(gv)) {
            SV* sv = sv_newmortal();
            gv_efullname4(sv, gv, Nullch, FALSE);
@@ -922,6 +936,7 @@ Perl_do_eof(pTHX_ GV *gv)
            (void)PerlIO_ungetc(IoIFP(io),ch);
            return FALSE;
        }
+
         if (PerlIO_has_cntptr(IoIFP(io)) && PerlIO_canset_cnt(IoIFP(io))) {
            if (PerlIO_get_cnt(IoIFP(io)) < -1)
                PerlIO_set_cnt(IoIFP(io),-1);
@@ -1041,7 +1056,11 @@ fail_discipline:
                end = strchr(s+1, ':');
                if (!end)
                    end = s+len;
+#ifndef PERLIO_LAYERS
                Perl_croak(aTHX_ "Unknown discipline '%.*s'", end-s, s);
+#else
+               s = end;
+#endif
            }
        }
     }
@@ -1051,46 +1070,11 @@ fail_discipline:
 int
 Perl_do_binmode(pTHX_ PerlIO *fp, int iotype, int mode)
 {
-#ifdef DOSISH
-#  if defined(atarist) || defined(__MINT__)
-    if (!PerlIO_flush(fp)) {
-       if (mode & O_BINARY)
-           ((FILE*)fp)->_flag |= _IOBIN;
-       else
-           ((FILE*)fp)->_flag &= ~ _IOBIN;
-       return 1;
-    }
-    return 0;
-#  else
-    if (PerlLIO_setmode(PerlIO_fileno(fp), mode) != -1) {
-#    if defined(WIN32) && defined(__BORLANDC__)
-       /* The translation mode of the stream is maintained independent
-        * of the translation mode of the fd in the Borland RTL (heavy
-        * digging through their runtime sources reveal).  User has to
-        * set the mode explicitly for the stream (though they don't
-        * document this anywhere). GSAR 97-5-24
-        */
-       PerlIO_seek(fp,0L,0);
-       if (mode & O_BINARY)
-           ((FILE*)fp)->flags |= _F_BIN;
-       else
-           ((FILE*)fp)->flags &= ~ _F_BIN;
-#    endif
-       return 1;
-    }
-    else
-       return 0;
-#  endif
-#else
-#  if defined(USEMYBINMODE)
-    if (my_binmode(fp, iotype, mode) != FALSE)
-       return 1;
-    else
-       return 0;
-#  else
-    return 1;
-#  endif
-#endif
+ /* The old body of this is now in non-LAYER part of perlio.c
+  * This is a stub for any XS code which might have been calling it.
+  */
+ char *name = (O_BINARY != O_TEXT && !(mode & O_BINARY)) ? ":crlf" : ":raw";
+ return PerlIO_binmode(aTHX_ fp, iotype, mode, name);
 }
 
 #if !defined(HAS_TRUNCATE) && !defined(HAS_CHSIZE) && defined(F_FREESP)
@@ -1200,7 +1184,7 @@ Perl_do_print(pTHX_ register SV *sv, PerlIO *fp)
      * but only until the system hard limit/the filesystem limit,
      * at which we would get EPERM.  Note that when using buffered
      * io the write failure can be delayed until the flush/close. --jhi */
-    if (len && (PerlIO_write(fp,tmps,len) == 0 || PerlIO_error(fp)))
+    if (len && (PerlIO_write(fp,tmps,len) == 0))
        return FALSE;
     return !PerlIO_error(fp);
 }
@@ -1320,7 +1304,7 @@ Perl_do_aexec5(pTHX_ SV *really, register SV **mark, register SV **sp,
        else
            PerlProc_execvp(PL_Argv[0],PL_Argv);
        if (ckWARN(WARN_EXEC))
-           Perl_warner(aTHX_ WARN_EXEC, "Can't exec \"%s\": %s", 
+           Perl_warner(aTHX_ WARN_EXEC, "Can't exec \"%s\": %s",
                PL_Argv[0], Strerror(errno));
        if (do_report) {
            int e = errno;
@@ -1455,7 +1439,7 @@ Perl_do_exec3(pTHX_ char *cmd, int fd, int do_report)
            int e = errno;
 
            if (ckWARN(WARN_EXEC))
-               Perl_warner(aTHX_ WARN_EXEC, "Can't exec \"%s\": %s", 
+               Perl_warner(aTHX_ WARN_EXEC, "Can't exec \"%s\": %s",
                    PL_Argv[0], Strerror(errno));
            if (do_report) {
                PerlLIO_write(fd, (void*)&e, sizeof(int));
@@ -1530,7 +1514,7 @@ Perl_apply(pTHX_ I32 type, register SV **mark, register SV **sp)
        }
        break;
 #endif
-/* 
+/*
 XXX Should we make lchown() directly available from perl?
 For now, we'll let Configure test for HAS_LCHOWN, but do
 nothing in the core.
@@ -1955,7 +1939,7 @@ Perl_do_msgrcv(pTHX_ SV **mark, SV **sp)
     flags = SvIVx(*++mark);
     SvPV_force(mstr, len);
     mbuf = SvGROW(mstr, sizeof(long)+msize+1);
-    
+
     SETERRNO(0,0);
     ret = msgrcv(id, (struct msgbuf *)mbuf, msize, mtype, flags);
     if (ret >= 0) {
@@ -2056,3 +2040,4 @@ Perl_do_shmio(pTHX_ I32 optype, SV **mark, SV **sp)
 
 #endif /* SYSV IPC */
 
+