Compress::Zlib 1.35
[p5sagit/p5-mst-13.2.git] / mg.c
diff --git a/mg.c b/mg.c
index 6d82070..e9faf1b 100644 (file)
--- a/mg.c
+++ b/mg.c
@@ -52,7 +52,11 @@ tie.
 #  include <sys/pstat.h>
 #endif
 
+#if defined(HAS_SIGACTION) && defined(SA_SIGINFO)
+Signal_t Perl_csighandler(int sig, ...);
+#else
 Signal_t Perl_csighandler(int sig);
+#endif
 
 #ifdef __Lynx__
 /* Missing protos on LynxOS */
@@ -1184,7 +1188,7 @@ Perl_magic_getsig(pTHX_ SV *sv, MAGIC *mg)
            if (PL_sig_handlers_initted && PL_sig_defaulting[i]) sigstate = SIG_DFL;
 #endif
            /* cache state so we don't fetch it again */
-           if(sigstate == SIG_IGN)
+           if(sigstate == (Sighandler_t) SIG_IGN)
                sv_setpv(sv,"IGNORE");
            else
                sv_setsv(sv,&PL_sv_undef);
@@ -1241,7 +1245,7 @@ Perl_magic_clearsig(pTHX_ SV *sv, MAGIC *mg)
            PL_sig_defaulting[i] = 1;
            (void)rsignal(i, PL_csighandlerp);
 #else
-           (void)rsignal(i, SIG_DFL);
+           (void)rsignal(i, (Sighandler_t) SIG_DFL);
 #endif
            if(PL_psig_name[i]) {
                SvREFCNT_dec(PL_psig_name[i]);
@@ -1270,7 +1274,11 @@ S_raise_signal(pTHX_ int sig)
 }
 
 Signal_t
+#if defined(HAS_SIGACTION) && defined(SA_SIGINFO)
+Perl_csighandler(int sig, ...)
+#else
 Perl_csighandler(int sig)
+#endif
 {
 #ifdef PERL_GET_SIG_CONTEXT
     dTHXa(PERL_GET_SIG_CONTEXT);
@@ -1419,7 +1427,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
            PL_sig_ignoring[i] = 1;
            (void)rsignal(i, PL_csighandlerp);
 #else
-           (void)rsignal(i, SIG_IGN);
+           (void)rsignal(i, (Sighandler_t) SIG_IGN);
 #endif
        }
     }
@@ -1431,7 +1439,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
            (void)rsignal(i, PL_csighandlerp);
          }
 #else
-           (void)rsignal(i, SIG_DFL);
+           (void)rsignal(i, (Sighandler_t) SIG_DFL);
 #endif
     }
     else {
@@ -1913,7 +1921,7 @@ int
 Perl_magic_gettaint(pTHX_ SV *sv, MAGIC *mg)
 {
     PERL_UNUSED_ARG(sv);
-    TAINT_IF(mg->mg_len & 1);
+    TAINT_IF((PL_localizing != 1) && (mg->mg_len & 1));
     return 0;
 }
 
@@ -1921,10 +1929,13 @@ int
 Perl_magic_settaint(pTHX_ SV *sv, MAGIC *mg)
 {
     PERL_UNUSED_ARG(sv);
-    if (PL_tainted)
-       mg->mg_len |= 1;
-    else
-       mg->mg_len &= ~1;
+    /* update taint status unless we're restoring at scope exit */
+    if (PL_localizing != 2) {
+       if (PL_tainted)
+           mg->mg_len |= 1;
+       else
+           mg->mg_len &= ~1;
+    }
     return 0;
 }
 
@@ -2017,7 +2028,7 @@ Perl_vivify_defelem(pTHX_ SV *sv)
        if ((I32)LvTARGLEN(sv) < 0 && (I32)LvTARGOFF(sv) > AvFILL(av))
            LvTARG(sv) = Nullsv;        /* array can't be extended */
        else {
-           SV** svp = av_fetch(av, LvTARGOFF(sv), TRUE);
+           SV** const svp = av_fetch(av, LvTARGOFF(sv), TRUE);
            if (!svp || (value = *svp) == &PL_sv_undef)
                Perl_croak(aTHX_ PL_no_aelem, (I32)LvTARGOFF(sv));
        }
@@ -2217,6 +2228,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
     case '\011':       /* ^I */ /* NOT \t in EBCDIC */
        Safefree(PL_inplace);
        PL_inplace = SvOK(sv) ? savesvpv(sv) : Nullch;
+       break;
     case '\017':       /* ^O */
        if (*(mg->mg_ptr+1) == '\0') {
            Safefree(PL_osname);
@@ -2609,7 +2621,11 @@ Perl_whichsig(pTHX_ const char *sig)
 }
 
 Signal_t
+#if defined(HAS_SIGACTION) && defined(SA_SIGINFO)
+Perl_sighandler(int sig, ...)
+#else
 Perl_sighandler(int sig)
+#endif
 {
 #ifdef PERL_GET_SIG_CONTEXT
     dTHXa(PERL_GET_SIG_CONTEXT);
@@ -2679,6 +2695,36 @@ Perl_sighandler(int sig)
     PUSHSTACKi(PERLSI_SIGNAL);
     PUSHMARK(SP);
     PUSHs(sv);
+#if defined(HAS_SIGACTION) && defined(SA_SIGINFO)
+    {
+        struct sigaction oact;
+
+        if (sigaction(sig, 0, &oact) == 0 && oact.sa_flags & SA_SIGINFO) {
+             siginfo_t *sip;
+             va_list args;
+
+             va_start(args, sig);
+             sip = (siginfo_t*)va_arg(args, siginfo_t*);
+             if (sip) {
+                  HV *sih = newHV();
+                  SV *rv  = newRV_noinc((SV*)sih);
+                  /* The siginfo fields signo, code, errno, pid, uid,
+                   * addr, status, and band are defined by POSIX/SUSv3. */
+                  hv_store(sih, "signo",   5, newSViv(sip->si_signo),  0);
+                  hv_store(sih, "code",    4, newSViv(sip->si_code),   0);
+                  hv_store(sih, "errno",   5, newSViv(sip->si_errno),  0);
+                  hv_store(sih, "uid",     3, newSViv(sip->si_uid),    0);
+                  hv_store(sih, "pid",     3, newSViv(sip->si_pid),    0);
+                  hv_store(sih, "addr",    4, newSVuv(PTR2UV(sip->si_addr)),   0);
+                  hv_store(sih, "status",  6, newSViv(sip->si_status), 0);
+                  hv_store(sih, "band",    4, newSViv(sip->si_band),   0);
+                  EXTEND(SP, 2);
+                  PUSHs((SV*)rv);
+                  PUSHs(newSVpv((void*)sip, sizeof(*sip)));
+             }
+        }
+    }
+#endif
     PUTBACK;
 
     call_sv((SV*)cv, G_DISCARD|G_EVAL);