I like doubleclicking on URLs in pods to select them.
[p5sagit/p5-mst-13.2.git] / doio.c
diff --git a/doio.c b/doio.c
index 32427eb..1495ff5 100644 (file)
--- a/doio.c
+++ b/doio.c
@@ -1,6 +1,6 @@
 /*    doio.c
  *
- *    Copyright (c) 1991-2001, Larry Wall
+ *    Copyright (c) 1991-2002, 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.
@@ -140,18 +140,44 @@ Perl_do_openn(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
     if (as_raw) {
         /* sysopen style args, i.e. integer mode and permissions */
        STRLEN ix = 0;
-       if (num_svs != 0) {
-            Perl_croak(aTHX_ "panic: sysopen with multiple args");
-       }
-       if (rawmode & (O_WRONLY|O_RDWR|O_CREAT
+       int appendtrunc =
+            0
 #ifdef O_APPEND        /* Not fully portable. */
-                      |O_APPEND
+            |O_APPEND
 #endif
 #ifdef O_TRUNC /* Not fully portable. */
-                      |O_TRUNC
+            |O_TRUNC
 #endif
-                      ))
-           TAINT_PROPER("sysopen");
+            ;
+       int modifyingmode =
+            O_WRONLY|O_RDWR|O_CREAT|appendtrunc;
+       int ismodifying;
+
+       if (num_svs != 0) {
+            Perl_croak(aTHX_ "panic: sysopen with multiple args");
+       }
+       /* It's not always
+
+          O_RDONLY 0
+          O_WRONLY 1
+          O_RDWR   2
+
+          It might be (in OS/390 and Mac OS Classic it is)
+
+          O_WRONLY 1
+          O_RDONLY 2
+          O_RDWR   3
+
+          This means that simple & with O_RDWR would look
+          like O_RDONLY is present.  Therefore we have to
+          be more careful.
+       */
+       if ((ismodifying = (rawmode & modifyingmode))) {
+            if ((ismodifying & O_WRONLY) == O_WRONLY ||
+                (ismodifying & O_RDWR)   == O_RDWR   ||
+                (ismodifying & (O_CREAT|appendtrunc)))
+                 TAINT_PROPER("sysopen");
+       }
        mode[ix++] = '#'; /* Marker to openn to use numeric "sysopen" */
 
 #if defined(USE_64_BIT_RAWIO) && defined(O_LARGEFILE)
@@ -222,7 +248,7 @@ Perl_do_openn(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
            if (*name == '\0') {
                /* command is missing 19990114 */
                if (ckWARN(WARN_PIPE))
-                   Perl_warner(aTHX_ WARN_PIPE, "Missing command in piped open");
+                   Perl_warner(aTHX_ packWARN(WARN_PIPE), "Missing command in piped open");
                errno = EPIPE;
                goto say_false;
            }
@@ -232,7 +258,7 @@ Perl_do_openn(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
            if (!num_svs && name[len-1] == '|') {
                name[--len] = '\0' ;
                if (ckWARN(WARN_PIPE))
-                   Perl_warner(aTHX_ WARN_PIPE, "Can't open bidirectional pipe");
+                   Perl_warner(aTHX_ packWARN(WARN_PIPE), "Can't open bidirectional pipe");
            }
            mode[0] = 'w';
            writing = 1;
@@ -429,7 +455,7 @@ Perl_do_openn(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
            if (*name == '\0') {
                /* command is missing 19990114 */
                if (ckWARN(WARN_PIPE))
-                   Perl_warner(aTHX_ WARN_PIPE, "Missing command in piped open");
+                   Perl_warner(aTHX_ packWARN(WARN_PIPE), "Missing command in piped open");
                errno = EPIPE;
                goto say_false;
            }
@@ -478,19 +504,19 @@ Perl_do_openn(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
     }
     if (!fp) {
        if (ckWARN(WARN_NEWLINE) && IoTYPE(io) == IoTYPE_RDONLY && strchr(name, '\n'))
-           Perl_warner(aTHX_ WARN_NEWLINE, PL_warn_nl, "open");
+           Perl_warner(aTHX_ packWARN(WARN_NEWLINE), PL_warn_nl, "open");
        goto say_false;
     }
 
     if (ckWARN(WARN_IO)) {
        if ((IoTYPE(io) == IoTYPE_RDONLY) &&
            (fp == PerlIO_stdout() || fp == PerlIO_stderr())) {
-               Perl_warner(aTHX_ WARN_IO,
+               Perl_warner(aTHX_ packWARN(WARN_IO),
                            "Filehandle STD%s opened only for input",
                            (fp == PerlIO_stdout()) ? "OUT" : "ERR");
        }
        else if ((IoTYPE(io) == IoTYPE_WRONLY) && fp == PerlIO_stdin()) {
-               Perl_warner(aTHX_ WARN_IO,
+               Perl_warner(aTHX_ packWARN(WARN_IO),
                            "Filehandle STDIN opened only for output");
        }
     }
@@ -546,8 +572,6 @@ Perl_do_openn(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
            }
        }
        if (savefd != fd) {
-           Pid_t pid;
-           SV *sv;
            /* Still a small can-of-worms here if (say) PerlIO::Scalar
               is assigned to (say) STDOUT - for now let dup2() fail
               and provide the error
@@ -558,25 +582,45 @@ Perl_do_openn(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
            }
 #ifdef VMS
            if (savefd != PerlIO_fileno(PerlIO_stdin())) {
-             char newname[FILENAME_MAX+1];
-             if (PerlIO_getname(fp, newname)) {
-               if (fd == PerlIO_fileno(PerlIO_stdout())) Perl_vmssetuserlnm(aTHX_ "SYS$OUTPUT", newname);
-               if (fd == PerlIO_fileno(PerlIO_stderr())) Perl_vmssetuserlnm(aTHX_ "SYS$ERROR",  newname);
-             }
+                char newname[FILENAME_MAX+1];
+                if (PerlIO_getname(fp, newname)) {
+                    if (fd == PerlIO_fileno(PerlIO_stdout()))
+                        Perl_vmssetuserlnm(aTHX_ "SYS$OUTPUT", newname);
+                    if (fd == PerlIO_fileno(PerlIO_stderr()))
+                        Perl_vmssetuserlnm(aTHX_ "SYS$ERROR",  newname);
+                }
            }
 #endif
-           LOCK_FDPID_MUTEX;
-           sv = *av_fetch(PL_fdpid,fd,TRUE);
-           (void)SvUPGRADE(sv, SVt_IV);
-           pid = SvIVX(sv);
-           SvIVX(sv) = 0;
-           sv = *av_fetch(PL_fdpid,savefd,TRUE);
-           UNLOCK_FDPID_MUTEX;
-           (void)SvUPGRADE(sv, SVt_IV);
-           SvIVX(sv) = pid;
-           if (!was_fdopen) {
-               PerlIO_close(fp);
+
+#if !defined(WIN32)
+           /* PL_fdpid isn't used on Windows, so avoid this useless work.
+            * XXX Probably the same for a lot of other places. */
+            {
+                Pid_t pid;
+                SV *sv;
+
+                LOCK_FDPID_MUTEX;
+                sv = *av_fetch(PL_fdpid,fd,TRUE);
+                (void)SvUPGRADE(sv, SVt_IV);
+                pid = SvIVX(sv);
+                SvIVX(sv) = 0;
+                sv = *av_fetch(PL_fdpid,savefd,TRUE);
+                (void)SvUPGRADE(sv, SVt_IV);
+                SvIVX(sv) = pid;
+                UNLOCK_FDPID_MUTEX;
+            }
+#endif
+
+           if (was_fdopen) {
+                /* need to close fp without closing underlying fd */
+                int ofd = PerlIO_fileno(fp);
+                int dupfd = PerlLIO_dup(ofd);
+                PerlIO_close(fp);
+                PerlLIO_dup2(dupfd,ofd);
+                PerlLIO_close(dupfd);
            }
+            else
+               PerlIO_close(fp);
        }
        fp = saveifp;
        PerlIO_clearerr(fp);
@@ -596,7 +640,7 @@ Perl_do_openn(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
        if (IoTYPE(io) == IoTYPE_SOCKET
            || (IoTYPE(io) == IoTYPE_WRONLY && fd >= 0 && S_ISCHR(PL_statbuf.st_mode)) ) {
            mode[0] = 'w';
-           if (!(IoOFP(io) = PerlIO_openn(aTHX_ type,mode,fd,0,0,NULL,num_svs,svp))) {
+           if (!(IoOFP(io) = PerlIO_openn(aTHX_ type,mode,fd,0,0,NULL,0,svp))) {
                PerlIO_close(fp);
                IoIFP(io) = Nullfp;
                goto say_false;
@@ -668,7 +712,7 @@ Perl_nextargv(pTHX_ register GV *gv)
                filegid = PL_statbuf.st_gid;
                if (!S_ISREG(PL_filemode)) {
                    if (ckWARN_d(WARN_INPLACE)) 
-                       Perl_warner(aTHX_ WARN_INPLACE,
+                       Perl_warner(aTHX_ packWARN(WARN_INPLACE),
                            "Can't do inplace edit: %s is not a regular file",
                            PL_oldname );
                    do_close(gv,FALSE);
@@ -700,7 +744,7 @@ Perl_nextargv(pTHX_ register GV *gv)
                       )
                    {
                        if (ckWARN_d(WARN_INPLACE))     
-                           Perl_warner(aTHX_ WARN_INPLACE,
+                           Perl_warner(aTHX_ packWARN(WARN_INPLACE),
                              "Can't do inplace edit: %s would not be unique",
                              SvPVX(sv));
                        do_close(gv,FALSE);
@@ -708,10 +752,10 @@ Perl_nextargv(pTHX_ register GV *gv)
                    }
 #endif
 #ifdef HAS_RENAME
-#if !defined(DOSISH) && !defined(__CYGWIN__)
+#if !defined(DOSISH) && !defined(__CYGWIN__) && !defined(EPOC)
                    if (PerlLIO_rename(PL_oldname,SvPVX(sv)) < 0) {
                        if (ckWARN_d(WARN_INPLACE))     
-                           Perl_warner(aTHX_ WARN_INPLACE,
+                           Perl_warner(aTHX_ packWARN(WARN_INPLACE),
                              "Can't rename %s to %s: %s, skipping file",
                              PL_oldname, SvPVX(sv), Strerror(errno) );
                        do_close(gv,FALSE);
@@ -727,7 +771,7 @@ Perl_nextargv(pTHX_ register GV *gv)
                    (void)UNLINK(SvPVX(sv));
                    if (link(PL_oldname,SvPVX(sv)) < 0) {
                        if (ckWARN_d(WARN_INPLACE))     
-                           Perl_warner(aTHX_ WARN_INPLACE,
+                           Perl_warner(aTHX_ packWARN(WARN_INPLACE),
                              "Can't rename %s to %s: %s, skipping file",
                              PL_oldname, SvPVX(sv), Strerror(errno) );
                        do_close(gv,FALSE);
@@ -741,7 +785,7 @@ Perl_nextargv(pTHX_ register GV *gv)
 #  ifndef VMS  /* Don't delete; use automatic file versioning */
                    if (UNLINK(PL_oldname) < 0) {
                        if (ckWARN_d(WARN_INPLACE))     
-                           Perl_warner(aTHX_ WARN_INPLACE,
+                           Perl_warner(aTHX_ packWARN(WARN_INPLACE),
                              "Can't remove %s: %s, skipping file",
                              PL_oldname, Strerror(errno) );
                        do_close(gv,FALSE);
@@ -765,7 +809,7 @@ Perl_nextargv(pTHX_ register GV *gv)
 #endif
                {
                    if (ckWARN_d(WARN_INPLACE)) 
-                       Perl_warner(aTHX_ WARN_INPLACE, "Can't do inplace edit on %s: %s",
+                       Perl_warner(aTHX_ packWARN(WARN_INPLACE), "Can't do inplace edit on %s: %s",
                          PL_oldname, Strerror(errno) );
                    do_close(gv,FALSE);
                    continue;
@@ -799,12 +843,12 @@ Perl_nextargv(pTHX_ register GV *gv)
                if (PerlLIO_stat(PL_oldname, &PL_statbuf) >= 0
                    && !S_ISREG(PL_statbuf.st_mode))    
                {
-                   Perl_warner(aTHX_ WARN_INPLACE,
+                   Perl_warner(aTHX_ packWARN(WARN_INPLACE),
                                "Can't do inplace edit: %s is not a regular file",
                                PL_oldname);
                }
                else
-                   Perl_warner(aTHX_ WARN_INPLACE, "Can't open %s: %s",
+                   Perl_warner(aTHX_ packWARN(WARN_INPLACE), "Can't open %s: %s",
                                PL_oldname, Strerror(eno));
            }
        }
@@ -971,7 +1015,7 @@ Perl_do_eof(pTHX_ GV *gv)
                PerlIO_set_cnt(IoIFP(io),-1);
        }
        if (PL_op->op_flags & OPf_SPECIAL) { /* not necessarily a real EOF yet? */
-           if (!nextargv(PL_argvgv))   /* get another fp handy */
+           if (gv != PL_argvgv || !nextargv(gv))       /* get another fp handy */
                return TRUE;
        }
        else
@@ -1197,9 +1241,9 @@ Perl_do_print(pTHX_ register SV *sv, PerlIO *fp)
        }
        else if (DO_UTF8(sv)) {
            if (!sv_utf8_downgrade((sv = sv_mortalcopy(sv)), TRUE)
-               && ckWARN(WARN_UTF8))
+               && ckWARN_d(WARN_UTF8))
            {
-               Perl_warner(aTHX_ WARN_UTF8, "Wide character in print");
+               Perl_warner(aTHX_ packWARN(WARN_UTF8), "Wide character in print");
            }
        }
        tmps = SvPV(sv, len);
@@ -1264,7 +1308,7 @@ Perl_my_stat(pTHX)
        PL_laststype = OP_STAT;
        PL_laststatval = PerlLIO_stat(s, &PL_statcache);
        if (PL_laststatval < 0 && ckWARN(WARN_NEWLINE) && strchr(s, '\n'))
-           Perl_warner(aTHX_ WARN_NEWLINE, PL_warn_nl, "stat");
+           Perl_warner(aTHX_ packWARN(WARN_NEWLINE), PL_warn_nl, "stat");
        return PL_laststatval;
     }
 }
@@ -1282,17 +1326,26 @@ Perl_my_lstat(pTHX)
                Perl_croak(aTHX_ "The stat preceding -l _ wasn't an lstat");
            return PL_laststatval;
        }
-       Perl_croak(aTHX_ "You can't use -l on a filehandle");
+       if (ckWARN(WARN_IO)) {
+           Perl_warner(aTHX_ packWARN(WARN_IO), "Use of -l on filehandle %s",
+                   GvENAME(cGVOP_gv));
+           return (PL_laststatval = -1);
+       }
     }
 
     PL_laststype = OP_LSTAT;
     PL_statgv = Nullgv;
     sv = POPs;
     PUTBACK;
+    if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVGV && ckWARN(WARN_IO)) {
+       Perl_warner(aTHX_ packWARN(WARN_IO), "Use of -l on filehandle %s",
+               GvENAME((GV*) SvRV(sv)));
+       return (PL_laststatval = -1);
+    }
     sv_setpv(PL_statname,SvPV(sv, n_a));
     PL_laststatval = PerlLIO_lstat(SvPV(sv, n_a),&PL_statcache);
     if (PL_laststatval < 0 && ckWARN(WARN_NEWLINE) && strchr(SvPV(sv, n_a), '\n'))
-       Perl_warner(aTHX_ WARN_NEWLINE, PL_warn_nl, "lstat");
+       Perl_warner(aTHX_ packWARN(WARN_NEWLINE), PL_warn_nl, "lstat");
     return PL_laststatval;
 }
 
@@ -1333,7 +1386,7 @@ Perl_do_aexec5(pTHX_ SV *really, register SV **mark, register SV **sp,
        else
            PerlProc_execvp(PL_Argv[0],EXEC_ARGV_CAST(PL_Argv));
        if (ckWARN(WARN_EXEC))
-           Perl_warner(aTHX_ WARN_EXEC, "Can't exec \"%s\": %s",
+           Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't exec \"%s\": %s",
                (really ? tmps : PL_Argv[0]), Strerror(errno));
        if (do_report) {
            int e = errno;
@@ -1471,7 +1524,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_ packWARN(WARN_EXEC), "Can't exec \"%s\": %s",
                    PL_Argv[0], Strerror(errno));
            if (do_report) {
                PerlLIO_write(fd, (void*)&e, sizeof(int));
@@ -2106,6 +2159,8 @@ Perl_do_shmio(pTHX_ I32 optype, SV **mark, SV **sp)
 #endif /* SYSV IPC */
 
 /*
+=head1 IO Functions
+
 =for apidoc start_glob
 
 Function called by C<do_readline> to spawn a glob (or do the glob inside