This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Refactoring to Sv*_set() macros - patch #5
[perl5.git] / ext / POSIX / POSIX.xs
index 030a68c..561dc30 100644 (file)
@@ -1,6 +1,15 @@
-#ifdef WIN32
-#define _POSIX_
-#endif
+#define PERL_EXT_POSIX
+
+#ifdef NETWARE
+       #define _POSIX_
+       /*
+        * Ideally this should be somewhere down in the includes
+        * but putting it in other places is giving compiler errors.
+        * Also here I am unable to check for HAS_UNAME since it wouldn't have
+        * yet come into the file at this stage - sgp 18th Oct 2000
+        */
+       #include <sys/utsname.h>
+#endif /* NETWARE */
 
 #define PERL_NO_GET_CONTEXT
 
 
 #define PERL_NO_GET_CONTEXT
 
@@ -8,7 +17,7 @@
 #define PERLIO_NOT_STDIO 1
 #include "perl.h"
 #include "XSUB.h"
 #define PERLIO_NOT_STDIO 1
 #include "perl.h"
 #include "XSUB.h"
-#if defined(PERL_OBJECT) || defined(PERL_CAPI) || defined(PERL_IMPLICIT_SYS)
+#if defined(PERL_IMPLICIT_SYS)
 #  undef signal
 #  undef open
 #  undef setmode
 #  undef signal
 #  undef open
 #  undef setmode
@@ -52,7 +61,9 @@
 #ifdef I_STDLIB
 #include <stdlib.h>
 #endif
 #ifdef I_STDLIB
 #include <stdlib.h>
 #endif
+#ifndef __ultrix__
 #include <string.h>
 #include <string.h>
+#endif
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <time.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <time.h>
 #include <fcntl.h>
 
 #ifdef HAS_TZNAME
 #include <fcntl.h>
 
 #ifdef HAS_TZNAME
-#  if !defined(WIN32) && !defined(__CYGWIN__)
+#  if !defined(WIN32) && !defined(__CYGWIN__) && !defined(NETWARE) && !defined(__UWIN__)
 extern char *tzname[];
 #  endif
 #else
 extern char *tzname[];
 #  endif
 #else
-#if !defined(WIN32) || (defined(__MINGW32__) && !defined(tzname))
+#if !defined(WIN32) && !defined(__UWIN__) || (defined(__MINGW32__) && !defined(tzname))
 char *tzname[] = { "" , "" };
 #endif
 #endif
 char *tzname[] = { "" , "" };
 #endif
 #endif
@@ -126,7 +137,7 @@ char *tzname[] = { "" , "" };
 #if defined (__CYGWIN__)
 #    define tzname _tzname
 #endif
 #if defined (__CYGWIN__)
 #    define tzname _tzname
 #endif
-#if defined (WIN32)
+#if defined (WIN32) || defined (NETWARE)
 #  undef mkfifo
 #  define mkfifo(a,b) not_here("mkfifo")
 #  define ttyname(a) (char*)not_here("ttyname")
 #  undef mkfifo
 #  define mkfifo(a,b) not_here("mkfifo")
 #  define ttyname(a) (char*)not_here("ttyname")
@@ -156,6 +167,12 @@ char *tzname[] = { "" , "" };
 #  define sigdelset(a,b)       not_here("sigdelset")
 #  define sigfillset(a)                not_here("sigfillset")
 #  define sigismember(a,b)     not_here("sigismember")
 #  define sigdelset(a,b)       not_here("sigdelset")
 #  define sigfillset(a)                not_here("sigfillset")
 #  define sigismember(a,b)     not_here("sigismember")
+#ifndef NETWARE
+#  undef setuid
+#  undef setgid
+#  define setuid(a)            not_here("setuid")
+#  define setgid(a)            not_here("setgid")
+#endif /* NETWARE */
 #else
 
 #  ifndef HAS_MKFIFO
 #else
 
 #  ifndef HAS_MKFIFO
@@ -182,7 +199,7 @@ char *tzname[] = { "" , "" };
 #  ifdef I_UTIME
 #    include <utime.h>
 #  endif
 #  ifdef I_UTIME
 #    include <utime.h>
 #  endif
-#endif /* WIN32 */
+#endif /* WIN32 || NETWARE */
 #endif /* __VMS */
 
 typedef int SysRet;
 #endif /* __VMS */
 
 typedef int SysRet;
@@ -211,9 +228,11 @@ typedef struct termios* POSIX__Termios;
 
 /* Possibly needed prototypes */
 char *cuserid (char *);
 
 /* Possibly needed prototypes */
 char *cuserid (char *);
+#ifndef WIN32
 double strtod (const char *, char **);
 long strtol (const char *, char **, int);
 unsigned long strtoul (const char *, char **, int);
 double strtod (const char *, char **);
 long strtol (const char *, char **, int);
 unsigned long strtoul (const char *, char **, int);
+#endif
 
 #ifndef HAS_CUSERID
 #define cuserid(a) (char *) not_here("cuserid")
 
 #ifndef HAS_CUSERID
 #define cuserid(a) (char *) not_here("cuserid")
@@ -269,7 +288,9 @@ unsigned long strtoul (const char *, char **, int);
 #define tcsetpgrp(a,b) not_here("tcsetpgrp")
 #endif
 #ifndef HAS_TIMES
 #define tcsetpgrp(a,b) not_here("tcsetpgrp")
 #endif
 #ifndef HAS_TIMES
+#ifndef NETWARE
 #define times(a) not_here("times")
 #define times(a) not_here("times")
+#endif /* NETWARE */
 #endif
 #ifndef HAS_UNAME
 #define uname(a) not_here("uname")
 #endif
 #ifndef HAS_UNAME
 #define uname(a) not_here("uname")
@@ -328,6 +349,20 @@ unsigned long strtoul (const char *, char **, int);
 #endif
 #endif
 
 #endif
 #endif
 
+/* Background: in most systems the low byte of the wait status
+ * is the signal (the lowest 7 bits) and the coredump flag is
+ * the eight bit, and the second lowest byte is the exit status.
+ * BeOS bucks the trend and has the bytes in different order.
+ * See beos/beos.c for how the reality is bent even in BeOS
+ * to follow the traditional.  However, to make the POSIX
+ * wait W*() macros to work in BeOS, we need to unbend the
+ * reality back in place. --jhi */
+#ifdef __BEOS__
+#    define WMUNGE(x) (((x) & 0xFF00) >> 8 | ((x) & 0x00FF) << 8)
+#else
+#    define WMUNGE(x) (x)
+#endif
+
 static int
 not_here(char *s)
 {
 static int
 not_here(char *s)
 {
@@ -335,16 +370,7 @@ not_here(char *s)
     return -1;
 }
 
     return -1;
 }
 
-#define PERL_constant_NOTFOUND 1
-#define PERL_constant_NOTDEF   2
-#define PERL_constant_ISIV     3
-#define PERL_constant_ISNO     4
-#define PERL_constant_ISNV     5
-#define PERL_constant_ISPV     6
-#define PERL_constant_ISPVN    7
-#define PERL_constant_ISUNDEF  8
-#define PERL_constant_ISUV     9
-#define PERL_constant_ISYES    10
+#include "const-c.inc"
 
 /* These were implemented in the old "constant" subroutine. They are actually
    macros that take an integer argument and return an integer result.  */
 
 /* These were implemented in the old "constant" subroutine. They are actually
    macros that take an integer argument and return an integer result.  */
@@ -429,7 +455,8 @@ __END__
       if (memEQ(name, "WSTOPSIG", 8)) {
       /*                  ^          */
 #ifdef WSTOPSIG
       if (memEQ(name, "WSTOPSIG", 8)) {
       /*                  ^          */
 #ifdef WSTOPSIG
-        *arg_result = WSTOPSIG(*arg_result);
+        int i = *arg_result;
+        *arg_result = WSTOPSIG(WMUNGE(i));
         return PERL_constant_ISIV;
 #else
         return PERL_constant_NOTDEF;
         return PERL_constant_ISIV;
 #else
         return PERL_constant_NOTDEF;
@@ -440,7 +467,8 @@ __END__
       if (memEQ(name, "WTERMSIG", 8)) {
       /*                  ^          */
 #ifdef WTERMSIG
       if (memEQ(name, "WTERMSIG", 8)) {
       /*                  ^          */
 #ifdef WTERMSIG
-        *arg_result = WTERMSIG(*arg_result);
+        int i = *arg_result;
+        *arg_result = WTERMSIG(WMUNGE(i));
         return PERL_constant_ISIV;
 #else
         return PERL_constant_NOTDEF;
         return PERL_constant_ISIV;
 #else
         return PERL_constant_NOTDEF;
@@ -463,7 +491,8 @@ __END__
   case 9:
     if (memEQ(name, "WIFEXITED", 9)) {
 #ifdef WIFEXITED
   case 9:
     if (memEQ(name, "WIFEXITED", 9)) {
 #ifdef WIFEXITED
-      *arg_result = WIFEXITED(*arg_result);
+      int i = *arg_result;
+      *arg_result = WIFEXITED(WMUNGE(i));
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
@@ -473,7 +502,8 @@ __END__
   case 10:
     if (memEQ(name, "WIFSTOPPED", 10)) {
 #ifdef WIFSTOPPED
   case 10:
     if (memEQ(name, "WIFSTOPPED", 10)) {
 #ifdef WIFSTOPPED
-      *arg_result = WIFSTOPPED(*arg_result);
+      int i = *arg_result;
+      *arg_result = WIFSTOPPED(WMUNGE(i));
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
       return PERL_constant_ISIV;
 #else
       return PERL_constant_NOTDEF;
@@ -489,7 +519,8 @@ __END__
       if (memEQ(name, "WEXITSTATUS", 11)) {
       /*                ^                */
 #ifdef WEXITSTATUS
       if (memEQ(name, "WEXITSTATUS", 11)) {
       /*                ^                */
 #ifdef WEXITSTATUS
-        *arg_result = WEXITSTATUS(*arg_result);
+       int i = *arg_result;
+        *arg_result = WEXITSTATUS(WMUNGE(i));
         return PERL_constant_ISIV;
 #else
         return PERL_constant_NOTDEF;
         return PERL_constant_ISIV;
 #else
         return PERL_constant_NOTDEF;
@@ -500,7 +531,8 @@ __END__
       if (memEQ(name, "WIFSIGNALED", 11)) {
       /*                ^                */
 #ifdef WIFSIGNALED
       if (memEQ(name, "WIFSIGNALED", 11)) {
       /*                ^                */
 #ifdef WIFSIGNALED
-        *arg_result = WIFSIGNALED(*arg_result);
+       int i = *arg_result;
+        *arg_result = WIFSIGNALED(WMUNGE(i));
         return PERL_constant_ISIV;
 #else
         return PERL_constant_NOTDEF;
         return PERL_constant_ISIV;
 #else
         return PERL_constant_NOTDEF;
@@ -513,17 +545,16 @@ __END__
   return PERL_constant_NOTFOUND;
 }
 
   return PERL_constant_NOTFOUND;
 }
 
-#include "constants.c"
-
 static void
 static void
-restore_sigmask(sigset_t *ossetp)
+restore_sigmask(pTHX_ SV *osset_sv)
 {
 {
-           /* Fortunately, restoring the signal mask can't fail, because
-            * there's nothing we can do about it if it does -- we're not
-            * supposed to return -1 from sigaction unless the disposition
-            * was unaffected.
-            */
-           (void)sigprocmask(SIG_SETMASK, ossetp, (sigset_t *)0);
+     /* Fortunately, restoring the signal mask can't fail, because
+      * there's nothing we can do about it if it does -- we're not
+      * supposed to return -1 from sigaction unless the disposition
+      * was unaffected.
+      */
+     sigset_t *ossetp = (sigset_t *) SvPV_nolen( osset_sv );
+     (void)sigprocmask(SIG_SETMASK, ossetp, (sigset_t *)0);
 }
 
 MODULE = SigSet                PACKAGE = POSIX::SigSet         PREFIX = sig
 }
 
 MODULE = SigSet                PACKAGE = POSIX::SigSet         PREFIX = sig
@@ -765,7 +796,7 @@ setcc(termios_ref, ccix, cc)
 
 MODULE = POSIX         PACKAGE = POSIX
 
 
 MODULE = POSIX         PACKAGE = POSIX
 
-INCLUDE: constants.xs
+INCLUDE: const-xs.inc
 
 void
 int_macro_int(sv, iv)
 
 void
 int_macro_int(sv, iv)
@@ -811,10 +842,12 @@ int_macro_int(sv, iv)
 
 int
 isalnum(charstring)
 
 int
 isalnum(charstring)
-       unsigned char * charstring
+       SV *    charstring
+    PREINIT:
+       STRLEN  len;
     CODE:
     CODE:
-       unsigned char *s = charstring;
-       unsigned char *e = s + PL_na;   /* "PL_na" set by typemap side effect */
+       unsigned char *s = (unsigned char *) SvPV(charstring, len);
+       unsigned char *e = s + len;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isalnum(*s))
                RETVAL = 0;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isalnum(*s))
                RETVAL = 0;
@@ -823,10 +856,12 @@ isalnum(charstring)
 
 int
 isalpha(charstring)
 
 int
 isalpha(charstring)
-       unsigned char * charstring
+       SV *    charstring
+    PREINIT:
+       STRLEN  len;
     CODE:
     CODE:
-       unsigned char *s = charstring;
-       unsigned char *e = s + PL_na;   /* "PL_na" set by typemap side effect */
+       unsigned char *s = (unsigned char *) SvPV(charstring, len);
+       unsigned char *e = s + len;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isalpha(*s))
                RETVAL = 0;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isalpha(*s))
                RETVAL = 0;
@@ -835,10 +870,12 @@ isalpha(charstring)
 
 int
 iscntrl(charstring)
 
 int
 iscntrl(charstring)
-       unsigned char * charstring
+       SV *    charstring
+    PREINIT:
+       STRLEN  len;
     CODE:
     CODE:
-       unsigned char *s = charstring;
-       unsigned char *e = s + PL_na;   /* "PL_na" set by typemap side effect */
+       unsigned char *s = (unsigned char *) SvPV(charstring, len);
+       unsigned char *e = s + len;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!iscntrl(*s))
                RETVAL = 0;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!iscntrl(*s))
                RETVAL = 0;
@@ -847,10 +884,12 @@ iscntrl(charstring)
 
 int
 isdigit(charstring)
 
 int
 isdigit(charstring)
-       unsigned char * charstring
+       SV *    charstring
+    PREINIT:
+       STRLEN  len;
     CODE:
     CODE:
-       unsigned char *s = charstring;
-       unsigned char *e = s + PL_na;   /* "PL_na" set by typemap side effect */
+       unsigned char *s = (unsigned char *) SvPV(charstring, len);
+       unsigned char *e = s + len;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isdigit(*s))
                RETVAL = 0;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isdigit(*s))
                RETVAL = 0;
@@ -859,10 +898,12 @@ isdigit(charstring)
 
 int
 isgraph(charstring)
 
 int
 isgraph(charstring)
-       unsigned char * charstring
+       SV *    charstring
+    PREINIT:
+       STRLEN  len;
     CODE:
     CODE:
-       unsigned char *s = charstring;
-       unsigned char *e = s + PL_na;   /* "PL_na" set by typemap side effect */
+       unsigned char *s = (unsigned char *) SvPV(charstring, len);
+       unsigned char *e = s + len;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isgraph(*s))
                RETVAL = 0;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isgraph(*s))
                RETVAL = 0;
@@ -871,10 +912,12 @@ isgraph(charstring)
 
 int
 islower(charstring)
 
 int
 islower(charstring)
-       unsigned char * charstring
+       SV *    charstring
+    PREINIT:
+       STRLEN  len;
     CODE:
     CODE:
-       unsigned char *s = charstring;
-       unsigned char *e = s + PL_na;   /* "PL_na" set by typemap side effect */
+       unsigned char *s = (unsigned char *) SvPV(charstring, len);
+       unsigned char *e = s + len;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!islower(*s))
                RETVAL = 0;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!islower(*s))
                RETVAL = 0;
@@ -883,10 +926,12 @@ islower(charstring)
 
 int
 isprint(charstring)
 
 int
 isprint(charstring)
-       unsigned char * charstring
+       SV *    charstring
+    PREINIT:
+       STRLEN  len;
     CODE:
     CODE:
-       unsigned char *s = charstring;
-       unsigned char *e = s + PL_na;   /* "PL_na" set by typemap side effect */
+       unsigned char *s = (unsigned char *) SvPV(charstring, len);
+       unsigned char *e = s + len;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isprint(*s))
                RETVAL = 0;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isprint(*s))
                RETVAL = 0;
@@ -895,10 +940,12 @@ isprint(charstring)
 
 int
 ispunct(charstring)
 
 int
 ispunct(charstring)
-       unsigned char * charstring
+       SV *    charstring
+    PREINIT:
+       STRLEN  len;
     CODE:
     CODE:
-       unsigned char *s = charstring;
-       unsigned char *e = s + PL_na;   /* "PL_na" set by typemap side effect */
+       unsigned char *s = (unsigned char *) SvPV(charstring, len);
+       unsigned char *e = s + len;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!ispunct(*s))
                RETVAL = 0;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!ispunct(*s))
                RETVAL = 0;
@@ -907,10 +954,12 @@ ispunct(charstring)
 
 int
 isspace(charstring)
 
 int
 isspace(charstring)
-       unsigned char * charstring
+       SV *    charstring
+    PREINIT:
+       STRLEN  len;
     CODE:
     CODE:
-       unsigned char *s = charstring;
-       unsigned char *e = s + PL_na;   /* "PL_na" set by typemap side effect */
+       unsigned char *s = (unsigned char *) SvPV(charstring, len);
+       unsigned char *e = s + len;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isspace(*s))
                RETVAL = 0;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isspace(*s))
                RETVAL = 0;
@@ -919,10 +968,12 @@ isspace(charstring)
 
 int
 isupper(charstring)
 
 int
 isupper(charstring)
-       unsigned char * charstring
+       SV *    charstring
+    PREINIT:
+       STRLEN  len;
     CODE:
     CODE:
-       unsigned char *s = charstring;
-       unsigned char *e = s + PL_na;   /* "PL_na" set by typemap side effect */
+       unsigned char *s = (unsigned char *) SvPV(charstring, len);
+       unsigned char *e = s + len;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isupper(*s))
                RETVAL = 0;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isupper(*s))
                RETVAL = 0;
@@ -931,10 +982,12 @@ isupper(charstring)
 
 int
 isxdigit(charstring)
 
 int
 isxdigit(charstring)
-       unsigned char * charstring
+       SV *    charstring
+    PREINIT:
+       STRLEN  len;
     CODE:
     CODE:
-       unsigned char *s = charstring;
-       unsigned char *e = s + PL_na;   /* "PL_na" set by typemap side effect */
+       unsigned char *s = (unsigned char *) SvPV(charstring, len);
+       unsigned char *e = s + len;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isxdigit(*s))
                RETVAL = 0;
        for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isxdigit(*s))
                RETVAL = 0;
@@ -960,6 +1013,7 @@ localeconv()
 #ifdef HAS_LOCALECONV
        struct lconv *lcbuf;
        RETVAL = newHV();
 #ifdef HAS_LOCALECONV
        struct lconv *lcbuf;
        RETVAL = newHV();
+       sv_2mortal((SV*)RETVAL);
        if ((lcbuf = localeconv())) {
            /* the strings */
            if (lcbuf->decimal_point && *lcbuf->decimal_point)
        if ((lcbuf = localeconv())) {
            /* the strings */
            if (lcbuf->decimal_point && *lcbuf->decimal_point)
@@ -1167,7 +1221,7 @@ sigaction(sig, optaction, oldaction = 0)
        SV *                    optaction
        POSIX::SigAction        oldaction
     CODE:
        SV *                    optaction
        POSIX::SigAction        oldaction
     CODE:
-#ifdef WIN32
+#if defined(WIN32) || defined(NETWARE)
        RETVAL = not_here("sigaction");
 #else
 # This code is really grody because we're trying to make the signal
        RETVAL = not_here("sigaction");
 #else
 # This code is really grody because we're trying to make the signal
@@ -1179,13 +1233,30 @@ sigaction(sig, optaction, oldaction = 0)
            struct sigaction act;
            struct sigaction oact;
            sigset_t sset;
            struct sigaction act;
            struct sigaction oact;
            sigset_t sset;
+           SV *osset_sv;
            sigset_t osset;
            POSIX__SigSet sigset;
            SV** svp;
            sigset_t osset;
            POSIX__SigSet sigset;
            SV** svp;
-           SV** sigsvp = hv_fetch(GvHVn(siggv),
-                                PL_sig_name[sig],
-                                strlen(PL_sig_name[sig]),
-                                TRUE);
+           SV** sigsvp;
+           if (sig == 0 && SvPOK(ST(0))) {
+               char *s = SvPVX(ST(0));
+               int i = whichsig(s);
+
+               if (i < 0 && memEQ(s, "SIG", 3))
+                   i = whichsig(s + 3);
+               if (i < 0) {
+                   if (ckWARN(WARN_SIGNAL))
+                       Perl_warner(aTHX_ packWARN(WARN_SIGNAL),
+                                    "No such signal: SIG%s", s);
+                   XSRETURN_UNDEF;
+               }
+               else
+                   sig = i;
+            }
+           sigsvp = hv_fetch(GvHVn(siggv),
+                             PL_sig_name[sig],
+                             strlen(PL_sig_name[sig]),
+                             TRUE);
 
            /* Check optaction and set action */
            if(SvTRUE(optaction)) {
 
            /* Check optaction and set action */
            if(SvTRUE(optaction)) {
@@ -1206,10 +1277,12 @@ sigaction(sig, optaction, oldaction = 0)
            sigfillset(&sset);
            RETVAL=sigprocmask(SIG_BLOCK, &sset, &osset);
            if(RETVAL == -1)
            sigfillset(&sset);
            RETVAL=sigprocmask(SIG_BLOCK, &sset, &osset);
            if(RETVAL == -1)
-               XSRETURN(1);
+               XSRETURN_UNDEF;
            ENTER;
            /* Restore signal mask no matter how we exit this block. */
            ENTER;
            /* Restore signal mask no matter how we exit this block. */
-           SAVEDESTRUCTOR(restore_sigmask, &osset);
+           osset_sv = newSVpv((char *)(&osset), sizeof(sigset_t));
+           SAVEFREESV( osset_sv );
+           SAVEDESTRUCTOR_X(restore_sigmask, osset_sv);
 
            RETVAL=-1; /* In case both oldaction and action are 0. */
 
 
            RETVAL=-1; /* In case both oldaction and action are 0. */
 
@@ -1226,7 +1299,7 @@ sigaction(sig, optaction, oldaction = 0)
                }
                RETVAL = sigaction(sig, (struct sigaction *)0, & oact);
                if(RETVAL == -1)
                }
                RETVAL = sigaction(sig, (struct sigaction *)0, & oact);
                if(RETVAL == -1)
-                   XSRETURN(1);
+                   XSRETURN_UNDEF;
                /* Get back the mask. */
                svp = hv_fetch(oldaction, "MASK", 4, TRUE);
                if (sv_isa(*svp, "POSIX::SigSet")) {
                /* Get back the mask. */
                svp = hv_fetch(oldaction, "MASK", 4, TRUE);
                if (sv_isa(*svp, "POSIX::SigSet")) {
@@ -1242,16 +1315,34 @@ sigaction(sig, optaction, oldaction = 0)
                /* Get back the flags. */
                svp = hv_fetch(oldaction, "FLAGS", 5, TRUE);
                sv_setiv(*svp, oact.sa_flags);
                /* Get back the flags. */
                svp = hv_fetch(oldaction, "FLAGS", 5, TRUE);
                sv_setiv(*svp, oact.sa_flags);
+
+               /* Get back whether the old handler used safe signals. */
+               svp = hv_fetch(oldaction, "SAFE", 4, TRUE);
+               sv_setiv(*svp, oact.sa_handler == PL_csighandlerp);
            }
 
            if (action) {
            }
 
            if (action) {
-               /* Vector new handler through %SIG.  (We always use sighandler
-                  for the C signal handler, which reads %SIG to dispatch.) */
+               /* Safe signals use "csighandler", which vectors through the
+                  PL_sighandlerp pointer when it's safe to do so.
+                  (BTW, "csighandler" is very different from "sighandler".) */
+               svp = hv_fetch(action, "SAFE", 4, FALSE);
+               act.sa_handler = (*svp && SvTRUE(*svp))
+                                ? PL_csighandlerp : PL_sighandlerp;
+
+               /* Vector new Perl handler through %SIG.
+                  (The core signal handlers read %SIG to dispatch.) */
                svp = hv_fetch(action, "HANDLER", 7, FALSE);
                if (!svp)
                    croak("Can't supply an action without a HANDLER");
                sv_setsv(*sigsvp, *svp);
                svp = hv_fetch(action, "HANDLER", 7, FALSE);
                if (!svp)
                    croak("Can't supply an action without a HANDLER");
                sv_setsv(*sigsvp, *svp);
-               mg_set(*sigsvp);        /* handles DEFAULT and IGNORE */
+
+               /* This call actually calls sigaction() with almost the
+                  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);
+
+               /* And here again we duplicate -- DEFAULT/IGNORE checking. */
                if(SvPOK(*svp)) {
                        char *s=SvPVX(*svp);
                        if(strEQ(s,"IGNORE")) {
                if(SvPOK(*svp)) {
                        char *s=SvPVX(*svp);
                        if(strEQ(s,"IGNORE")) {
@@ -1260,12 +1351,6 @@ sigaction(sig, optaction, oldaction = 0)
                        else if(strEQ(s,"DEFAULT")) {
                                act.sa_handler = SIG_DFL;
                        }
                        else if(strEQ(s,"DEFAULT")) {
                                act.sa_handler = SIG_DFL;
                        }
-                       else {
-                               act.sa_handler = PL_sighandlerp;
-                       }
-               }
-               else {
-                       act.sa_handler = PL_sighandlerp;
                }
 
                /* Set up any desired mask. */
                }
 
                /* Set up any desired mask. */
@@ -1288,6 +1373,8 @@ sigaction(sig, optaction, oldaction = 0)
                 * essentially meaningless anyway.
                 */
                RETVAL = sigaction(sig, & act, (struct sigaction *)0);
                 * essentially meaningless anyway.
                 */
                RETVAL = sigaction(sig, & act, (struct sigaction *)0);
+               if(RETVAL == -1)
+                   XSRETURN_UNDEF;
            }
 
            LEAVE;
            }
 
            LEAVE;
@@ -1303,20 +1390,25 @@ sigpending(sigset)
 SysRet
 sigprocmask(how, sigset, oldsigset = 0)
        int                     how
 SysRet
 sigprocmask(how, sigset, oldsigset = 0)
        int                     how
-       POSIX::SigSet           sigset
+       POSIX::SigSet           sigset = NO_INIT
        POSIX::SigSet           oldsigset = NO_INIT
 INIT:
        POSIX::SigSet           oldsigset = NO_INIT
 INIT:
-       if ( items < 3 ) {
-           oldsigset = 0;
+       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);
+       } else {
+           croak("sigset is not of type POSIX::SigSet");
        }
        }
-       else if (sv_derived_from(ST(2), "POSIX::SigSet")) {
+
+       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);
            IV tmp = SvIV((SV*)SvRV(ST(2)));
            oldsigset = INT2PTR(POSIX__SigSet,tmp);
-       }
-       else {
-           New(0, oldsigset, 1, sigset_t);
-           sigemptyset(oldsigset);
-           sv_setref_pv(ST(2), "POSIX::SigSet", (void*)oldsigset);
+       } else {
+           croak("oldsigset is not of type POSIX::SigSet");
        }
 
 SysRet
        }
 
 SysRet
@@ -1340,15 +1432,29 @@ dup2(fd1, fd2)
        int             fd1
        int             fd2
 
        int             fd1
        int             fd2
 
-SysRetLong
+SV *
 lseek(fd, offset, whence)
        int             fd
        Off_t           offset
        int             whence
 lseek(fd, offset, whence)
        int             fd
        Off_t           offset
        int             whence
+    CODE:
+       Off_t pos = PerlLIO_lseek(fd, offset, whence);
+       RETVAL = sizeof(Off_t) > sizeof(IV)
+                ? newSVnv((NV)pos) : newSViv((IV)pos);
+    OUTPUT:
+       RETVAL
 
 
-SysRet
+void
 nice(incr)
        int             incr
 nice(incr)
        int             incr
+    PPCODE:
+       errno = 0;
+       if ((incr = nice(incr)) != -1 || errno == 0) {
+           if (incr == 0)
+               XPUSHs(sv_2mortal(newSVpvn("0 but true", 10)));
+           else
+               XPUSHs(sv_2mortal(newSViv(incr)));
+       }
 
 void
 pipe()
 
 void
 pipe()
@@ -1370,7 +1476,7 @@ read(fd, buffer, nbytes)
         char *          buffer = sv_grow( sv_buffer, nbytes+1 );
     CLEANUP:
         if (RETVAL >= 0) {
         char *          buffer = sv_grow( sv_buffer, nbytes+1 );
     CLEANUP:
         if (RETVAL >= 0) {
-            SvCUR(sv_buffer) = RETVAL;
+            SvCUR_set(sv_buffer, RETVAL);
             SvPOK_only(sv_buffer);
             *SvEND(sv_buffer) = '\0';
             SvTAINTED_on(sv_buffer);
             SvPOK_only(sv_buffer);
             *SvEND(sv_buffer) = '\0';
             SvTAINTED_on(sv_buffer);
@@ -1515,10 +1621,12 @@ strtoul(str, base = 0)
        char *unparsed;
     PPCODE:
        num = strtoul(str, &unparsed, base);
        char *unparsed;
     PPCODE:
        num = strtoul(str, &unparsed, base);
-       if (num <= IV_MAX)
-           PUSHs(sv_2mortal(newSViv((IV)num)));
-       else
+#if IVSIZE <= LONGSIZE
+       if (num > IV_MAX)
            PUSHs(sv_2mortal(newSVnv((double)num)));
            PUSHs(sv_2mortal(newSVnv((double)num)));
+       else
+#endif
+           PUSHs(sv_2mortal(newSViv((IV)num)));
        if (GIMME == G_ARRAY) {
            EXTEND(SP, 1);
            if (unparsed)
        if (GIMME == G_ARRAY) {
            EXTEND(SP, 1);
            if (unparsed)
@@ -1536,7 +1644,7 @@ strxfrm(src)
           STRLEN dstlen;
           char *p = SvPV(src,srclen);
           srclen++;
           STRLEN dstlen;
           char *p = SvPV(src,srclen);
           srclen++;
-          ST(0) = sv_2mortal(NEWSV(800,srclen));
+          ST(0) = sv_2mortal(NEWSV(800,srclen*4+1));
           dstlen = strxfrm(SvPVX(ST(0)), p, (size_t)srclen);
           if (dstlen > srclen) {
               dstlen++;
           dstlen = strxfrm(SvPVX(ST(0)), p, (size_t)srclen);
           if (dstlen > srclen) {
               dstlen++;
@@ -1544,7 +1652,7 @@ strxfrm(src)
               strxfrm(SvPVX(ST(0)), p, (size_t)dstlen);
               dstlen--;
           }
               strxfrm(SvPVX(ST(0)), p, (size_t)dstlen);
               dstlen--;
           }
-          SvCUR(ST(0)) = dstlen;
+          SvCUR_set(ST(0), dstlen);
            SvPOK_only(ST(0));
        }
 
            SvPOK_only(ST(0));
        }
 
@@ -1703,7 +1811,18 @@ access(filename, mode)
 
 char *
 ctermid(s = 0)
 
 char *
 ctermid(s = 0)
-       char *          s = 0;
+       char *          s = 0;
+    CODE:
+#ifdef HAS_CTERMID_R
+       s = safemalloc((size_t) L_ctermid);
+#endif
+       RETVAL = ctermid(s);
+    OUTPUT:
+       RETVAL
+    CLEANUP:
+#ifdef HAS_CTERMID_R
+       Safefree(s);
+#endif
 
 char *
 cuserid(s = 0)
 
 char *
 cuserid(s = 0)
@@ -1725,10 +1844,24 @@ pause()
 SysRet
 setgid(gid)
        Gid_t           gid
 SysRet
 setgid(gid)
        Gid_t           gid
+    CLEANUP:
+#ifndef WIN32
+       if (RETVAL >= 0) {
+           PL_gid  = getgid();
+           PL_egid = getegid();
+       }
+#endif
 
 SysRet
 setuid(uid)
        Uid_t           uid
 
 SysRet
 setuid(uid)
        Uid_t           uid
+    CLEANUP:
+#ifndef WIN32
+       if (RETVAL >= 0) {
+           PL_uid  = getuid();
+           PL_euid = geteuid();
+       }
+#endif
 
 SysRetLong
 sysconf(name)
 
 SysRetLong
 sysconf(name)
@@ -1738,40 +1871,27 @@ char *
 ttyname(fd)
        int             fd
 
 ttyname(fd)
        int             fd
 
-#XXX: use sv_getcwd()
 void
 getcwd()
 void
 getcwd()
-       PPCODE:
-#ifdef HAS_GETCWD
-       char *          buf;
-       int             buflen = 128;
-
-       New(0, buf, buflen, char);
-       /* Many getcwd()s know how to automatically allocate memory
-        * for the directory if the buffer argument is NULL but...
-        * (1) we cannot assume all getcwd()s do that
-        * (2) this may interfere with Perl's malloc
-         * So let's not.  --jhi */
-       while ((getcwd(buf, buflen) == NULL) && errno == ERANGE) {
-           buflen += 128;
-           if (buflen > MAXPATHLEN) {
-               Safefree(buf);
-               buf = NULL;
-               break;
-           }
-           Renew(buf, buflen, char);
-       }
-       if (buf) {
-           PUSHs(sv_2mortal(newSVpv(buf, 0)));
-           Safefree(buf);
-       }
-       else
-           PUSHs(&PL_sv_undef);
+    PPCODE:
+      {
+       dXSTARG;
+       getcwd_sv(TARG);
+       XSprePUSH; PUSHTARG;
+      }
+
+SysRet
+lchown(uid, gid, path)
+       Uid_t           uid
+       Gid_t           gid
+       char *          path
+    CODE:
+#ifdef HAS_LCHOWN
+       /* yes, the order of arguments is different,
+        * but consistent with CORE::chown() */
+       RETVAL = lchown(path, uid, gid);
 #else
 #else
-       require_pv("Cwd.pm");
-        /* Module require may have grown the stack */
-       SPAGAIN;
-       PUSHMARK(sp);
-       PUTBACK;
-       XSRETURN(call_pv("Cwd::cwd", GIMME_V));
+       RETVAL = not_here("lchown");
 #endif
 #endif
+    OUTPUT:
+       RETVAL