This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perldelta for #112962, reg_temp_copy and null offs
[perl5.git] / pp_sys.c
index 1a84e10..8ef1df7 100644 (file)
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -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)
@@ -2341,7 +2348,7 @@ PP(pp_flock)
     dVAR; dSP; dTARGET;
     I32 value;
     const int argtype = POPi;
-    GV * const gv = (MAXARG == 0) ? PL_last_in_gv : MUTABLE_GV(POPs);
+    GV * const gv = MUTABLE_GV(POPs);
     IO *const io = GvIO(gv);
     PerlIO *const fp = io ? IoIFP(io) : NULL;
 
@@ -2752,7 +2759,7 @@ PP(pp_stat)
     dVAR;
     dSP;
     GV *gv = NULL;
-    IO *io;
+    IO *io = NULL;
     I32 gimme;
     I32 max = 13;
     SV* sv;
@@ -2774,28 +2781,33 @@ PP(pp_stat)
        }
 
        if (gv != PL_defgv) {
+           bool havefp;
+          do_fstat_have_io:
+           havefp = FALSE;
            PL_laststype = OP_STAT;
-           PL_statgv = gv;
+           PL_statgv = gv ? gv : (GV *)io;
            sv_setpvs(PL_statname, "");
             if(gv) {
                 io = GvIO(gv);
-                do_fstat_have_io:
-                if (io) {
+           }
+            if (io) {
                     if (IoIFP(io)) {
                         PL_laststatval = 
                             PerlLIO_fstat(PerlIO_fileno(IoIFP(io)), &PL_statcache);   
+                        havefp = TRUE;
                     } else if (IoDIRP(io)) {
                         PL_laststatval =
                             PerlLIO_fstat(my_dirfd(IoDIRP(io)), &PL_statcache);
+                        havefp = TRUE;
                     } else {
                         PL_laststatval = -1;
                     }
-               }
             }
+           else PL_laststatval = -1;
+           if (PL_laststatval < 0 && !havefp) report_evil_fh(gv);
         }
 
        if (PL_laststatval < 0) {
-           report_evil_fh(gv);
            max = 0;
        }
     }
@@ -2804,9 +2816,6 @@ PP(pp_stat)
             io = MUTABLE_IO(SvRV(sv));
             if (PL_op->op_type == OP_LSTAT)
                 goto do_fstat_warning_check;
-           PL_laststype = OP_STAT;
-           PL_statgv = (GV *)io;
-           sv_setpvs(PL_statname, "");
             goto do_fstat_have_io; 
         }
         
@@ -2893,21 +2902,61 @@ PP(pp_stat)
     RETURN;
 }
 
+/* If the next filetest is stacked up with this one
+   (PL_op->op_private & OPpFT_STACKING), we leave
+   the original argument on the stack for success,
+   and skip the stacked operators on failure.
+   The next few macros/functions take care of this.
+*/
+
+static OP *
+S_ft_stacking_return_false(pTHX_ SV *ret) {
+    dSP;
+    OP *next = NORMAL;
+    while (OP_IS_FILETEST(next->op_type)
+       && next->op_private & OPpFT_STACKED)
+       next = next->op_next;
+    if (PL_op->op_flags & OPf_REF) XPUSHs(ret);
+    else                          SETs(ret);
+    PUTBACK;
+    return next;
+}
+
+#define FT_RETURN_FALSE(X)                          \
+    STMT_START {                                     \
+       if (PL_op->op_private & OPpFT_STACKING)        \
+           return S_ft_stacking_return_false(aTHX_ X); \
+       RETURNX(PL_op->op_flags & OPf_REF ? XPUSHs(X) : SETs(X)); \
+    } STMT_END
+#define FT_RETURN_TRUE(X)               \
+    RETURNX((void)(                      \
+       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)
+#define FT_RETURNUNDEF FT_RETURN_FALSE(&PL_sv_undef)
+#define FT_RETURNYES   FT_RETURN_TRUE(&PL_sv_yes)
+
 #define tryAMAGICftest_MG(chr) STMT_START { \
        if ( (SvFLAGS(TOPs) & (SVf_ROK|SVs_GMG)) \
-               && PL_op->op_flags & OPf_KIDS    \
-               && S_try_amagic_ftest(aTHX_ chr)) \
-           return NORMAL; \
+               && PL_op->op_flags & OPf_KIDS) {     \
+           OP *next = S_try_amagic_ftest(aTHX_ chr);   \
+           if (next) return next;                        \
+       }                                                  \
     } STMT_END
 
-STATIC bool
+STATIC OP *
 S_try_amagic_ftest(pTHX_ char chr) {
     dVAR;
     dSP;
     SV* const arg = TOPs;
 
     assert(chr != '?');
-    SvGETMAGIC(arg);
+    if (!(PL_op->op_private & OPpFT_STACKING)) SvGETMAGIC(arg);
 
     if (SvAMAGIC(TOPs))
     {
@@ -2917,33 +2966,15 @@ S_try_amagic_ftest(pTHX_ char chr) {
                                ftest_amg, AMGf_unary);
 
        if (!tmpsv)
-           return FALSE;
-
-       SPAGAIN;
+           return NULL;
 
-       if (PL_op->op_private & OPpFT_STACKING) {
-           if (SvTRUE(tmpsv))
-               /* leave the object alone */
-               return TRUE;
-       }
-
-       SETs(tmpsv);
-       PUTBACK;
-       return TRUE;
+       if (SvTRUE(tmpsv)) FT_RETURN_TRUE(tmpsv);
+       FT_RETURN_FALSE(tmpsv);
     }
-    return FALSE;
+    return NULL;
 }
 
 
-/* This macro is used by the stacked filetest operators :
- * if the previous filetest failed, short-circuit and pass its value.
- * Else, discard it from the stack and continue. --rgs
- */
-#define STACKED_FTEST_CHECK if (PL_op->op_private & OPpFT_STACKED) { \
-       if (!SvTRUE(TOPs)) { RETURN; } \
-       else { (void)POPs; PUTBACK; } \
-    }
-
 PP(pp_ftrread)
 {
     dVAR;
@@ -2979,8 +3010,6 @@ PP(pp_ftrread)
     }
     tryAMAGICftest_MG(opchar);
 
-    STACKED_FTEST_CHECK;
-
     switch (PL_op->op_type) {
     case OP_FTRREAD:
 #if !(defined(HAS_ACCESS) && defined(R_OK))
@@ -3033,7 +3062,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);
@@ -3050,20 +3079,19 @@ 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)
-       RETPUSHUNDEF;
+       FT_RETURNUNDEF;
     if (cando(stat_mode, effective, &PL_statcache))
-       RETPUSHYES;
-    RETPUSHNO;
+       FT_RETURNYES;
+    FT_RETURNNO;
 }
 
 PP(pp_ftis)
@@ -3083,14 +3111,11 @@ PP(pp_ftis)
     }
     tryAMAGICftest_MG(opchar);
 
-    STACKED_FTEST_CHECK;
-
     result = my_stat_flags(0);
-    SPAGAIN;
     if (result < 0)
-       RETPUSHUNDEF;
+       FT_RETURNUNDEF;
     if (op_type == OP_FTIS)
-       RETPUSHYES;
+       FT_RETURNYES;
     {
        /* You can't dTARGET inside OP_FTIS, because you'll get
           "panic: pad_sv po" - the op is not flagged to have a target.  */
@@ -3098,23 +3123,28 @@ PP(pp_ftis)
        switch (op_type) {
        case OP_FTSIZE:
 #if Off_t_size > IVSIZE
-           PUSHn(PL_statcache.st_size);
+           sv_setnv(TARG, (NV)PL_statcache.st_size);
 #else
-           PUSHi(PL_statcache.st_size);
+           sv_setiv(TARG, (IV)PL_statcache.st_size);
 #endif
            break;
        case OP_FTMTIME:
-           PUSHn( (((NV)PL_basetime - PL_statcache.st_mtime)) / 86400.0 );
+           sv_setnv(TARG,
+                   ((NV)PL_basetime - PL_statcache.st_mtime) / 86400.0 );
            break;
        case OP_FTATIME:
-           PUSHn( (((NV)PL_basetime - PL_statcache.st_atime)) / 86400.0 );
+           sv_setnv(TARG,
+                   ((NV)PL_basetime - PL_statcache.st_atime) / 86400.0 );
            break;
        case OP_FTCTIME:
-           PUSHn( (((NV)PL_basetime - PL_statcache.st_ctime)) / 86400.0 );
+           sv_setnv(TARG,
+                   ((NV)PL_basetime - PL_statcache.st_ctime) / 86400.0 );
            break;
        }
+       SvSETMAGIC(TARG);
+       if (SvTRUE_nomg(TARG)) FT_RETURN_TRUE(TARG);
+       else                   FT_RETURN_FALSE(TARG);
     }
-    RETURN;
 }
 
 PP(pp_ftrowned)
@@ -3140,93 +3170,84 @@ PP(pp_ftrowned)
     }
     tryAMAGICftest_MG(opchar);
 
-    STACKED_FTEST_CHECK;
-
     /* I believe that all these three are likely to be defined on most every
        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_STACKED) == 0)
-           (void) POPs;
-       RETPUSHNO;
+       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_STACKED) == 0)
-           (void) POPs;
-       RETPUSHNO;
+       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_STACKED) == 0)
-           (void) POPs;
-       RETPUSHNO;
+       FT_RETURNNO;
     }
 #endif
 
     result = my_stat_flags(0);
-    SPAGAIN;
     if (result < 0)
-       RETPUSHUNDEF;
+       FT_RETURNUNDEF;
     switch (PL_op->op_type) {
     case OP_FTROWNED:
-       if (PL_statcache.st_uid == PL_uid)
-           RETPUSHYES;
+       if (PL_statcache.st_uid == PerlProc_getuid())
+           FT_RETURNYES;
        break;
     case OP_FTEOWNED:
-       if (PL_statcache.st_uid == PL_euid)
-           RETPUSHYES;
+       if (PL_statcache.st_uid == PerlProc_geteuid())
+           FT_RETURNYES;
        break;
     case OP_FTZERO:
        if (PL_statcache.st_size == 0)
-           RETPUSHYES;
+           FT_RETURNYES;
        break;
     case OP_FTSOCK:
        if (S_ISSOCK(PL_statcache.st_mode))
-           RETPUSHYES;
+           FT_RETURNYES;
        break;
     case OP_FTCHR:
        if (S_ISCHR(PL_statcache.st_mode))
-           RETPUSHYES;
+           FT_RETURNYES;
        break;
     case OP_FTBLK:
        if (S_ISBLK(PL_statcache.st_mode))
-           RETPUSHYES;
+           FT_RETURNYES;
        break;
     case OP_FTFILE:
        if (S_ISREG(PL_statcache.st_mode))
-           RETPUSHYES;
+           FT_RETURNYES;
        break;
     case OP_FTDIR:
        if (S_ISDIR(PL_statcache.st_mode))
-           RETPUSHYES;
+           FT_RETURNYES;
        break;
     case OP_FTPIPE:
        if (S_ISFIFO(PL_statcache.st_mode))
-           RETPUSHYES;
+           FT_RETURNYES;
        break;
 #ifdef S_ISUID
     case OP_FTSUID:
        if (PL_statcache.st_mode & S_ISUID)
-           RETPUSHYES;
+           FT_RETURNYES;
        break;
 #endif
 #ifdef S_ISGID
     case OP_FTSGID:
        if (PL_statcache.st_mode & S_ISGID)
-           RETPUSHYES;
+           FT_RETURNYES;
        break;
 #endif
 #ifdef S_ISVTX
     case OP_FTSVTX:
        if (PL_statcache.st_mode & S_ISVTX)
-           RETPUSHYES;
+           FT_RETURNYES;
        break;
 #endif
     }
-    RETPUSHNO;
+    FT_RETURNNO;
 }
 
 PP(pp_ftlink)
@@ -3236,15 +3257,13 @@ PP(pp_ftlink)
     I32 result;
 
     tryAMAGICftest_MG('l');
-    STACKED_FTEST_CHECK;
     result = my_lstat_flags(0);
-    SPAGAIN;
 
     if (result < 0)
-       RETPUSHUNDEF;
+       FT_RETURNUNDEF;
     if (S_ISLNK(PL_statcache.st_mode))
-       RETPUSHYES;
-    RETPUSHNO;
+       FT_RETURNYES;
+    FT_RETURNNO;
 }
 
 PP(pp_fttty)
@@ -3258,12 +3277,10 @@ PP(pp_fttty)
 
     tryAMAGICftest_MG('t');
 
-    STACKED_FTEST_CHECK;
-
     if (PL_op->op_flags & OPf_REF)
        gv = cGVOP_gv;
     else {
-      SV *tmpsv = 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);
@@ -3275,10 +3292,10 @@ PP(pp_fttty)
     else if (name && isDIGIT(*name))
            fd = atoi(name);
     else
-       RETPUSHUNDEF;
+       FT_RETURNUNDEF;
     if (PerlLIO_isatty(fd))
-       RETPUSHYES;
-    RETPUSHNO;
+       FT_RETURNYES;
+    FT_RETURNNO;
 }
 
 #if defined(atarist) /* this will work with atariST. Configure will
@@ -3305,16 +3322,15 @@ PP(pp_fttext)
 
     tryAMAGICftest_MG(PL_op->op_type == OP_FTTEXT ? 'T' : 'B');
 
-    STACKED_FTEST_CHECK;
-
     if (PL_op->op_flags & OPf_REF)
-    {
        gv = cGVOP_gv;
-       EXTEND(SP, 1);
-    }
-    else if (PL_op->op_private & OPpFT_STACKED)
+    else if ((PL_op->op_private & (OPpFT_STACKED|OPpFT_AFTER_t))
+            == OPpFT_STACKED)
        gv = PL_defgv;
-    else sv = POPs, gv = MAYBE_DEREF_GV_nomg(sv);
+    else {
+       sv = TOPs;
+       gv = MAYBE_DEREF_GV_nomg(sv);
+    }
 
     if (gv) {
        if (gv == PL_defgv) {
@@ -3323,7 +3339,6 @@ PP(pp_fttext)
                    ? (IO *)PL_statgv
                    : GvIO(PL_statgv);
            else {
-               sv = PL_statname;
                goto really_filename;
            }
        }
@@ -3333,18 +3348,18 @@ PP(pp_fttext)
            io = GvIO(PL_statgv);
        }
        PL_laststatval = -1;
+       PL_laststype = OP_STAT;
        if (io && IoIFP(io)) {
            if (! PerlIO_has_base(IoIFP(io)))
                DIE(aTHX_ "-T and -B not implemented on filehandles");
            PL_laststatval = PerlLIO_fstat(PerlIO_fileno(IoIFP(io)), &PL_statcache);
-           PL_laststype = OP_STAT;
            if (PL_laststatval < 0)
-               RETPUSHUNDEF;
+               FT_RETURNUNDEF;
            if (S_ISDIR(PL_statcache.st_mode)) { /* handle NFS glitch */
                if (PL_op->op_type == OP_FTTEXT)
-                   RETPUSHNO;
+                   FT_RETURNNO;
                else
-                   RETPUSHYES;
+                   FT_RETURNYES;
             }
            if (PerlIO_get_cnt(IoIFP(io)) <= 0) {
                i = PerlIO_getc(IoIFP(io));
@@ -3352,7 +3367,7 @@ PP(pp_fttext)
                    (void)PerlIO_ungetc(IoIFP(io),i);
            }
            if (PerlIO_get_cnt(IoIFP(io)) <= 0) /* null file is anything */
-               RETPUSHYES;
+               FT_RETURNYES;
            len = PerlIO_get_bufsiz(IoIFP(io));
            s = (STDCHAR *) PerlIO_get_base(IoIFP(io));
            /* sfio can have large buffers - limit to 512 */
@@ -3360,34 +3375,39 @@ PP(pp_fttext)
                len = 512;
        }
        else {
+           SETERRNO(EBADF,RMS_IFI);
            report_evil_fh(gv);
            SETERRNO(EBADF,RMS_IFI);
-           RETPUSHUNDEF;
+           FT_RETURNUNDEF;
        }
     }
     else {
+       sv_setpv(PL_statname, SvPV_nomg_const_nolen(sv));
       really_filename:
        PL_statgv = NULL;
-       PL_laststype = OP_STAT;
-       sv_setpv(PL_statname, SvPV_nomg_const_nolen(sv));
        if (!(fp = PerlIO_open(SvPVX_const(PL_statname), "r"))) {
+           if (!gv) {
+               PL_laststatval = -1;
+               PL_laststype = OP_STAT;
+           }
            if (ckWARN(WARN_NEWLINE) && strchr(SvPV_nolen_const(PL_statname),
                                               '\n'))
                Perl_warner(aTHX_ packWARN(WARN_NEWLINE), PL_warn_nl, "open");
-           RETPUSHUNDEF;
+           FT_RETURNUNDEF;
        }
+       PL_laststype = OP_STAT;
        PL_laststatval = PerlLIO_fstat(PerlIO_fileno(fp), &PL_statcache);
        if (PL_laststatval < 0) {
            (void)PerlIO_close(fp);
-           RETPUSHUNDEF;
+           FT_RETURNUNDEF;
        }
        PerlIO_binmode(aTHX_ fp, '<', O_BINARY, NULL);
        len = PerlIO_read(fp, tbuf, sizeof(tbuf));
        (void)PerlIO_close(fp);
        if (len <= 0) {
            if (S_ISDIR(PL_statcache.st_mode) && PL_op->op_type == OP_FTTEXT)
-               RETPUSHNO;              /* special case NFS directories */
-           RETPUSHYES;         /* null file is anything */
+               FT_RETURNNO;            /* special case NFS directories */
+           FT_RETURNYES;               /* null file is anything */
        }
        s = tbuf;
     }
@@ -3441,9 +3461,9 @@ PP(pp_fttext)
     }
 
     if ((odd * 3 > len) == (PL_op->op_type == OP_FTTEXT)) /* allow 1/3 odd */
-       RETPUSHNO;
+       FT_RETURNNO;
     else
-       RETPUSHYES;
+       FT_RETURNYES;
 }
 
 /* File calls. */
@@ -3557,7 +3577,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);
@@ -4008,16 +4028,34 @@ 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) {
-#ifdef THREADS_HAVE_PIDS
-       PL_ppid = (IV)getppid();
-#endif
 #ifdef PERL_USES_PL_PIDSTATUS
        hv_clear(PL_pidstatus); /* no kids, so don't wait for 'em */
 #endif
@@ -4193,7 +4231,7 @@ PP(pp_system)
                PerlLIO_close(pp[0]);
                if (n) {                        /* Error */
                    if (n != sizeof(int))
-                       DIE(aTHX_ "panic: kid popen errno read");
+                       DIE(aTHX_ "panic: kid popen errno read, n=%u", n);
                    errno = errkid;             /* Propagate errno from kid */
                    STATUS_NATIVE_CHILD_SET(-1);
                }
@@ -4308,14 +4346,7 @@ PP(pp_getppid)
 {
 #ifdef HAS_GETPPID
     dVAR; dSP; dTARGET;
-#   ifdef THREADS_HAVE_PIDS
-    if (PL_ppid != 1 && getppid() == 1)
-       /* maybe the parent process has died. Refresh ppid cache */
-       PL_ppid = 1;
-    XPUSHi( PL_ppid );
-#   else
     XPUSHi( getppid() );
-#   endif
     RETURN;
 #else
     DIE(aTHX_ PL_no_func, "getppid");
@@ -5639,8 +5670,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:
  */