This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Most platforms don't actually need PL_pidstatus, or the associated
[perl5.git] / pp_sys.c
index fb508b5..19a735a 100644 (file)
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -87,7 +87,7 @@ extern int h_errno;
 #ifndef getpwent
   struct passwd *getpwent (void);
 #elif defined (VMS) && defined (my_getpwent)
-  struct passwd *Perl_my_getpwent (void);
+  struct passwd *Perl_my_getpwent (pTHX);
 #endif
 # endif
 #endif
@@ -201,6 +201,15 @@ void endservent(void);
 #undef PERL_EFF_ACCESS_W_OK
 #undef PERL_EFF_ACCESS_X_OK
 
+/* AIX 5.2 and below use mktime for localtime, and defines the edge case
+ * for time 0x7fffffff to be valid only in UTC. AIX 5.3 provides localtime64
+ * available in the 32bit environment, which could warrant Configure
+ * checks in the future.
+ */
+#ifdef  _AIX
+#define LOCALTIME_EDGECASE_BROKEN
+#endif
+
 /* F_OK unused: if stat() cannot find it... */
 
 #if !defined(PERL_EFF_ACCESS_R_OK) && defined(HAS_ACCESS) && defined(EFF_ONLY_OK) && !defined(NO_EFF_ONLY_OK)
@@ -321,7 +330,7 @@ PP(pp_backtick)
 {
     dSP; dTARGET;
     PerlIO *fp;
-    const char *tmps = POPpconstx;
+    const char * const tmps = POPpconstx;
     const I32 gimme = GIMME_V;
     const char *mode = "r";
 
@@ -330,7 +339,7 @@ PP(pp_backtick)
        mode = "rb";
     else if (PL_op->op_private & OPpOPEN_IN_CRLF)
        mode = "rt";
-    fp = PerlProc_popen((char*)tmps, (char *)mode);
+    fp = PerlProc_popen(tmps, mode);
     if (fp) {
         const char *type = NULL;
        if (PL_curcop->cop_io) {
@@ -342,7 +351,6 @@ PP(pp_backtick)
        if (gimme == G_VOID) {
            char tmpbuf[256];
            while (PerlIO_read(fp, tmpbuf, sizeof tmpbuf) > 0)
-               /*SUPPRESS 530*/
                ;
        }
        else if (gimme == G_SCALAR) {
@@ -351,17 +359,14 @@ PP(pp_backtick)
            PL_rs = &PL_sv_undef;
            sv_setpvn(TARG, "", 0);     /* note that this preserves previous buffer */
            while (sv_gets(TARG, fp, SvCUR(TARG)) != Nullch)
-               /*SUPPRESS 530*/
                ;
            LEAVE;
            XPUSHs(TARG);
            SvTAINTED_on(TARG);
        }
        else {
-           SV *sv;
-
            for (;;) {
-               sv = NEWSV(56, 79);
+               SV * const sv = NEWSV(56, 79);
                if (sv_gets(sv, fp, 0) == Nullch) {
                    SvREFCNT_dec(sv);
                    break;
@@ -373,11 +378,11 @@ PP(pp_backtick)
                SvTAINTED_on(sv);
            }
        }
-       STATUS_NATIVE_SET(PerlProc_pclose(fp));
+       STATUS_NATIVE_CHILD_SET(PerlProc_pclose(fp));
        TAINT;          /* "I believe that this is not gratuitous!" */
     }
     else {
-       STATUS_NATIVE_SET(-1);
+       STATUS_NATIVE_CHILD_SET(-1);
        if (gimme == G_SCALAR)
            RETPUSHUNDEF;
     }
@@ -447,7 +452,7 @@ PP(pp_warn)
     }
     tmps = SvPV_const(tmpsv, len);
     if ((!tmps || !len) && PL_errgv) {
-       SV *error = ERRSV;
+       SV * const error = ERRSV;
        SvUPGRADE(error, SVt_PV);
        if (SvPOK(error) && SvCUR(error))
            sv_catpv(error, "\t...caught");
@@ -506,13 +511,16 @@ PP(pp_die)
                    sv_setsv(error,*PL_stack_sp--);
                }
            }
-           DIE_NULL;
+           DIE(aTHX_ Nullch);
        }
        else {
            if (SvPOK(error) && SvCUR(error))
                sv_catpv(error, "\t...propagated");
            tmpsv = error;
-           tmps = SvPV_const(tmpsv, len);
+           if (SvOK(tmpsv))
+               tmps = SvPV_const(tmpsv, len);
+           else
+               tmps = Nullch;
        }
     }
     if (!tmps || !len)
@@ -559,11 +567,11 @@ PP(pp_open)
        sv = *++MARK;
     }
     else {
-       sv = GvSV(gv);
+       sv = GvSVn(gv);
     }
 
     tmps = SvPV_const(sv, len);
-    ok = do_openn(gv, (char *)tmps, len, FALSE, O_RDONLY, 0, Nullfp, MARK+1, (SP-MARK));
+    ok = do_openn(gv, tmps, len, FALSE, O_RDONLY, 0, Nullfp, MARK+1, (SP-MARK));
     SP = ORIGMARK;
     if (ok)
        PUSHi( (I32)PL_forkprocess );
@@ -884,7 +892,7 @@ PP(pp_untie)
        RETPUSHYES;
 
     if ((mg = SvTIED_mg(sv, how))) {
-       SV *obj = SvRV(SvTIED_obj(sv, mg));
+       SV * const obj = SvRV(SvTIED_obj(sv, mg));
        GV *gv;
        CV *cv = NULL;
         if (obj) {
@@ -899,8 +907,7 @@ PP(pp_untie)
               LEAVE;
               SPAGAIN;
             }
-           else if (ckWARN(WARN_UNTIE)) {
-              if (mg && SvREFCNT(obj) > 1)
+           else if (mg && SvREFCNT(obj) > 1 && ckWARN(WARN_UNTIE)) {
                  Perl_warner(aTHX_ packWARN(WARN_UNTIE),
                      "untie attempted while %"UVuf" inner references still exist",
                       (UV)SvREFCNT(obj) - 1 ) ;
@@ -914,7 +921,7 @@ PP(pp_untie)
 PP(pp_tied)
 {
     dSP;
-    MAGIC *mg;
+    const MAGIC *mg;
     SV *sv = POPs;
     const char how = (SvTYPE(sv) == SVt_PVHV || SvTYPE(sv) == SVt_PVAV)
                ? PERL_MAGIC_tied : PERL_MAGIC_tiedscalar;
@@ -935,13 +942,12 @@ PP(pp_tied)
 PP(pp_dbmopen)
 {
     dVAR; dSP;
-    HV *hv;
     dPOPPOPssrl;
     HV* stash;
     GV *gv;
     SV *sv;
 
-    hv = (HV*)POPs;
+    HV * const hv = (HV*)POPs;
 
     sv = sv_mortalcopy(&PL_sv_no);
     sv_setpv(sv, "AnyDBM_File");
@@ -1024,9 +1030,21 @@ PP(pp_sselect)
 
     SP -= 4;
     for (i = 1; i <= 3; i++) {
-       if (!SvPOK(SP[i]))
+       SV *sv = SP[i];
+       if (!SvOK(sv))
            continue;
-       j = SvCUR(SP[i]);
+       if (SvREADONLY(sv)) {
+           if (SvIsCOW(sv))
+               sv_force_normal_flags(sv, 0);
+           if (SvREADONLY(sv) && !(SvPOK(sv) && SvCUR(sv) == 0))
+               DIE(aTHX_ PL_no_modify);
+       }
+       if (!SvPOK(sv)) {
+           if (ckWARN(WARN_MISC))
+                Perl_warner(aTHX_ packWARN(WARN_MISC), "Non-string passed as bitmask");
+           SvPV_force_nolen(sv);       /* force string conversion */
+       }
+       j = SvCUR(sv);
        if (maxlen < j)
            maxlen = j;
     }
@@ -1075,12 +1093,11 @@ PP(pp_sselect)
 
     for (i = 1; i <= 3; i++) {
        sv = SP[i];
-       if (!SvOK(sv)) {
+       if (!SvOK(sv) || SvCUR(sv) == 0) {
            fd_sets[i] = 0;
            continue;
        }
-       else if (!SvPOK(sv))
-           SvPV_force_nolen(sv);       /* force string conversion */
+       assert(SvPOK(sv));
        j = SvLEN(sv);
        if (j < growsize) {
            Sv_Grow(sv, growsize);
@@ -1093,7 +1110,7 @@ PP(pp_sselect)
 
 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
        s = SvPVX(sv);
-       New(403, fd_sets[i], growsize, char);
+       Newx(fd_sets[i], growsize, char);
        for (offset = 0; offset < growsize; offset += masksize) {
            for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
                fd_sets[i][j+offset] = s[(k % masksize) + offset];
@@ -1135,10 +1152,7 @@ PP(pp_sselect)
        }
     }
 
-    if (nfound == -1)
-       PUSHs(&PL_sv_undef);
-    else
-       PUSHi(nfound);
+    PUSHi(nfound);
     if (GIMME == G_ARRAY && tbuf) {
        value = (NV)(timebuf.tv_sec) +
                (NV)(timebuf.tv_usec) / 1000000.0;
@@ -1176,7 +1190,7 @@ PP(pp_select)
     if (! hv)
        XPUSHs(&PL_sv_undef);
     else {
-       GV **gvp = (GV**)hv_fetch(hv, GvNAME(egv), GvNAMELEN(egv), FALSE);
+       GV ** const gvp = (GV**)hv_fetch(hv, GvNAME(egv), GvNAMELEN(egv), FALSE);
        if (gvp && *gvp == egv) {
            gv_efullname4(TARG, PL_defoutgv, Nullch, TRUE);
            XPUSHTARG;
@@ -1198,14 +1212,9 @@ PP(pp_select)
 PP(pp_getc)
 {
     dVAR; dSP; dTARGET;
-    GV *gv;
     IO *io = NULL;
     MAGIC *mg;
-
-    if (MAXARG == 0)
-       gv = PL_stdingv;
-    else
-       gv = (GV*)POPs;
+    GV * const gv = (MAXARG==0) ? PL_stdingv : (GV*)POPs;
 
     if (gv && (io = GvIO(gv))
        && (mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar)))
@@ -1223,8 +1232,8 @@ PP(pp_getc)
        RETURN;
     }
     if (!gv || do_eof(gv)) { /* make sure we have fp with something */
-       if (ckWARN2(WARN_UNOPENED,WARN_CLOSED)
-               && (!io || (!IoIFP(io) && IoTYPE(io) != IoTYPE_WRONLY)))
+       if ((!io || (!IoIFP(io) && IoTYPE(io) != IoTYPE_WRONLY))
+         && ckWARN2(WARN_UNOPENED,WARN_CLOSED))
            report_evil_fh(gv, io, PL_op->op_type);
        SETERRNO(EBADF,RMS_IFI);
        RETPUSHUNDEF;
@@ -1264,7 +1273,8 @@ S_doform(pTHX_ CV *cv, GV *gv, OP *retop)
     PUSHBLOCK(cx, CXt_FORMAT, PL_stack_sp);
     PUSHFORMAT(cx);
     cx->blk_sub.retop = retop;
-    PAD_SET_CUR(CvPADLIST(cv), 1);
+    SAVECOMPPAD();
+    PAD_SET_CUR_NOSAVE(CvPADLIST(cv), 1);
 
     setdefout(gv);         /* locally select filehandle so $% et al work */
     return CvSTART(cv);
@@ -1317,9 +1327,9 @@ PP(pp_enterwrite)
 PP(pp_leavewrite)
 {
     dVAR; dSP;
-    GV *gv = cxstack[cxstack_ix].blk_sub.gv;
-    register IO *io = GvIOp(gv);
-    PerlIO *ofp = IoOFP(io);
+    GV * const gv = cxstack[cxstack_ix].blk_sub.gv;
+    register IO * const io = GvIOp(gv);
+    PerlIO * const ofp = IoOFP(io);
     PerlIO *fp;
     SV **newsp;
     I32 gimme;
@@ -1336,9 +1346,9 @@ PP(pp_leavewrite)
        CV *cv;
        if (!IoTOP_GV(io)) {
            GV *topgv;
-           SV *topname;
 
            if (!IoTOP_NAME(io)) {
+               SV *topname;
                if (!IoFMT_NAME(io))
                    IoFMT_NAME(io) = savepv(GvNAME(gv));
                topname = sv_2mortal(Perl_newSVpvf(aTHX_ "%s_TOP", GvNAME(gv)));
@@ -1437,6 +1447,8 @@ PP(pp_leavewrite)
     /* bad_ofp: */
     PL_formtarget = PL_bodytarget;
     PUTBACK;
+    PERL_UNUSED_VAR(newsp);
+    PERL_UNUSED_VAR(gimme);
     return cx->blk_sub.retop;
 }
 
@@ -1517,21 +1529,16 @@ PP(pp_prtf)
 PP(pp_sysopen)
 {
     dSP;
-    GV *gv;
-    SV *sv;
-    const char *tmps;
-    STRLEN len;
     const int perm = (MAXARG > 3) ? POPi : 0666;
     const int mode = POPi;
-
-    sv = POPs;
-    gv = (GV *)POPs;
+    SV * const sv = POPs;
+    GV * const gv = (GV *)POPs;
+    STRLEN len;
 
     /* Need TIEHANDLE method ? */
-
-    tmps = SvPV_const(sv, len);
+    const char * const tmps = SvPV_const(sv, len);
     /* FIXME? do_open should do const  */
-    if (do_open(gv, (char*)tmps, len, TRUE, mode, perm, Nullfp)) {
+    if (do_open(gv, tmps, len, TRUE, mode, perm, Nullfp)) {
        IoLINES(GvIOp(gv)) = 0;
        PUSHs(&PL_sv_yes);
     }
@@ -1545,7 +1552,6 @@ PP(pp_sysread)
 {
     dVAR; dSP; dMARK; dORIGMARK; dTARGET;
     int offset;
-    GV *gv;
     IO *io;
     char *buffer;
     SSize_t length;
@@ -1553,7 +1559,6 @@ PP(pp_sysread)
     Sock_size_t bufsize;
     SV *bufsv;
     STRLEN blen;
-    MAGIC *mg;
     int fp_utf8;
     int buffer_utf8;
     SV *read_target;
@@ -1563,23 +1568,24 @@ PP(pp_sysread)
     STRLEN charskip = 0;
     STRLEN skip = 0;
 
-    gv = (GV*)*++MARK;
+    GV * const gv = (GV*)*++MARK;
     if ((PL_op->op_type == OP_READ || PL_op->op_type == OP_SYSREAD)
-       && gv && (io = GvIO(gv))
-       && (mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar)))
+       && gv && (io = GvIO(gv)) )
     {
-       SV *sv;
-       
-       PUSHMARK(MARK-1);
-       *MARK = SvTIED_obj((SV*)io, mg);
-       ENTER;
-       call_method("READ", G_SCALAR);
-       LEAVE;
-       SPAGAIN;
-       sv = POPs;
-       SP = ORIGMARK;
-       PUSHs(sv);
-       RETURN;
+       const MAGIC * mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar);
+       if (mg) {
+           SV *sv;
+           PUSHMARK(MARK-1);
+           *MARK = SvTIED_obj((SV*)io, mg);
+           ENTER;
+           call_method("READ", G_SCALAR);
+           LEAVE;
+           SPAGAIN;
+           sv = POPs;
+           SP = ORIGMARK;
+           PUSHs(sv);
+           RETURN;
+       }
     }
 
     if (!gv)
@@ -1966,7 +1972,7 @@ PP(pp_eof)
                if ((IoFLAGS(io) & IOf_START) && av_len(GvAVn(gv)) < 0) {
                    IoLINES(io) = 0;
                    IoFLAGS(io) &= ~IOf_START;
-                   do_open(gv, (char *)"-", 1, FALSE, O_RDONLY, 0, Nullfp);
+                   do_open(gv, "-", 1, FALSE, O_RDONLY, 0, Nullfp);
                    sv_setpvn(GvSV(gv), "-", 1);
                    SvSETMAGIC(GvSV(gv));
                }
@@ -2430,7 +2436,8 @@ PP(pp_bind)
     extern void GETUSERMODE();
 #endif
     SV *addrsv = POPs;
-    char *addr;
+    /* OK, so on what platform does bind modify addr?  */
+    const char *addr;
     GV *gv = (GV*)POPs;
     register IO *io = GvIOn(gv);
     STRLEN len;
@@ -2442,7 +2449,7 @@ PP(pp_bind)
     if (!io || !IoIFP(io))
        goto nuts;
 
-    addr = SvPV(addrsv, len);
+    addr = SvPV_const(addrsv, len);
     TAINT_PROPER("bind");
 #ifdef MPE /* Deal with MPE bind() peculiarities */
     if (((struct sockaddr *)addr)->sa_family == AF_INET) {
@@ -2485,7 +2492,7 @@ PP(pp_connect)
 #ifdef HAS_SOCKET
     dSP;
     SV *addrsv = POPs;
-    char *addr;
+    const char *addr;
     GV *gv = (GV*)POPs;
     register IO *io = GvIOn(gv);
     STRLEN len;
@@ -2493,7 +2500,7 @@ PP(pp_connect)
     if (!io || !IoIFP(io))
        goto nuts;
 
-    addr = SvPV(addrsv, len);
+    addr = SvPV_const(addrsv, len);
     TAINT_PROPER("connect");
     if (PerlSock_connect(PerlIO_fileno(IoIFP(io)), (struct sockaddr *)addr, len) >= 0)
        RETPUSHYES;
@@ -2680,16 +2687,30 @@ PP(pp_ssockopt)
        PUSHs(sv);
        break;
     case OP_SSOCKOPT: {
-           char *buf;
+#if defined(__SYMBIAN32__)
+# define SETSOCKOPT_OPTION_VALUE_T void *
+#else
+# define SETSOCKOPT_OPTION_VALUE_T const char *
+#endif
+       /* XXX TODO: We need to have a proper type (a Configure probe,
+        * etc.) for what the C headers think of the third argument of
+        * setsockopt(), the option_value read-only buffer: is it
+        * a "char *", or a "void *", const or not.  Some compilers
+        * don't take kindly to e.g. assuming that "char *" implicitly
+        * promotes to a "void *", or to explicitly promoting/demoting
+        * consts to non/vice versa.  The "const void *" is the SUS
+        * definition, but that does not fly everywhere for the above
+        * reasons. */
+           SETSOCKOPT_OPTION_VALUE_T buf;
            int aint;
            if (SvPOKp(sv)) {
                STRLEN l;
-               buf = SvPV(sv, l);
+               buf = (SETSOCKOPT_OPTION_VALUE_T) SvPV_const(sv, l);
                len = l;
            }
            else {
                aint = (int)SvIV(sv);
-               buf = (char*)&aint;
+               buf = (SETSOCKOPT_OPTION_VALUE_T) &aint;
                len = sizeof(int);
            }
            if (PerlSock_setsockopt(fd, lvl, optname, buf, len) < 0)
@@ -2753,8 +2774,8 @@ PP(pp_getpeername)
        {
            static const char nowhere[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
            /* If the call succeeded, make sure we don't have a zeroed port/addr */
-           if (((struct sockaddr *)SvPVX(sv))->sa_family == AF_INET &&
-               !memcmp((char *)SvPVX(sv) + sizeof(u_short), nowhere,
+           if (((struct sockaddr *)SvPVX_const(sv))->sa_family == AF_INET &&
+               !memcmp(SvPVX_const(sv) + sizeof(u_short), nowhere,
                        sizeof(u_short) + sizeof(struct in_addr))) {
                goto nuts2;     
            }
@@ -3349,7 +3370,7 @@ PP(pp_fttty)
     if (GvIO(gv) && IoIFP(GvIOp(gv)))
        fd = PerlIO_fileno(IoIFP(GvIOp(gv)));
     else if (tmpsv && SvOK(tmpsv)) {
-       char *tmps = SvPV_nolen(tmpsv);
+       const char *tmps = SvPV_nolen_const(tmpsv);
        if (isDIGIT(*tmps))
            fd = atoi(tmps);
        else 
@@ -3449,9 +3470,10 @@ PP(pp_fttext)
       really_filename:
        PL_statgv = Nullgv;
        PL_laststype = OP_STAT;
-       sv_setpv(PL_statname, SvPV_nolen(sv));
+       sv_setpv(PL_statname, SvPV_nolen_const(sv));
        if (!(fp = PerlIO_open(SvPVX_const(PL_statname), "r"))) {
-           if (ckWARN(WARN_NEWLINE) && strchr(SvPV_nolen(PL_statname), '\n'))
+           if (ckWARN(WARN_NEWLINE) && strchr(SvPV_nolen_const(PL_statname),
+                                              '\n'))
                Perl_warner(aTHX_ packWARN(WARN_NEWLINE), PL_warn_nl, "open");
            RETPUSHUNDEF;
        }
@@ -3535,19 +3557,30 @@ PP(pp_ftbinary)
 PP(pp_chdir)
 {
     dSP; dTARGET;
-    const char *tmps;
-    SV **svp;
+    const char *tmps = 0;
+    GV *gv = NULL;
 
-    if( MAXARG == 1 )
-        tmps = POPpconstx;
-    else
-        tmps = 0;
+    if( MAXARG == 1 ) {
+       SV * const sv = POPs;
+        if (SvTYPE(sv) == SVt_PVGV) {
+           gv = (GV*)sv;
+        }
+       else if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVGV) {
+            gv = (GV*)SvRV(sv);
+        }
+        else {
+           tmps = SvPVx_nolen_const(sv);
+       }
+    }
+
+    if( !gv && (!tmps || !*tmps) ) {
+       HV * const table = GvHVn(PL_envgv);
+       SV **svp;
 
-    if( !tmps || !*tmps ) {
-        if (    (svp = hv_fetch(GvHVn(PL_envgv), "HOME", 4, FALSE))
-             || (svp = hv_fetch(GvHVn(PL_envgv), "LOGDIR", 6, FALSE))
+        if (    (svp = hv_fetch(table, "HOME", 4, FALSE))
+             || (svp = hv_fetch(table, "LOGDIR", 6, FALSE))
 #ifdef VMS
-             || (svp = hv_fetch(GvHVn(PL_envgv), "SYS$LOGIN", 9, FALSE))
+             || (svp = hv_fetch(table, "SYS$LOGIN", 9, FALSE))
 #endif
            )
         {
@@ -3563,7 +3596,33 @@ PP(pp_chdir)
     }
 
     TAINT_PROPER("chdir");
-    PUSHi( PerlDir_chdir(tmps) >= 0 );
+    if (gv) {
+#ifdef HAS_FCHDIR
+       IO* const io = GvIO(gv);
+       if (io) {
+           if (IoIFP(io)) {
+               PUSHi(fchdir(PerlIO_fileno(IoIFP(io))) >= 0);
+           }
+           else if (IoDIRP(io)) {
+#ifdef HAS_DIRFD
+               PUSHi(fchdir(dirfd(IoDIRP(io))) >= 0);
+#else
+               DIE(aTHX_ PL_no_func, "dirfd");
+#endif
+           }
+           else {
+               PUSHi(0);
+           }
+        }
+       else {
+           PUSHi(0);
+       }
+#else
+       DIE(aTHX_ PL_no_func, "fchdir");
+#endif
+    }
+    else 
+        PUSHi( PerlDir_chdir(tmps) >= 0 );
 #ifdef VMS
     /* Clear the DEFAULT element of ENV so we'll get the new value
      * in the future. */
@@ -3717,7 +3776,7 @@ S_dooneliner(pTHX_ const char *cmd, const char *filename)
     PerlIO *myfp;
     int anum = 1;
 
-    New(666, cmdline, strlen(cmd) + (strlen(filename) * 2) + 10, char);
+    Newx(cmdline, strlen(cmd) + (strlen(filename) * 2) + 10, char);
     strcpy(cmdline, cmd);
     strcat(cmdline, " ");
     for (s = cmdline + strlen(cmdline); *filename; ) {
@@ -4061,7 +4120,6 @@ PP(pp_fork)
     if (childpid < 0)
        RETSETUNDEF;
     if (!childpid) {
-       /*SUPPRESS 560*/
        if ((tmpgv = gv_fetchpv("$", TRUE, SVt_PV))) {
             SvREADONLY_off(GvSV(tmpgv));
            sv_setiv(GvSV(tmpgv), (IV)PerlProc_getpid());
@@ -4070,7 +4128,9 @@ PP(pp_fork)
 #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
     }
     PUSHi(childpid);
     RETURN;
@@ -4109,9 +4169,9 @@ PP(pp_wait)
     }
 #  if defined(USE_ITHREADS) && defined(PERL_IMPLICIT_SYS)
     /* 0 and -1 are both error returns (the former applies to WNOHANG case) */
-    STATUS_NATIVE_SET((childpid && childpid != -1) ? argflags : -1);
+    STATUS_NATIVE_CHILD_SET((childpid && childpid != -1) ? argflags : -1);
 #  else
-    STATUS_NATIVE_SET((childpid > 0) ? argflags : -1);
+    STATUS_NATIVE_CHILD_SET((childpid > 0) ? argflags : -1);
 #  endif
     XPUSHi(childpid);
     RETURN;
@@ -4141,9 +4201,9 @@ PP(pp_waitpid)
     }
 #  if defined(USE_ITHREADS) && defined(PERL_IMPLICIT_SYS)
     /* 0 and -1 are both error returns (the former applies to WNOHANG case) */
-    STATUS_NATIVE_SET((result && result != -1) ? argflags : -1);
+    STATUS_NATIVE_CHILD_SET((result && result != -1) ? argflags : -1);
 #  else
-    STATUS_NATIVE_SET((result > 0) ? argflags : -1);
+    STATUS_NATIVE_CHILD_SET((result > 0) ? argflags : -1);
 #  endif
     SETi(result);
     RETURN;
@@ -4197,8 +4257,8 @@ PP(pp_system)
            if (did_pipes)
                PerlLIO_close(pp[1]);
 #ifndef PERL_MICRO
-           rsignal_save(SIGINT, SIG_IGN, &ihand);
-           rsignal_save(SIGQUIT, SIG_IGN, &qhand);
+           rsignal_save(SIGINT,  (Sighandler_t) SIG_IGN, &ihand);
+           rsignal_save(SIGQUIT, (Sighandler_t) SIG_IGN, &qhand);
 #endif
            do {
                result = wait4pid(childpid, &status, 0);
@@ -4207,7 +4267,7 @@ PP(pp_system)
            (void)rsignal_restore(SIGINT, &ihand);
            (void)rsignal_restore(SIGQUIT, &qhand);
 #endif
-           STATUS_NATIVE_SET(result == -1 ? -1 : status);
+           STATUS_NATIVE_CHILD_SET(result == -1 ? -1 : status);
            do_execfree();      /* free any memory child malloced on fork */
            SP = ORIGMARK;
            if (did_pipes) {
@@ -4227,7 +4287,7 @@ PP(pp_system)
                    if (n != sizeof(int))
                        DIE(aTHX_ "panic: kid popen errno read");
                    errno = errkid;             /* Propagate errno from kid */
-                   STATUS_CURRENT = -1;
+                   STATUS_NATIVE_CHILD_SET(-1);
                }
            }
            PUSHi(STATUS_CURRENT);
@@ -4255,14 +4315,14 @@ PP(pp_system)
     result = 0;
     if (PL_op->op_flags & OPf_STACKED) {
        SV *really = *++MARK;
-#  if defined(WIN32) || defined(OS2) || defined(SYMBIAN)
+#  if defined(WIN32) || defined(OS2) || defined(__SYMBIAN32__)
        value = (I32)do_aspawn(really, MARK, SP);
 #  else
        value = (I32)do_aspawn(really, (void **)MARK, (void **)SP);
 #  endif
     }
     else if (SP - MARK != 1) {
-#  if defined(WIN32) || defined(OS2) || defined(SYMBIAN)
+#  if defined(WIN32) || defined(OS2) || defined(__SYMBIAN32__)
        value = (I32)do_aspawn(Nullsv, MARK, SP);
 #  else
        value = (I32)do_aspawn(Nullsv, (void **)MARK, (void **)SP);
@@ -4273,7 +4333,7 @@ PP(pp_system)
     }
     if (PL_statusvalue == -1)  /* hint that value must be returned as is */
        result = 1;
-    STATUS_NATIVE_SET(value);
+    STATUS_NATIVE_CHILD_SET(value);
     do_execfree();
     SP = ORIGMARK;
     PUSHi(result ? value : STATUS_CURRENT);
@@ -4504,6 +4564,46 @@ PP(pp_localtime)
     return pp_gmtime();
 }
 
+#ifdef LOCALTIME_EDGECASE_BROKEN
+static struct tm *S_my_localtime (pTHX_ Time_t *tp)
+{
+    auto time_t     T;
+    auto struct tm *P;
+
+    /* No workarounds in the valid range */
+    if (!tp || *tp < 0x7fff573f || *tp >= 0x80000000)
+       return (localtime (tp));
+
+    /* This edge case is to workaround the undefined behaviour, where the
+     * TIMEZONE makes the time go beyond the defined range.
+     * gmtime (0x7fffffff) => 2038-01-19 03:14:07
+     * If there is a negative offset in TZ, like MET-1METDST, some broken
+     * implementations of localtime () (like AIX 5.2) barf with bogus
+     * return values:
+     * 0x7fffffff gmtime               2038-01-19 03:14:07
+     * 0x7fffffff localtime            1901-12-13 21:45:51
+     * 0x7fffffff mylocaltime          2038-01-19 04:14:07
+     * 0x3c19137f gmtime               2001-12-13 20:45:51
+     * 0x3c19137f localtime            2001-12-13 21:45:51
+     * 0x3c19137f mylocaltime          2001-12-13 21:45:51
+     * Given that legal timezones are typically between GMT-12 and GMT+12
+     * we turn back the clock 23 hours before calling the localtime
+     * function, and add those to the return value. This will never cause
+     * day wrapping problems, since the edge case is Tue Jan *19*
+     */
+    T = *tp - 82800; /* 23 hour. allows up to GMT-23 */
+    P = localtime (&T);
+    P->tm_hour += 23;
+    if (P->tm_hour >= 24) {
+       P->tm_hour -= 24;
+       P->tm_mday++;   /* 18  -> 19  */
+       P->tm_wday++;   /* Mon -> Tue */
+       P->tm_yday++;   /* 18  -> 19  */
+    }
+    return (P);
+} /* S_my_localtime */
+#endif
+
 PP(pp_gmtime)
 {
     dSP;
@@ -4525,7 +4625,11 @@ PP(pp_gmtime)
 #endif
 
     if (PL_op->op_type == OP_LOCALTIME)
+#ifdef LOCALTIME_EDGECASE_BROKEN
+       tmbuf = S_my_localtime(aTHX_ &when);
+#else
        tmbuf = localtime(&when);
+#endif
     else
        tmbuf = gmtime(&when);
 
@@ -4785,7 +4889,7 @@ PP(pp_ghostent)
            h_errno = PL_reentrant_buffer->_gethostent_errno;
 #   endif
 #endif
-           STATUS_NATIVE_SET(h_errno);
+           STATUS_UNIX_SET(h_errno);
        }
 #endif
 
@@ -4896,7 +5000,7 @@ PP(pp_gnetent)
             h_errno = PL_reentrant_buffer->_getnetent_errno;
 #   endif
 #endif
-           STATUS_NATIVE_SET(h_errno);
+           STATUS_UNIX_SET(h_errno);
        }
 #endif