This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Stop truncate(word) from falling back to file name
[perl5.git] / pp_sys.c
index 33b86ab..a17227d 100644 (file)
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -363,7 +363,7 @@ PP(pp_glob)
      * is called once and only once */
     if (SvGMAGICAL(TOPm1s)) TOPm1s = sv_2mortal(newSVsv(TOPm1s));
 
-    tryAMAGICunTARGET(iter_amg, -1, (PL_op->op_flags & OPf_SPECIAL));
+    tryAMAGICunTARGETlist(iter_amg, -1, (PL_op->op_flags & OPf_SPECIAL));
 
     if (PL_op->op_flags & OPf_SPECIAL) {
        /* call Perl-level glob function instead. Stack args are:
@@ -438,20 +438,29 @@ PP(pp_warn)
     }
     else {
        exsv = TOPs;
+       if (SvGMAGICAL(exsv)) exsv = sv_mortalcopy(exsv);
     }
 
     if (SvROK(exsv) || (SvPV_const(exsv, len), len)) {
        /* well-formed exception supplied */
     }
-    else if (SvROK(ERRSV)) {
-       exsv = ERRSV;
-    }
-    else if (SvPOK(ERRSV) && SvCUR(ERRSV)) {
-       exsv = sv_mortalcopy(ERRSV);
-       sv_catpvs(exsv, "\t...caught");
-    }
     else {
+      SvGETMAGIC(ERRSV);
+      if (SvROK(ERRSV)) {
+       if (SvGMAGICAL(ERRSV)) {
+           exsv = sv_newmortal();
+           sv_setsv_nomg(exsv, ERRSV);
+       }
+       else exsv = ERRSV;
+      }
+      else if (SvPOKp(ERRSV) ? SvCUR(ERRSV) : SvNIOKp(ERRSV)) {
+       exsv = sv_newmortal();
+       sv_setsv_nomg(exsv, ERRSV);
+       sv_catpvs(exsv, "\t...caught");
+      }
+      else {
        exsv = newSVpvs_flags("Warning: something's wrong", SVs_TEMP);
+      }
     }
     if (SvROK(exsv) && !PL_warnhook)
         Perl_warn(aTHX_ "%"SVf, SVfARG(exsv));
@@ -500,7 +509,7 @@ PP(pp_die)
            }
        }
     }
-    else if (SvPOK(ERRSV) && SvCUR(ERRSV)) {
+    else if (SvPV_const(ERRSV, len), len) {
        exsv = sv_mortalcopy(ERRSV);
        sv_catpvs(exsv, "\t...propagated");
     }
@@ -1227,7 +1236,8 @@ void
 Perl_setdefout(pTHX_ GV *gv)
 {
     dVAR;
-    SvREFCNT_inc_simple_void(gv);
+    PERL_ARGS_ASSERT_SETDEFOUT;
+    SvREFCNT_inc_simple_void_NN(gv);
     SvREFCNT_dec(PL_defoutgv);
     PL_defoutgv = gv;
 }
@@ -1360,21 +1370,16 @@ PP(pp_enterwrite)
     else
        fgv = gv;
 
-    if (!fgv)
-       goto not_a_format_reference;
+    assert(fgv);
 
     cv = GvFORM(fgv);
     if (!cv) {
        tmpsv = sv_newmortal();
        gv_efullname4(tmpsv, fgv, NULL, FALSE);
-       if (SvPOK(tmpsv) && *SvPV_nolen_const(tmpsv))
-           DIE(aTHX_ "Undefined format \"%"SVf"\" called", SVfARG(tmpsv));
-
-       not_a_format_reference:
-       DIE(aTHX_ "Not a format reference");
+       DIE(aTHX_ "Undefined format \"%"SVf"\" called", SVfARG(tmpsv));
     }
     IoFLAGS(io) &= ~IOf_DIDTOP;
-    return doform(cv,gv,PL_op->op_next);
+    RETURNOP(doform(cv,gv,PL_op->op_next));
 }
 
 PP(pp_leavewrite)
@@ -1389,6 +1394,12 @@ PP(pp_leavewrite)
     register PERL_CONTEXT *cx;
     OP *retop;
 
+    /* I'm not sure why, but executing the format leaves an extra value on the
+     * stack. There's probably a better place to be handling this (probably
+     * by avoiding pushing it in the first place!) but I don't quite know
+     * where to look. -doy */
+    (void)POPs;
+
     if (!io || !(ofp = IoOFP(io)))
         goto forget_top;
 
@@ -1456,12 +1467,9 @@ PP(pp_leavewrite)
        if (!cv) {
            SV * const sv = sv_newmortal();
            gv_efullname4(sv, fgv, NULL, FALSE);
-           if (SvPOK(sv) && *SvPV_nolen_const(sv))
-               DIE(aTHX_ "Undefined top format \"%"SVf"\" called", SVfARG(sv));
-           else
-               DIE(aTHX_ "Undefined top format called");
+           DIE(aTHX_ "Undefined top format \"%"SVf"\" called", SVfARG(sv));
        }
-       return doform(cv, gv, PL_op);
+       RETURNOP(doform(cv, gv, PL_op));
     }
 
   forget_top:
@@ -1495,10 +1503,9 @@ PP(pp_leavewrite)
     }
     /* bad_ofp: */
     PL_formtarget = PL_bodytarget;
-    PUTBACK;
     PERL_UNUSED_VAR(newsp);
     PERL_UNUSED_VAR(gimme);
-    return retop;
+    RETURNOP(retop);
 }
 
 PP(pp_prtf)
@@ -1623,6 +1630,8 @@ PP(pp_sysread)
     if (! SvOK(bufsv))
        sv_setpvs(bufsv, "");
     length = SvIVx(*++MARK);
+    if (length < 0)
+       DIE(aTHX_ "Negative length");
     SETERRNO(0,0);
     if (MARK < SP)
        offset = SvIVx(*++MARK);
@@ -1644,13 +1653,19 @@ PP(pp_sysread)
        buffer = SvPV_force(bufsv, blen);
        buffer_utf8 = !IN_BYTES && SvUTF8(bufsv);
     }
-    if (length < 0)
-       DIE(aTHX_ "Negative length");
-    wanted = length;
+    if (DO_UTF8(bufsv)) {
+       /* offset adjust in characters not bytes */
+        /* SV's length cache is only safe for non-magical values */
+        if (SvGMAGICAL(bufsv))
+            blen = utf8_length((const U8 *)buffer, (const U8 *)buffer + blen);
+        else
+            blen = sv_len_utf8(bufsv);
+    }
 
     charstart = TRUE;
     charskip  = 0;
     skip = 0;
+    wanted = length;
 
 #ifdef HAS_SOCKET
     if (PL_op->op_type == OP_RECV) {
@@ -1693,10 +1708,6 @@ PP(pp_sysread)
        RETURN;
     }
 #endif
-    if (DO_UTF8(bufsv)) {
-       /* offset adjust in characters not bytes */
-       blen = sv_len_utf8(bufsv);
-    }
     if (offset < 0) {
        if (-offset > (SSize_t)blen)
            DIE(aTHX_ "Offset outside string");
@@ -1704,7 +1715,7 @@ PP(pp_sysread)
     }
     if (DO_UTF8(bufsv)) {
        /* convert offset-as-chars to offset-as-bytes */
-       if (offset >= (int)blen)
+       if (offset >= (SSize_t)blen)
            offset += SvCUR(bufsv) - blen;
        else
            offset = utf8_hop((U8 *)buffer,offset) - (U8 *) buffer;
@@ -2204,9 +2215,9 @@ PP(pp_truncate)
        GV *tmpgv;
        IO *io;
 
-       if ((tmpgv = PL_op->op_flags & OPf_SPECIAL
-                      ? gv_fetchsv(sv, 0, SVt_PVIO)
-                      : MAYBE_DEREF_GV(sv) )) {
+       if (PL_op->op_flags & OPf_SPECIAL
+                      ? (tmpgv = gv_fetchsv(sv, 0, SVt_PVIO), 1)
+                      : !!(tmpgv = MAYBE_DEREF_GV(sv)) ) {
            io = GvIO(tmpgv);
            if (!io)
                result = 0;
@@ -2812,6 +2823,7 @@ PP(pp_stat)
             goto do_fstat_have_io; 
         }
         
+       SvTAINTED_off(PL_statname); /* previous tainting irrelevant */
        sv_setpv(PL_statname, SvPV_nomg_const_nolen(sv));
        PL_statgv = NULL;
        PL_laststype = PL_op->op_type;
@@ -2909,7 +2921,7 @@ S_ft_stacking_return_false(pTHX_ SV *ret) {
     while (OP_IS_FILETEST(next->op_type)
        && next->op_private & OPpFT_STACKED)
        next = next->op_next;
-    if (PL_op->op_flags & OPf_REF) PUSHs(ret);
+    if (PL_op->op_flags & OPf_REF) XPUSHs(ret);
     else                          SETs(ret);
     PUTBACK;
     return next;
@@ -2919,15 +2931,15 @@ S_ft_stacking_return_false(pTHX_ SV *ret) {
     STMT_START {                                     \
        if (PL_op->op_private & OPpFT_STACKING)        \
            return S_ft_stacking_return_false(aTHX_ X); \
-       RETURNX(PUSHs(X));                               \
+       RETURNX(PL_op->op_flags & OPf_REF ? XPUSHs(X) : SETs(X)); \
     } STMT_END
 #define FT_RETURN_TRUE(X)               \
     RETURNX((void)(                      \
-       PL_op->op_private & OPpFT_STACKING \
-           ? PL_op->op_flags & OPf_REF     \
-               ? PUSHs((SV *)cGVOP_gv)      \
-               : 0                           \
-           : PUSHs(X)                         \
+       PL_op->op_flags & OPf_REF          \
+           ? (bool)XPUSHs(                 \
+               PL_op->op_private & OPpFT_STACKING ? (SV *)cGVOP_gv : (X) \
+             )                                                           \
+           : (PL_op->op_private & OPpFT_STACKING || SETs(X))             \
     ))
 
 #define FT_RETURNNO    FT_RETURN_FALSE(&PL_sv_no)
@@ -2961,8 +2973,6 @@ S_try_amagic_ftest(pTHX_ char chr) {
        if (!tmpsv)
            return NULL;
 
-       SPAGAIN;
-
        if (SvTRUE(tmpsv)) FT_RETURN_TRUE(tmpsv);
        FT_RETURN_FALSE(tmpsv);
     }
@@ -3057,7 +3067,7 @@ PP(pp_ftrread)
 
     if (use_access) {
 #if defined(HAS_ACCESS) || defined (PERL_EFF_ACCESS)
-       const char *name = POPpx;
+       const char *name = TOPpx;
        if (effective) {
 #  ifdef PERL_EFF_ACCESS
            result = PERL_EFF_ACCESS(name, access_mode);
@@ -3074,15 +3084,14 @@ PP(pp_ftrread)
 #  endif
        }
        if (result == 0)
-           RETPUSHYES;
+           FT_RETURNYES;
        if (result < 0)
-           RETPUSHUNDEF;
-       RETPUSHNO;
+           FT_RETURNUNDEF;
+       FT_RETURNNO;
 #endif
     }
 
     result = my_stat_flags(0);
-    SPAGAIN;
     if (result < 0)
        FT_RETURNUNDEF;
     if (cando(stat_mode, effective, &PL_statcache))
@@ -3108,7 +3117,6 @@ PP(pp_ftis)
     tryAMAGICftest_MG(opchar);
 
     result = my_stat_flags(0);
-    SPAGAIN;
     if (result < 0)
        FT_RETURNUNDEF;
     if (op_type == OP_FTIS)
@@ -3171,37 +3179,30 @@ PP(pp_ftrowned)
        system these days.  */
 #ifndef S_ISUID
     if(PL_op->op_type == OP_FTSUID) {
-       if ((PL_op->op_flags & OPf_REF) == 0 && !(PL_op->op_private & OPpFT_STACKING))
-           (void) POPs;
        FT_RETURNNO;
     }
 #endif
 #ifndef S_ISGID
     if(PL_op->op_type == OP_FTSGID) {
-       if ((PL_op->op_flags & OPf_REF) == 0 && !(PL_op->op_private & OPpFT_STACKING))
-           (void) POPs;
        FT_RETURNNO;
     }
 #endif
 #ifndef S_ISVTX
     if(PL_op->op_type == OP_FTSVTX) {
-       if ((PL_op->op_flags & OPf_REF) == 0 && !(PL_op->op_private & OPpFT_STACKING))
-           (void) POPs;
        FT_RETURNNO;
     }
 #endif
 
     result = my_stat_flags(0);
-    SPAGAIN;
     if (result < 0)
        FT_RETURNUNDEF;
     switch (PL_op->op_type) {
     case OP_FTROWNED:
-       if (PL_statcache.st_uid == PL_uid)
+       if (PL_statcache.st_uid == PerlProc_getuid())
            FT_RETURNYES;
        break;
     case OP_FTEOWNED:
-       if (PL_statcache.st_uid == PL_euid)
+       if (PL_statcache.st_uid == PerlProc_geteuid())
            FT_RETURNYES;
        break;
     case OP_FTZERO:
@@ -3262,7 +3263,6 @@ PP(pp_ftlink)
 
     tryAMAGICftest_MG('l');
     result = my_lstat_flags(0);
-    SPAGAIN;
 
     if (result < 0)
        FT_RETURNUNDEF;
@@ -3285,7 +3285,7 @@ PP(pp_fttty)
     if (PL_op->op_flags & OPf_REF)
        gv = cGVOP_gv;
     else {
-      SV *tmpsv = PL_op->op_private & OPpFT_STACKING ? TOPs : POPs;
+      SV *tmpsv = TOPs;
       if (!(gv = MAYBE_DEREF_GV_nomg(tmpsv))) {
        name = SvPV_nomg(tmpsv, namelen);
        gv = gv_fetchpvn_flags(name, namelen, SvUTF8(tmpsv), SVt_PVIO);
@@ -3328,16 +3328,13 @@ PP(pp_fttext)
     tryAMAGICftest_MG(PL_op->op_type == OP_FTTEXT ? 'T' : 'B');
 
     if (PL_op->op_flags & OPf_REF)
-    {
        gv = cGVOP_gv;
-       EXTEND(SP, 1);
-    }
-    else {
-      sv = PL_op->op_private & OPpFT_STACKING ? TOPs : POPs;
-      if ((PL_op->op_private & (OPpFT_STACKED|OPpFT_AFTER_t))
+    else if ((PL_op->op_private & (OPpFT_STACKED|OPpFT_AFTER_t))
             == OPpFT_STACKED)
        gv = PL_defgv;
-      else gv = MAYBE_DEREF_GV_nomg(sv);
+    else {
+       sv = TOPs;
+       gv = MAYBE_DEREF_GV_nomg(sv);
     }
 
     if (gv) {
@@ -3585,7 +3582,7 @@ PP(pp_rename)
        if (same_dirent(tmps2, tmps))   /* can always rename to same name */
            anum = 1;
        else {
-           if (PL_euid || PerlLIO_stat(tmps2, &PL_statbuf) < 0 || !S_ISDIR(PL_statbuf.st_mode))
+           if (PerlProc_geteuid() || PerlLIO_stat(tmps2, &PL_statbuf) < 0 || !S_ISDIR(PL_statbuf.st_mode))
                (void)UNLINK(tmps2);
            if (!(anum = link(tmps, tmps2)))
                anum = UNLINK(tmps);
@@ -4036,10 +4033,31 @@ PP(pp_fork)
 #ifdef HAS_FORK
     dVAR; dSP; dTARGET;
     Pid_t childpid;
+#if defined(HAS_SIGPROCMASK) && !defined(PERL_MICRO)
+    sigset_t oldmask, newmask;
+#endif
 
     EXTEND(SP, 1);
     PERL_FLUSHALL_FOR_CHILD;
+#if defined(HAS_SIGPROCMASK) && !defined(PERL_MICRO)
+    sigfillset(&newmask);
+    sigprocmask(SIG_SETMASK, &newmask, &oldmask);
+#endif
     childpid = PerlProc_fork();
+    if (childpid == 0) {
+       int sig;
+       PL_sig_pending = 0;
+       if (PL_psig_pend)
+           for (sig = 1; sig < SIG_SIZE; sig++)
+               PL_psig_pend[sig] = 0;
+    }
+#if defined(HAS_SIGPROCMASK) && !defined(PERL_MICRO)
+    {
+       dSAVE_ERRNO;
+       sigprocmask(SIG_SETMASK, &oldmask, NULL);
+       RESTORE_ERRNO;
+    }
+#endif
     if (childpid < 0)
        RETSETUNDEF;
     if (!childpid) {
@@ -5443,7 +5461,7 @@ PP(pp_syscall)
     register I32 items = SP - MARK;
     unsigned long a[20];
     register I32 i = 0;
-    I32 retval = -1;
+    IV retval = -1;
 
     if (PL_tainting) {
        while (++MARK <= SP) {
@@ -5657,8 +5675,8 @@ lockf_emulate_flock(int fd, int operation)
  * Local variables:
  * c-indentation-style: bsd
  * c-basic-offset: 4
- * indent-tabs-mode: t
+ * indent-tabs-mode: nil
  * End:
  *
- * ex: set ts=8 sts=4 sw=4 noet:
+ * ex: set ts=8 sts=4 sw=4 et:
  */