This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
$#a>>=1 relies on malloc wrap to avoid the segfault, so need to
[perl5.git] / doio.c
diff --git a/doio.c b/doio.c
index e2dcad8..70b3535 100644 (file)
--- a/doio.c
+++ b/doio.c
@@ -1,7 +1,7 @@
 /*    doio.c
  *
  *    Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- *    2000, 2001, 2002, 2003, by Larry Wall and others
+ *    2000, 2001, 2002, 2003, 2004, by Larry Wall and others
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
  * chattering, into calmer and more level reaches."
  */
 
+/* This file contains functions that do the actual I/O on behalf of ops.
+ * For example, pp_print() calls the do_print() function in this file for
+ * each argument needing printing.
+ */
+
 #include "EXTERN.h"
 #define PERL_IN_DOIO_C
 #include "perl.h"
@@ -48,9 +53,7 @@
 #  define OPEN_EXCL 0
 #endif
 
-#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
 #include <signal.h>
-#endif
 
 bool
 Perl_do_open(pTHX_ GV *gv, register char *name, I32 len, int as_raw,
@@ -725,11 +728,13 @@ Perl_nextargv(pTHX_ register GV *gv)
     if (PL_filemode & (S_ISUID|S_ISGID)) {
        PerlIO_flush(IoIFP(GvIOn(PL_argvoutgv)));  /* chmod must follow last write */
 #ifdef HAS_FCHMOD
-       (void)fchmod(PL_lastfd,PL_filemode);
+       if (PL_lastfd != -1)
+           (void)fchmod(PL_lastfd,PL_filemode);
 #else
        (void)PerlLIO_chmod(PL_oldname,PL_filemode);
 #endif
     }
+    PL_lastfd = -1;
     PL_filemode = 0;
     if (!GvAV(gv))
         return Nullfp;
@@ -1172,6 +1177,7 @@ fail_discipline:
 #ifndef PERLIO_LAYERS
                Perl_croak(aTHX_ "IO layers (like '%.*s') unavailable", end-s, s);
 #else
+               len -= end-s;
                s = end;
 #endif
            }
@@ -1270,7 +1276,7 @@ Perl_do_print(pTHX_ register SV *sv, PerlIO *fp)
     switch (SvTYPE(sv)) {
     case SVt_NULL:
        if (ckWARN(WARN_UNINITIALIZED))
-           report_uninit();
+           report_uninit(sv);
        return TRUE;
     case SVt_IV:
        if (SvIOK(sv)) {
@@ -1338,6 +1344,9 @@ Perl_my_stat(pTHX)
            return (PL_laststatval = -1);
        }
     }
+    else if (PL_op->op_private & OPpFT_STACKED) {
+       return PL_laststatval;
+    }
     else {
        SV* sv = POPs;
        char *s;
@@ -1364,6 +1373,8 @@ Perl_my_stat(pTHX)
     }
 }
 
+static char no_prev_lstat[] = "The stat preceding -l _ wasn't an lstat";
+
 I32
 Perl_my_lstat(pTHX)
 {
@@ -1374,7 +1385,7 @@ Perl_my_lstat(pTHX)
        EXTEND(SP,1);
        if (cGVOP_gv == PL_defgv) {
            if (PL_laststype != OP_LSTAT)
-               Perl_croak(aTHX_ "The stat preceding -l _ wasn't an lstat");
+               Perl_croak(aTHX_ no_prev_lstat);
            return PL_laststatval;
        }
        if (ckWARN(WARN_IO)) {
@@ -1383,6 +1394,9 @@ Perl_my_lstat(pTHX)
            return (PL_laststatval = -1);
        }
     }
+    else if (ckWARN(WARN_IO) && PL_laststype != OP_LSTAT
+           && (PL_op->op_private & OPpFT_STACKED))
+       Perl_croak(aTHX_ no_prev_lstat);
 
     PL_laststype = OP_LSTAT;
     PL_statgv = Nullgv;
@@ -1548,7 +1562,7 @@ Perl_do_exec3(pTHX_ char *cmd, int fd, int do_report)
 
                while (*t && isSPACE(*t))
                    ++t;
-               if (!*t && (dup2(1,2) != -1)) {
+               if (!*t && (PerlLIO_dup2(1,2) != -1)) {
                    s[-2] = '\0';
                    break;
                }
@@ -2290,8 +2304,9 @@ Perl_start_glob (pTHX_ SV *tmpglob, IO *io)
                if (*cp == '?') *cp = '%';  /* VMS style single-char wildcard */
            while (ok && ((sts = lib$find_file(&wilddsc,&rsdsc,&cxt,
                                               &dfltdsc,NULL,NULL,NULL))&1)) {
-               end = rstr + (unsigned long int) *rslt;
-               if (!hasver) while (*end != ';') end--;
+               /* with varying string, 1st word of buffer contains result length */
+               end = rstr + *((unsigned short int*)rslt);
+               if (!hasver) while (*end != ';' && end > rstr) end--;
                *(end++) = '\n';  *end = '\0';
                for (cp = rstr; *cp; cp++) *cp = _tolower(*cp);
                if (hasdir) {