This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Merge the implementations of 2 sets of POSIX functions.
[perl5.git] / ext / POSIX / POSIX.xs
index 14b24ff..50498ea 100644 (file)
@@ -160,9 +160,6 @@ char *tzname[] = { "" , "" };
 #  define ttyname(a) (char*)not_here("ttyname")
 #  define sigset_t long
 #  define pid_t long
-#  ifdef __BORLANDC__
-#    define tzname _tzname
-#  endif
 #  ifdef _MSC_VER
 #    define mode_t short
 #  endif
@@ -216,6 +213,160 @@ char *tzname[] = { "" , "" };
 #endif /* WIN32 || NETWARE */
 #endif /* __VMS */
 
+#ifdef WIN32
+   /* Perl on Windows assigns WSAGetLastError() return values to errno
+    * (in win32/win32sck.c).  Therefore we need to map these values
+    * back to standard symbolic names, but only for those names having
+    * no existing value or an existing value >= 100. (VC++ 2010 defines
+    * a group of names with values >= 100 in its errno.h which we *do*
+    * need to redefine.) The Errno.pm module does a similar mapping.
+    */
+#  ifdef EWOULDBLOCK
+#    undef EWOULDBLOCK
+#  endif
+#  define EWOULDBLOCK WSAEWOULDBLOCK
+#  ifdef EINPROGRESS
+#    undef EINPROGRESS
+#  endif
+#  define EINPROGRESS WSAEINPROGRESS
+#  ifdef EALREADY
+#    undef EALREADY
+#  endif
+#  define EALREADY WSAEALREADY
+#  ifdef ENOTSOCK
+#    undef ENOTSOCK
+#  endif
+#  define ENOTSOCK WSAENOTSOCK
+#  ifdef EDESTADDRREQ
+#    undef EDESTADDRREQ
+#  endif
+#  define EDESTADDRREQ WSAEDESTADDRREQ
+#  ifdef EMSGSIZE
+#    undef EMSGSIZE
+#  endif
+#  define EMSGSIZE WSAEMSGSIZE
+#  ifdef EPROTOTYPE
+#    undef EPROTOTYPE
+#  endif
+#  define EPROTOTYPE WSAEPROTOTYPE
+#  ifdef ENOPROTOOPT
+#    undef ENOPROTOOPT
+#  endif
+#  define ENOPROTOOPT WSAENOPROTOOPT
+#  ifdef EPROTONOSUPPORT
+#    undef EPROTONOSUPPORT
+#  endif
+#  define EPROTONOSUPPORT WSAEPROTONOSUPPORT
+#  ifdef ESOCKTNOSUPPORT
+#    undef ESOCKTNOSUPPORT
+#  endif
+#  define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
+#  ifdef EOPNOTSUPP
+#    undef EOPNOTSUPP
+#  endif
+#  define EOPNOTSUPP WSAEOPNOTSUPP
+#  ifdef EPFNOSUPPORT
+#    undef EPFNOSUPPORT
+#  endif
+#  define EPFNOSUPPORT WSAEPFNOSUPPORT
+#  ifdef EAFNOSUPPORT
+#    undef EAFNOSUPPORT
+#  endif
+#  define EAFNOSUPPORT WSAEAFNOSUPPORT
+#  ifdef EADDRINUSE
+#    undef EADDRINUSE
+#  endif
+#  define EADDRINUSE WSAEADDRINUSE
+#  ifdef EADDRNOTAVAIL
+#    undef EADDRNOTAVAIL
+#  endif
+#  define EADDRNOTAVAIL WSAEADDRNOTAVAIL
+#  ifdef ENETDOWN
+#    undef ENETDOWN
+#  endif
+#  define ENETDOWN WSAENETDOWN
+#  ifdef ENETUNREACH
+#    undef ENETUNREACH
+#  endif
+#  define ENETUNREACH WSAENETUNREACH
+#  ifdef ENETRESET
+#    undef ENETRESET
+#  endif
+#  define ENETRESET WSAENETRESET
+#  ifdef ECONNABORTED
+#    undef ECONNABORTED
+#  endif
+#  define ECONNABORTED WSAECONNABORTED
+#  ifdef ECONNRESET
+#    undef ECONNRESET
+#  endif
+#  define ECONNRESET WSAECONNRESET
+#  ifdef ENOBUFS
+#    undef ENOBUFS
+#  endif
+#  define ENOBUFS WSAENOBUFS
+#  ifdef EISCONN
+#    undef EISCONN
+#  endif
+#  define EISCONN WSAEISCONN
+#  ifdef ENOTCONN
+#    undef ENOTCONN
+#  endif
+#  define ENOTCONN WSAENOTCONN
+#  ifdef ESHUTDOWN
+#    undef ESHUTDOWN
+#  endif
+#  define ESHUTDOWN WSAESHUTDOWN
+#  ifdef ETOOMANYREFS
+#    undef ETOOMANYREFS
+#  endif
+#  define ETOOMANYREFS WSAETOOMANYREFS
+#  ifdef ETIMEDOUT
+#    undef ETIMEDOUT
+#  endif
+#  define ETIMEDOUT WSAETIMEDOUT
+#  ifdef ECONNREFUSED
+#    undef ECONNREFUSED
+#  endif
+#  define ECONNREFUSED WSAECONNREFUSED
+#  ifdef ELOOP
+#    undef ELOOP
+#  endif
+#  define ELOOP WSAELOOP
+#  ifdef EHOSTDOWN
+#    undef EHOSTDOWN
+#  endif
+#  define EHOSTDOWN WSAEHOSTDOWN
+#  ifdef EHOSTUNREACH
+#    undef EHOSTUNREACH
+#  endif
+#  define EHOSTUNREACH WSAEHOSTUNREACH
+#  ifdef EPROCLIM
+#    undef EPROCLIM
+#  endif
+#  define EPROCLIM WSAEPROCLIM
+#  ifdef EUSERS
+#    undef EUSERS
+#  endif
+#  define EUSERS WSAEUSERS
+#  ifdef EDQUOT
+#    undef EDQUOT
+#  endif
+#  define EDQUOT WSAEDQUOT
+#  ifdef ESTALE
+#    undef ESTALE
+#  endif
+#  define ESTALE WSAESTALE
+#  ifdef EREMOTE
+#    undef EREMOTE
+#  endif
+#  define EREMOTE WSAEREMOTE
+#  ifdef EDISCON
+#    undef EDISCON
+#  endif
+#  define EDISCON WSAEDISCON
+#endif
+
 typedef int SysRet;
 typedef long SysRetLong;
 typedef sigset_t* POSIX__SigSet;
@@ -404,6 +555,16 @@ restore_sigmask(pTHX_ SV *osset_sv)
      (void)sigprocmask(SIG_SETMASK, ossetp, (sigset_t *)0);
 }
 
+static void *
+allocate_struct(pTHX_ SV *rv, const STRLEN size, const char *packname) {
+    SV *const t = newSVrv(rv, packname);
+    void *const p = sv_grow(t, size + 1);
+
+    SvCUR_set(t, size);
+    SvPOK_on(t);
+    return p;
+}
+
 #ifdef WIN32
 
 /*
@@ -463,7 +624,7 @@ restore_sigmask(pTHX_ SV *osset_sv)
  *
  * Note that we don't free() the malloc()ed memory unless and until we call
  * malloc() again ourselves because the CRT putenv() function simply puts its
- * pointer argument into the environ[] arrary (it doesn't make a copy of it)
+ * pointer argument into the environ[] array (it doesn't make a copy of it)
  * so this memory must otherwise be leaked.
  */
 
@@ -516,43 +677,42 @@ my_tzset(pTHX)
 
 MODULE = SigSet                PACKAGE = POSIX::SigSet         PREFIX = sig
 
-POSIX::SigSet
+void
 new(packname = "POSIX::SigSet", ...)
     const char *       packname
     CODE:
        {
            int i;
-           Newx(RETVAL, 1, sigset_t);
-           sigemptyset(RETVAL);
+           sigset_t *const s
+               = (sigset_t *) allocate_struct(aTHX_ (ST(0) = sv_newmortal()),
+                                              sizeof(sigset_t),
+                                              packname);
+           sigemptyset(s);
            for (i = 1; i < items; i++)
-               sigaddset(RETVAL, SvIV(ST(i)));
+               sigaddset(s, SvIV(ST(i)));
+           XSRETURN(1);
        }
-    OUTPUT:
-       RETVAL
-
-void
-DESTROY(sigset)
-       POSIX::SigSet   sigset
-    CODE:
-       Safefree(sigset);
-
-SysRet
-sigaddset(sigset, sig)
-       POSIX::SigSet   sigset
-       int             sig
 
 SysRet
-sigdelset(sigset, sig)
+addset(sigset, sig)
        POSIX::SigSet   sigset
        int             sig
+   ALIAS:
+       delset = 1
+   CODE:
+       RETVAL = ix ? sigdelset(sigset, sig) : sigaddset(sigset, sig);
+   OUTPUT:
+       RETVAL
 
 SysRet
-sigemptyset(sigset)
-       POSIX::SigSet   sigset
-
-SysRet
-sigfillset(sigset)
+emptyset(sigset)
        POSIX::SigSet   sigset
+   ALIAS:
+       fillset = 1
+   CODE:
+       RETVAL = ix ? sigfillset(sigset) : sigemptyset(sigset);
+   OUTPUT:
+       RETVAL
 
 int
 sigismember(sigset, sig)
@@ -561,30 +721,24 @@ sigismember(sigset, sig)
 
 MODULE = Termios       PACKAGE = POSIX::Termios        PREFIX = cf
 
-POSIX::Termios
+void
 new(packname = "POSIX::Termios", ...)
     const char *       packname
     CODE:
        {
 #ifdef I_TERMIOS
-           Newx(RETVAL, 1, struct termios);
+           void *const p = allocate_struct(aTHX_ (ST(0) = sv_newmortal()),
+                                           sizeof(struct termios), packname);
+           /* The previous implementation stored a pointer to an uninitialised
+              struct termios. Seems safer to initialise it, particularly as
+              this implementation exposes the struct to prying from perl-space.
+           */
+           memset(p, 0, 1 + sizeof(struct termios));
+           XSRETURN(1);
 #else
            not_here("termios");
-        RETVAL = 0;
 #endif
        }
-    OUTPUT:
-       RETVAL
-
-void
-DESTROY(termios_ref)
-       POSIX::Termios  termios_ref
-    CODE:
-#ifdef I_TERMIOS
-       Safefree(termios_ref);
-#else
-           not_here("termios");
-#endif
 
 SysRet
 getattr(termios_ref, fd = 0)
@@ -606,61 +760,41 @@ setattr(termios_ref, fd = 0, optional_actions = 0)
        RETVAL
 
 speed_t
-cfgetispeed(termios_ref)
-       POSIX::Termios  termios_ref
-
-speed_t
-cfgetospeed(termios_ref)
-       POSIX::Termios  termios_ref
-
-tcflag_t
-getiflag(termios_ref)
-       POSIX::Termios  termios_ref
-    CODE:
-#ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
-       RETVAL = termios_ref->c_iflag;
-#else
-     not_here("getiflag");
-     RETVAL = 0;
-#endif
-    OUTPUT:
-       RETVAL
-
-tcflag_t
-getoflag(termios_ref)
-       POSIX::Termios  termios_ref
-    CODE:
-#ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
-       RETVAL = termios_ref->c_oflag;
-#else
-     not_here("getoflag");
-     RETVAL = 0;
-#endif
-    OUTPUT:
-       RETVAL
-
-tcflag_t
-getcflag(termios_ref)
+getispeed(termios_ref)
        POSIX::Termios  termios_ref
+    ALIAS:
+       getospeed = 1
     CODE:
-#ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
-       RETVAL = termios_ref->c_cflag;
-#else
-     not_here("getcflag");
-     RETVAL = 0;
-#endif
+       RETVAL = ix ? cfgetospeed(termios_ref) : cfgetispeed(termios_ref);
     OUTPUT:
        RETVAL
 
 tcflag_t
-getlflag(termios_ref)
+getiflag(termios_ref)
        POSIX::Termios  termios_ref
+    ALIAS:
+       getoflag = 1
+       getcflag = 2
+       getlflag = 3
     CODE:
 #ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
-       RETVAL = termios_ref->c_lflag;
+       switch(ix) {
+       case 0:
+           RETVAL = termios_ref->c_iflag;
+           break;
+       case 1:
+           RETVAL = termios_ref->c_oflag;
+           break;
+       case 2:
+           RETVAL = termios_ref->c_cflag;
+           break;
+       case 3:
+           RETVAL = termios_ref->c_lflag;
+           break;
+       }
 #else
-     not_here("getlflag");
-     RETVAL = 0;
+       not_here(GvNAME(CvGV(cv)));
+       RETVAL = 0;
 #endif
     OUTPUT:
        RETVAL
@@ -682,57 +816,43 @@ getcc(termios_ref, ccix)
        RETVAL
 
 SysRet
-cfsetispeed(termios_ref, speed)
+setispeed(termios_ref, speed)
        POSIX::Termios  termios_ref
        speed_t         speed
-
-SysRet
-cfsetospeed(termios_ref, speed)
-       POSIX::Termios  termios_ref
-       speed_t         speed
-
-void
-setiflag(termios_ref, iflag)
-       POSIX::Termios  termios_ref
-       tcflag_t        iflag
-    CODE:
-#ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
-       termios_ref->c_iflag = iflag;
-#else
-           not_here("setiflag");
-#endif
-
-void
-setoflag(termios_ref, oflag)
-       POSIX::Termios  termios_ref
-       tcflag_t        oflag
-    CODE:
-#ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
-       termios_ref->c_oflag = oflag;
-#else
-           not_here("setoflag");
-#endif
-
-void
-setcflag(termios_ref, cflag)
-       POSIX::Termios  termios_ref
-       tcflag_t        cflag
+    ALIAS:
+       setospeed = 1
     CODE:
-#ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
-       termios_ref->c_cflag = cflag;
-#else
-           not_here("setcflag");
-#endif
+       RETVAL = ix
+           ? cfsetospeed(termios_ref, speed) : cfsetispeed(termios_ref, speed);
+    OUTPUT:
+       RETVAL
 
 void
-setlflag(termios_ref, lflag)
+setiflag(termios_ref, flag)
        POSIX::Termios  termios_ref
-       tcflag_t        lflag
+       tcflag_t        flag
+    ALIAS:
+       setoflag = 1
+       setcflag = 2
+       setlflag = 3
     CODE:
 #ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
-       termios_ref->c_lflag = lflag;
+       switch(ix) {
+       case 0:
+           termios_ref->c_iflag = flag;
+           break;
+       case 1:
+           termios_ref->c_oflag = flag;
+           break;
+       case 2:
+           termios_ref->c_cflag = flag;
+           break;
+       case 3:
+           termios_ref->c_lflag = flag;
+           break;
+       }
 #else
-           not_here("setlflag");
+       not_here(GvNAME(CvGV(cv)));
 #endif
 
 void
@@ -764,8 +884,8 @@ WEXITSTATUS(status)
        POSIX::WSTOPSIG = 4
        POSIX::WTERMSIG = 5
     CODE:
-#if !(defined(WEXITSTATUS) || defined(WIFEXITED) || defined(WIFSIGNALED) \
-      || defined(WIFSTOPPED) || defined(WSTOPSIG) || defined (WTERMSIG))
+#if !defined(WEXITSTATUS) || !defined(WIFEXITED) || !defined(WIFSIGNALED) \
+      || !defined(WIFSTOPPED) || !defined(WSTOPSIG) || !defined(WTERMSIG)
         RETVAL = 0; /* Silence compilers that notice this, but don't realise
                       that not_here() can't return.  */
 #endif
@@ -813,7 +933,7 @@ WEXITSTATUS(status)
 #endif
            break;
        default:
-           Perl_croak(aTHX_ "Illegal alias %d for POSIX::W*", ix);
+           Perl_croak(aTHX_ "Illegal alias %d for POSIX::W*", (int)ix);
        }
     OUTPUT:
        RETVAL
@@ -995,65 +1115,65 @@ localeconv()
        if ((lcbuf = localeconv())) {
            /* the strings */
            if (lcbuf->decimal_point && *lcbuf->decimal_point)
-               hv_store(RETVAL, "decimal_point", 13,
+               (void) hv_store(RETVAL, "decimal_point", 13,
                    newSVpv(lcbuf->decimal_point, 0), 0);
            if (lcbuf->thousands_sep && *lcbuf->thousands_sep)
-               hv_store(RETVAL, "thousands_sep", 13,
+               (void) hv_store(RETVAL, "thousands_sep", 13,
                    newSVpv(lcbuf->thousands_sep, 0), 0);
 #ifndef NO_LOCALECONV_GROUPING
            if (lcbuf->grouping && *lcbuf->grouping)
-               hv_store(RETVAL, "grouping", 8,
+               (void) hv_store(RETVAL, "grouping", 8,
                    newSVpv(lcbuf->grouping, 0), 0);
 #endif
            if (lcbuf->int_curr_symbol && *lcbuf->int_curr_symbol)
-               hv_store(RETVAL, "int_curr_symbol", 15,
+               (void) hv_store(RETVAL, "int_curr_symbol", 15,
                    newSVpv(lcbuf->int_curr_symbol, 0), 0);
            if (lcbuf->currency_symbol && *lcbuf->currency_symbol)
-               hv_store(RETVAL, "currency_symbol", 15,
+               (void) hv_store(RETVAL, "currency_symbol", 15,
                    newSVpv(lcbuf->currency_symbol, 0), 0);
            if (lcbuf->mon_decimal_point && *lcbuf->mon_decimal_point)
-               hv_store(RETVAL, "mon_decimal_point", 17,
+               (void) hv_store(RETVAL, "mon_decimal_point", 17,
                    newSVpv(lcbuf->mon_decimal_point, 0), 0);
 #ifndef NO_LOCALECONV_MON_THOUSANDS_SEP
            if (lcbuf->mon_thousands_sep && *lcbuf->mon_thousands_sep)
-               hv_store(RETVAL, "mon_thousands_sep", 17,
+               (void) hv_store(RETVAL, "mon_thousands_sep", 17,
                    newSVpv(lcbuf->mon_thousands_sep, 0), 0);
 #endif
 #ifndef NO_LOCALECONV_MON_GROUPING
            if (lcbuf->mon_grouping && *lcbuf->mon_grouping)
-               hv_store(RETVAL, "mon_grouping", 12,
+               (void) hv_store(RETVAL, "mon_grouping", 12,
                    newSVpv(lcbuf->mon_grouping, 0), 0);
 #endif
            if (lcbuf->positive_sign && *lcbuf->positive_sign)
-               hv_store(RETVAL, "positive_sign", 13,
+               (void) hv_store(RETVAL, "positive_sign", 13,
                    newSVpv(lcbuf->positive_sign, 0), 0);
            if (lcbuf->negative_sign && *lcbuf->negative_sign)
-               hv_store(RETVAL, "negative_sign", 13,
+               (void) hv_store(RETVAL, "negative_sign", 13,
                    newSVpv(lcbuf->negative_sign, 0), 0);
            /* the integers */
            if (lcbuf->int_frac_digits != CHAR_MAX)
-               hv_store(RETVAL, "int_frac_digits", 15,
+               (void) hv_store(RETVAL, "int_frac_digits", 15,
                    newSViv(lcbuf->int_frac_digits), 0);
            if (lcbuf->frac_digits != CHAR_MAX)
-               hv_store(RETVAL, "frac_digits", 11,
+               (void) hv_store(RETVAL, "frac_digits", 11,
                    newSViv(lcbuf->frac_digits), 0);
            if (lcbuf->p_cs_precedes != CHAR_MAX)
-               hv_store(RETVAL, "p_cs_precedes", 13,
+               (void) hv_store(RETVAL, "p_cs_precedes", 13,
                    newSViv(lcbuf->p_cs_precedes), 0);
            if (lcbuf->p_sep_by_space != CHAR_MAX)
-               hv_store(RETVAL, "p_sep_by_space", 14,
+               (void) hv_store(RETVAL, "p_sep_by_space", 14,
                    newSViv(lcbuf->p_sep_by_space), 0);
            if (lcbuf->n_cs_precedes != CHAR_MAX)
-               hv_store(RETVAL, "n_cs_precedes", 13,
+               (void) hv_store(RETVAL, "n_cs_precedes", 13,
                    newSViv(lcbuf->n_cs_precedes), 0);
            if (lcbuf->n_sep_by_space != CHAR_MAX)
-               hv_store(RETVAL, "n_sep_by_space", 14,
+               (void) hv_store(RETVAL, "n_sep_by_space", 14,
                    newSViv(lcbuf->n_sep_by_space), 0);
            if (lcbuf->p_sign_posn != CHAR_MAX)
-               hv_store(RETVAL, "p_sign_posn", 11,
+               (void) hv_store(RETVAL, "p_sign_posn", 11,
                    newSViv(lcbuf->p_sign_posn), 0);
            if (lcbuf->n_sign_posn != CHAR_MAX)
-               hv_store(RETVAL, "n_sign_posn", 11,
+               (void) hv_store(RETVAL, "n_sign_posn", 11,
                    newSViv(lcbuf->n_sign_posn), 0);
        }
 #else
@@ -1217,7 +1337,7 @@ sigaction(sig, optaction, oldaction = 0)
        {
            dVAR;
            POSIX__SigAction action;
-           GV *siggv = gv_fetchpv("SIG", TRUE, SVt_PVHV);
+           GV *siggv = gv_fetchpvs("SIG", GV_ADD, SVt_PVHV);
            struct sigaction act;
            struct sigaction oact;
            sigset_t sset;
@@ -1280,7 +1400,7 @@ sigaction(sig, optaction, oldaction = 0)
                XSRETURN_UNDEF;
            ENTER;
            /* Restore signal mask no matter how we exit this block. */
-           osset_sv = newSVpv((char *)(&osset), sizeof(sigset_t));
+           osset_sv = newSVpvn((char *)(&osset), sizeof(sigset_t));
            SAVEFREESV( osset_sv );
            SAVEDESTRUCTOR_X(restore_sigmask, osset_sv);
 
@@ -1295,20 +1415,22 @@ sigaction(sig, optaction, oldaction = 0)
                        sv_setsv(*svp, *sigsvp);
                }
                else {
-                       sv_setpv(*svp, "DEFAULT");
+                       sv_setpvs(*svp, "DEFAULT");
                }
                RETVAL = sigaction(sig, (struct sigaction *)0, & oact);
-               if(RETVAL == -1)
+               if(RETVAL == -1) {
+                   LEAVE;
                    XSRETURN_UNDEF;
+                }
                /* Get back the mask. */
                svp = hv_fetchs(oldaction, "MASK", TRUE);
                if (sv_isa(*svp, "POSIX::SigSet")) {
-                   IV tmp = SvIV((SV*)SvRV(*svp));
-                   sigset = INT2PTR(sigset_t*, tmp);
+                   sigset = (sigset_t *) SvPV_nolen(SvRV(*svp));
                }
                else {
-                   Newx(sigset, 1, sigset_t);
-                   sv_setptrobj(*svp, sigset, "POSIX::SigSet");
+                   sigset = (sigset_t *) allocate_struct(aTHX_ *svp,
+                                                         sizeof(sigset_t),
+                                                         "POSIX::SigSet");
                }
                *sigset = oact.sa_mask;
 
@@ -1346,7 +1468,7 @@ sigaction(sig, optaction, oldaction = 0)
                   right settings, including appropriate interpretation
                   of DEFAULT and IGNORE.  However, why are we doing
                   this when we're about to do it again just below?  XXX */
-               mg_set(*sigsvp);
+               SvSETMAGIC(*sigsvp);
 
                /* And here again we duplicate -- DEFAULT/IGNORE checking. */
                if(SvPOK(*svp)) {
@@ -1362,8 +1484,7 @@ sigaction(sig, optaction, oldaction = 0)
                /* Set up any desired mask. */
                svp = hv_fetchs(action, "MASK", FALSE);
                if (svp && sv_isa(*svp, "POSIX::SigSet")) {
-                   IV tmp = SvIV((SV*)SvRV(*svp));
-                   sigset = INT2PTR(sigset_t*, tmp);
+                   sigset = (sigset_t *) SvPV_nolen(SvRV(*svp));
                    act.sa_mask = *sigset;
                }
                else
@@ -1379,8 +1500,10 @@ sigaction(sig, optaction, oldaction = 0)
                 * essentially meaningless anyway.
                 */
                RETVAL = sigaction(sig, & act, (struct sigaction *)0);
-               if(RETVAL == -1)
+               if(RETVAL == -1) {
+                    LEAVE;
                    XSRETURN_UNDEF;
+                }
            }
 
            LEAVE;
@@ -1392,6 +1515,12 @@ sigaction(sig, optaction, oldaction = 0)
 SysRet
 sigpending(sigset)
        POSIX::SigSet           sigset
+    ALIAS:
+       sigsuspend = 1
+    CODE:
+       RETVAL = ix ? sigsuspend(sigset) : sigpending(sigset);
+    OUTPUT:
+       RETVAL
 
 SysRet
 sigprocmask(how, sigset, oldsigset = 0)
@@ -1402,8 +1531,7 @@ INIT:
        if (! SvOK(ST(1))) {
            sigset = NULL;
        } else if (sv_isa(ST(1), "POSIX::SigSet")) {
-           IV tmp = SvIV((SV*)SvRV(ST(1)));
-           sigset = INT2PTR(POSIX__SigSet,tmp);
+           sigset = (sigset_t *) SvPV_nolen(SvRV(ST(1)));
        } else {
            croak("sigset is not of type POSIX::SigSet");
        }
@@ -1411,16 +1539,11 @@ INIT:
        if (items < 3 || ! SvOK(ST(2))) {
            oldsigset = NULL;
        } else if (sv_isa(ST(2), "POSIX::SigSet")) {
-           IV tmp = SvIV((SV*)SvRV(ST(2)));
-           oldsigset = INT2PTR(POSIX__SigSet,tmp);
+           oldsigset = (sigset_t *) SvPV_nolen(SvRV(ST(2)));
        } else {
            croak("oldsigset is not of type POSIX::SigSet");
        }
 
-SysRet
-sigsuspend(signal_mask)
-       POSIX::SigSet           signal_mask
-
 void
 _exit(status)
        int             status
@@ -1457,7 +1580,7 @@ nice(incr)
        errno = 0;
        if ((incr = nice(incr)) != -1 || errno == 0) {
            if (incr == 0)
-               XPUSHs(sv_2mortal(newSVpvn("0 but true", 10)));
+               XPUSHs(newSVpvs_flags("0 but true", SVs_TEMP));
            else
                XPUSHs(sv_2mortal(newSViv(incr)));
        }
@@ -1512,11 +1635,11 @@ uname()
        struct utsname buf;
        if (uname(&buf) >= 0) {
            EXTEND(SP, 5);
-           PUSHs(sv_2mortal(newSVpv(buf.sysname, 0)));
-           PUSHs(sv_2mortal(newSVpv(buf.nodename, 0)));
-           PUSHs(sv_2mortal(newSVpv(buf.release, 0)));
-           PUSHs(sv_2mortal(newSVpv(buf.version, 0)));
-           PUSHs(sv_2mortal(newSVpv(buf.machine, 0)));
+           PUSHs(newSVpvn_flags(buf.sysname, strlen(buf.sysname), SVs_TEMP));
+           PUSHs(newSVpvn_flags(buf.nodename, strlen(buf.nodename), SVs_TEMP));
+           PUSHs(newSVpvn_flags(buf.release, strlen(buf.release), SVs_TEMP));
+           PUSHs(newSVpvn_flags(buf.version, strlen(buf.version), SVs_TEMP));
+           PUSHs(newSVpvn_flags(buf.machine, strlen(buf.machine), SVs_TEMP));
        }
 #else
        uname((char *) 0); /* A stub to call not_here(). */
@@ -1681,17 +1804,14 @@ SysRet
 tcflow(fd, action)
        int             fd
        int             action
-
-
-SysRet
-tcflush(fd, queue_selector)
-       int             fd
-       int             queue_selector
-
-SysRet
-tcsendbreak(fd, duration)
-       int             fd
-       int             duration
+    ALIAS:
+       tcflush = 1
+       tcsendbreak = 2
+    CODE:
+       RETVAL = ix == 1 ? tcflush(fd, action)
+           : (ix < 1 ? tcflow(fd, action) : tcsendbreak(fd, action));
+    OUTPUT:
+       RETVAL
 
 char *
 asctime(sec, min, hour, mday, mon, year, wday = 0, yday = 0, isdst = -1)
@@ -1793,10 +1913,14 @@ strftime(fmt, sec, min, hour, mday, mon, year, wday = -1, yday = -1, isdst = -1)
        int             isdst
     CODE:
        {
-           char *buf = my_strftime(SvPVutf8_nolen(fmt), sec, min, hour, mday, mon, year, wday, yday, isdst);
+           char *buf = my_strftime(SvPV_nolen(fmt), sec, min, hour, mday, mon, year, wday, yday, isdst);
            if (buf) {
-               ST(0) = sv_2mortal(newSVpvn_utf8(buf, strlen(buf), SvUTF8(fmt)));
-               Safefree(buf);
+               SV *const sv = sv_newmortal();
+               sv_usepvn_flags(sv, buf, strlen(buf), SV_HAS_TRAILING_NUL);
+               if (SvUTF8(fmt)) {
+                   SvUTF8_on(sv);
+               }
+               ST(0) = sv;
            }
        }
 
@@ -1809,8 +1933,8 @@ void
 tzname()
     PPCODE:
        EXTEND(SP,2);
-       PUSHs(sv_2mortal(newSVpvn(tzname[0],strlen(tzname[0]))));
-       PUSHs(sv_2mortal(newSVpvn(tzname[1],strlen(tzname[1]))));
+       PUSHs(newSVpvn_flags(tzname[0], strlen(tzname[0]), SVs_TEMP));
+       PUSHs(newSVpvn_flags(tzname[1], strlen(tzname[1]), SVs_TEMP));
 
 SysRet
 access(filename, mode)