tweaks to allow both mingw32{gcc-2.8.1,egcs-1.0.2} build and test
[p5sagit/p5-mst-13.2.git] / ext / POSIX / POSIX.xs
index 3d68d91..41c6ba3 100644 (file)
@@ -1,16 +1,25 @@
+#ifdef WIN32
+#define _POSIX_
+#endif
 #include "EXTERN.h"
+#define PERLIO_NOT_STDIO 1
 #include "perl.h"
 #include "XSUB.h"
+#ifdef PERL_OBJECT     /* XXX _very_ temporary hacks */
+#  undef signal
+#  undef open
+#  define open PerlLIO_open3
+#  undef TAINT_PROPER
+#  define TAINT_PROPER(a)
+#endif
 #include <ctype.h>
 #ifdef I_DIRENT    /* XXX maybe better to just rely on perl.h? */
 #include <dirent.h>
 #endif
 #include <errno.h>
-#include <fcntl.h>
 #ifdef I_FLOAT
 #include <float.h>
 #endif
-#include <grp.h>
 #ifdef I_LIMITS
 #include <limits.h>
 #endif
@@ -21,9 +30,8 @@
 #endif
 #include <setjmp.h>
 #include <signal.h>
-#ifdef I_STDARG
 #include <stdarg.h>
-#endif
+
 #ifdef I_STDDEF
 #include <stddef.h>
 #endif
 #if defined(I_TERMIOS)
 #include <termios.h>
 #endif
-#include <stdio.h>
 #ifdef I_STDLIB
 #include <stdlib.h>
 #endif
 #include <string.h>
 #include <sys/stat.h>
-#include <sys/times.h>
 #include <sys/types.h>
-#ifdef HAS_UNAME
-#include <sys/utsname.h>
-#endif
-#include <sys/wait.h>
 #include <time.h>
+#ifdef I_UNISTD
 #include <unistd.h>
-#ifdef I_UTIME
-#include <utime.h>
 #endif
+#include <fcntl.h>
+
+#if defined(__VMS) && !defined(__POSIX_SOURCE)
+#  include <libdef.h>       /* LIB$_INVARG constant */
+#  include <lib$routines.h> /* prototype for lib$ediv() */
+#  include <starlet.h>      /* prototype for sys$gettim() */
+#  if DECC_VERSION < 50000000
+#    define pid_t int       /* old versions of DECC miss this in types.h */
+#  endif
+
+#  undef mkfifo  /* #defined in perl.h */
+#  define mkfifo(a,b) (not_here("mkfifo"),-1)
+#  define tzset() not_here("tzset")
+
+#if ((__VMS_VER >= 70000000) && (__DECC_VER >= 50200000)) || (__CRTL_VER >= 70000000)
+#    define HAS_TZNAME  /* shows up in VMS 7.0 or Dec C 5.6 */
+#    include <utsname.h>
+#  endif /* __VMS_VER >= 70000000 or Dec C 5.6 */
+
+   /* The POSIX notion of ttyname() is better served by getname() under VMS */
+   static char ttnambuf[64];
+#  define ttyname(fd) (isatty(fd) > 0 ? getname(fd,ttnambuf,0) : NULL)
+
+   /* The non-POSIX CRTL times() has void return type, so we just get the
+      current time directly */
+   clock_t vms_times(struct tms *bufptr) {
+       clock_t retval;
+       /* Get wall time and convert to 10 ms intervals to
+        * produce the return value that the POSIX standard expects */
+#  if defined(__DECC) && defined (__ALPHA)
+#    include <ints.h>
+       uint64 vmstime;
+       _ckvmssts(sys$gettim(&vmstime));
+       vmstime /= 100000;
+       retval = vmstime & 0x7fffffff;
+#  else
+       /* (Older hw or ccs don't have an atomic 64-bit type, so we
+        * juggle 32-bit ints (and a float) to produce a time_t result
+        * with minimal loss of information.) */
+       long int vmstime[2],remainder,divisor = 100000;
+       _ckvmssts(sys$gettim((unsigned long int *)vmstime));
+       vmstime[1] &= 0x7fff;  /* prevent overflow in EDIV */
+       _ckvmssts(lib$ediv(&divisor,vmstime,(long int *)&retval,&remainder));
+#  endif
+       /* Fill in the struct tms using the CRTL routine . . .*/
+       times((tbuffer_t *)bufptr);
+       return (clock_t) retval;
+   }
+#  define times(t) vms_times(t)
+#else
+#if defined (WIN32)
+#  undef mkfifo  /* #defined in perl.h */
+#  define mkfifo(a,b) not_here("mkfifo")
+#  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
+#  ifdef __MINGW32__
+#    define mode_t short
+#    ifndef tzset
+#      define tzset()          not_here("tzset")
+#    endif
+#    ifndef _POSIX_OPEN_MAX
+#      define _POSIX_OPEN_MAX  FOPEN_MAX       /* XXX bogus ? */
+#    endif
+#  endif
+#  define sigaction(a,b,c)     not_here("sigaction")
+#  define sigpending(a)                not_here("sigpending")
+#  define sigprocmask(a,b,c)   not_here("sigprocmask")
+#  define sigsuspend(a)                not_here("sigsuspend")
+#  define sigemptyset(a)       not_here("sigemptyset")
+#  define sigaddset(a,b)       not_here("sigaddset")
+#  define sigdelset(a,b)       not_here("sigdelset")
+#  define sigfillset(a)                not_here("sigfillset")
+#  define sigismember(a,b)     not_here("sigismember")
+#else
+#  include <grp.h>
+#  include <sys/times.h>
+#  ifdef HAS_UNAME
+#    include <sys/utsname.h>
+#  endif
+#  include <sys/wait.h>
+#  ifdef I_UTIME
+#    include <utime.h>
+#  endif
+#endif /* WIN32 */
+#endif /* __VMS */
 
-typedef FILE * InputStream;
-typedef FILE * OutputStream;
 typedef int SysRet;
 typedef long SysRetLong;
 typedef sigset_t* POSIX__SigSet;
@@ -80,6 +171,9 @@ typedef struct termios* POSIX__Termios;
 
 /* Possibly needed prototypes */
 char *cuserid _((char *));
+double strtod _((const char *, char **));
+long strtol _((const char *, char **, int));
+unsigned long strtoul _((const char *, char **, int));
 
 #ifndef HAS_CUSERID
 #define cuserid(a) (char *) not_here("cuserid")
@@ -116,6 +210,15 @@ char *cuserid _((char *));
 #ifndef HAS_STRCOLL
 #define strcoll(s1,s2) not_here("strcoll")
 #endif
+#ifndef HAS_STRTOD
+#define strtod(s1,s2) not_here("strtod")
+#endif
+#ifndef HAS_STRTOL
+#define strtol(s1,s2,b) not_here("strtol")
+#endif
+#ifndef HAS_STRTOUL
+#define strtoul(s1,s2,b) not_here("strtoul")
+#endif
 #ifndef HAS_STRXFRM
 #define strxfrm(s1,s2,n) not_here("strxfrm")
 #endif
@@ -135,13 +238,6 @@ char *cuserid _((char *));
 #define waitpid(a,b,c) not_here("waitpid")
 #endif
 
-#ifndef HAS_FGETPOS
-#define fgetpos(a,b) not_here("fgetpos")
-#endif
-#ifndef HAS_FSETPOS
-#define fsetpos(a,b) not_here("fsetpos")
-#endif
-
 #ifndef HAS_MBLEN
 #ifndef mblen
 #define mblen(a,b) not_here("mblen")
@@ -175,12 +271,57 @@ char *cuserid _((char *));
 #endif
 
 #ifdef HAS_TZNAME
+#  ifndef WIN32
 extern char *tzname[];
+#  endif
 #else
+#if !defined(WIN32) || (defined(__MINGW32__) && !defined(tzname))
 char *tzname[] = { "" , "" };
 #endif
+#endif
+
+/* XXX struct tm on some systems (SunOS4/BSD) contains extra (non POSIX)
+ * fields for which we don't have Configure support yet:
+ *   char *tm_zone;   -- abbreviation of timezone name
+ *   long tm_gmtoff;  -- offset from GMT in seconds
+ * To workaround core dumps from the uninitialised tm_zone we get the
+ * system to give us a reasonable struct to copy.  This fix means that
+ * strftime uses the tm_zone and tm_gmtoff values returned by
+ * localtime(time()). That should give the desired result most of the
+ * time. But probably not always!
+ *
+ * This is a temporary workaround to be removed once Configure
+ * support is added and NETaa14816 is considered in full.
+ * It does not address tzname aspects of NETaa14816.
+ */
+#ifdef HAS_GNULIBC
+# ifndef STRUCT_TM_HASZONE
+#    define STRUCT_TM_HAS_ZONE
+# endif
+#endif
+
+#ifdef STRUCT_TM_HASZONE
+static void
+init_tm(ptm)           /* see mktime, strftime and asctime     */
+    struct tm *ptm;
+{
+    Time_t now;
+    (void)time(&now);
+    Copy(localtime(&now), ptm, 1, struct tm);
+}
+
+#else
+# define init_tm(ptm)
+#endif
+
+
+#ifdef HAS_LONG_DOUBLE
+#  if LONG_DOUBLESIZE > DOUBLESIZE
+#    undef HAS_LONG_DOUBLE  /* XXX until we figure out how to use them */
+#  endif
+#endif
 
-#ifndef HAS_LONG_DOUBLE /* XXX What to do about long doubles? */
+#ifndef HAS_LONG_DOUBLE 
 #ifdef LDBL_MAX
 #undef LDBL_MAX
 #endif
@@ -193,17 +334,19 @@ char *tzname[] = { "" , "" };
 #endif
 
 static int
-not_here(s)
-char *s;
+not_here(char *s)
 {
     croak("POSIX::%s not implemented on this architecture", s);
     return -1;
 }
 
-static double
-constant(name, arg)
-char *name;
-int arg;
+static
+#ifdef HAS_LONG_DOUBLE
+long double
+#else
+double
+#endif
+constant(char *name, int arg)
 {
     errno = 0;
     switch (*name) {
@@ -476,12 +619,36 @@ int arg;
 #else
                goto not_there;
 #endif
+           if (strEQ(name, "EADDRINUSE"))
+#ifdef EADDRINUSE
+               return EADDRINUSE;
+#else
+               goto not_there;
+#endif
+           if (strEQ(name, "EADDRNOTAVAIL"))
+#ifdef EADDRNOTAVAIL
+               return EADDRNOTAVAIL;
+#else
+               goto not_there;
+#endif
+           if (strEQ(name, "EAFNOSUPPORT"))
+#ifdef EAFNOSUPPORT
+               return EAFNOSUPPORT;
+#else
+               goto not_there;
+#endif
            if (strEQ(name, "EAGAIN"))
 #ifdef EAGAIN
                return EAGAIN;
 #else
                goto not_there;
 #endif
+           if (strEQ(name, "EALREADY"))
+#ifdef EALREADY
+               return EALREADY;
+#else
+               goto not_there;
+#endif
            break;
        case 'B':
            if (strEQ(name, "EBADF"))
@@ -528,6 +695,24 @@ int arg;
 #else
                goto not_there;
 #endif
+           if (strEQ(name, "ECONNABORTED"))
+#ifdef ECONNABORTED
+               return ECONNABORTED;
+#else
+               goto not_there;
+#endif
+           if (strEQ(name, "ECONNREFUSED"))
+#ifdef ECONNREFUSED
+               return ECONNREFUSED;
+#else
+               goto not_there;
+#endif
+           if (strEQ(name, "ECONNRESET"))
+#ifdef ECONNRESET
+               return ECONNRESET;
+#else
+               goto not_there;
+#endif
            break;
        case 'D':
            if (strEQ(name, "EDEADLK"))
@@ -536,12 +721,24 @@ int arg;
 #else
                goto not_there;
 #endif
+           if (strEQ(name, "EDESTADDRREQ"))
+#ifdef EDESTADDRREQ
+               return EDESTADDRREQ;
+#else
+               goto not_there;
+#endif
            if (strEQ(name, "EDOM"))
 #ifdef EDOM
                return EDOM;
 #else
                goto not_there;
 #endif
+           if (strEQ(name, "EDQUOT"))
+#ifdef EDQUOT
+               return EDQUOT;
+#else
+               goto not_there;
+#endif
            break;
        case 'E':
            if (strEQ(name, "EEXIST"))
@@ -565,7 +762,27 @@ int arg;
                goto not_there;
 #endif
            break;
+       case 'H':
+           if (strEQ(name, "EHOSTDOWN"))
+#ifdef EHOSTDOWN
+               return EHOSTDOWN;
+#else
+               goto not_there;
+#endif
+           if (strEQ(name, "EHOSTUNREACH"))
+#ifdef EHOSTUNREACH
+               return EHOSTUNREACH;
+#else
+               goto not_there;
+#endif
+           break;
        case 'I':
+           if (strEQ(name, "EINPROGRESS"))
+#ifdef EINPROGRESS
+               return EINPROGRESS;
+#else
+               goto not_there;
+#endif
            if (strEQ(name, "EINTR"))
 #ifdef EINTR
                return EINTR;
@@ -584,12 +801,24 @@ int arg;
 #else
                goto not_there;
 #endif
+           if (strEQ(name, "EISCONN"))
+#ifdef EISCONN
+               return EISCONN;
+#else
+               goto not_there;
+#endif
            if (strEQ(name, "EISDIR"))
 #ifdef EISDIR
                return EISDIR;
 #else
                goto not_there;
 #endif
+           if (strEQ(name, "ELOOP"))
+#ifdef ELOOP
+               return ELOOP;
+#else
+               goto not_there;
+#endif
            break;
        case 'M':
            if (strEQ(name, "EMFILE"))
@@ -604,29 +833,71 @@ int arg;
 #else
                goto not_there;
 #endif
+           if (strEQ(name, "EMSGSIZE"))
+#ifdef EMSGSIZE
+               return EMSGSIZE;
+#else
+               goto not_there;
+#endif
            break;
        case 'N':
+           if (strEQ(name, "ENETDOWN"))
+#ifdef ENETDOWN
+               return ENETDOWN;
+#else
+               goto not_there;
+#endif
+           if (strEQ(name, "ENETRESET"))
+#ifdef ENETRESET
+               return ENETRESET;
+#else
+               goto not_there;
+#endif
+           if (strEQ(name, "ENETUNREACH"))
+#ifdef ENETUNREACH
+               return ENETUNREACH;
+#else
+               goto not_there;
+#endif
+           if (strEQ(name, "ENOBUFS"))
+#ifdef ENOBUFS
+               return ENOBUFS;
+#else
+               goto not_there;
+#endif
+           if (strEQ(name, "ENOEXEC"))
+#ifdef ENOEXEC
+               return ENOEXEC;
+#else
+               goto not_there;
+#endif
            if (strEQ(name, "ENOMEM"))
 #ifdef ENOMEM
                return ENOMEM;
 #else
                goto not_there;
 #endif
+           if (strEQ(name, "ENOPROTOOPT"))
+#ifdef ENOPROTOOPT
+               return ENOPROTOOPT;
+#else
+               goto not_there;
+#endif
            if (strEQ(name, "ENOSPC"))
 #ifdef ENOSPC
                return ENOSPC;
 #else
                goto not_there;
 #endif
-           if (strEQ(name, "ENOEXEC"))
-#ifdef ENOEXEC
-               return ENOEXEC;
+           if (strEQ(name, "ENOTBLK"))
+#ifdef ENOTBLK
+               return ENOTBLK;
 #else
                goto not_there;
 #endif
-           if (strEQ(name, "ENOTTY"))
-#ifdef ENOTTY
-               return ENOTTY;
+           if (strEQ(name, "ENOTCONN"))
+#ifdef ENOTCONN
+               return ENOTCONN;
 #else
                goto not_there;
 #endif
@@ -642,6 +913,18 @@ int arg;
 #else
                goto not_there;
 #endif
+           if (strEQ(name, "ENOTSOCK"))
+#ifdef ENOTSOCK
+               return ENOTSOCK;
+#else
+               goto not_there;
+#endif
+           if (strEQ(name, "ENOTTY"))
+#ifdef ENOTTY
+               return ENOTTY;
+#else
+               goto not_there;
+#endif
            if (strEQ(name, "ENFILE"))
 #ifdef ENFILE
                return ENFILE;
@@ -692,6 +975,12 @@ int arg;
 #else
                goto not_there;
 #endif
+           if (strEQ(name, "EOPNOTSUPP"))
+#ifdef EOPNOTSUPP
+               return EOPNOTSUPP;
+#else
+               goto not_there;
+#endif
            break;
        case 'P':
            if (strEQ(name, "EPERM"))
@@ -700,12 +989,36 @@ int arg;
 #else
                goto not_there;
 #endif
+           if (strEQ(name, "EPFNOSUPPORT"))
+#ifdef EPFNOSUPPORT
+               return EPFNOSUPPORT;
+#else
+               goto not_there;
+#endif
            if (strEQ(name, "EPIPE"))
 #ifdef EPIPE
                return EPIPE;
 #else
                goto not_there;
 #endif
+           if (strEQ(name, "EPROCLIM"))
+#ifdef EPROCLIM
+               return EPROCLIM;
+#else
+               goto not_there;
+#endif
+           if (strEQ(name, "EPROTONOSUPPORT"))
+#ifdef EPROTONOSUPPORT
+               return EPROTONOSUPPORT;
+#else
+               goto not_there;
+#endif
+           if (strEQ(name, "EPROTOTYPE"))
+#ifdef EPROTOTYPE
+               return EPROTOTYPE;
+#else
+               goto not_there;
+#endif
            break;
        case 'R':
            if (strEQ(name, "ERANGE"))
@@ -714,6 +1027,18 @@ int arg;
 #else
                goto not_there;
 #endif
+           if (strEQ(name, "EREMOTE"))
+#ifdef EREMOTE
+               return EREMOTE;
+#else
+               goto not_there;
+#endif
+           if (strEQ(name, "ERESTART"))
+#ifdef ERESTART
+               return ERESTART;
+#else
+               goto not_there;
+#endif
            if (strEQ(name, "EROFS"))
 #ifdef EROFS
                return EROFS;
@@ -722,6 +1047,18 @@ int arg;
 #endif
            break;
        case 'S':
+           if (strEQ(name, "ESHUTDOWN"))
+#ifdef ESHUTDOWN
+               return ESHUTDOWN;
+#else
+               goto not_there;
+#endif
+           if (strEQ(name, "ESOCKTNOSUPPORT"))
+#ifdef ESOCKTNOSUPPORT
+               return ESOCKTNOSUPPORT;
+#else
+               goto not_there;
+#endif
            if (strEQ(name, "ESPIPE"))
 #ifdef ESPIPE
                return ESPIPE;
@@ -734,7 +1071,49 @@ int arg;
 #else
                goto not_there;
 #endif
+           if (strEQ(name, "ESTALE"))
+#ifdef ESTALE
+               return ESTALE;
+#else
+               goto not_there;
+#endif
            break;
+       case 'T':
+           if (strEQ(name, "ETIMEDOUT"))
+#ifdef ETIMEDOUT
+               return ETIMEDOUT;
+#else
+               goto not_there;
+#endif
+           if (strEQ(name, "ETOOMANYREFS"))
+#ifdef ETOOMANYREFS
+               return ETOOMANYREFS;
+#else
+               goto not_there;
+#endif
+           if (strEQ(name, "ETXTBSY"))
+#ifdef ETXTBSY
+               return ETXTBSY;
+#else
+               goto not_there;
+#endif
+           break;
+       case 'U':
+           if (strEQ(name, "EUSERS"))
+#ifdef EUSERS
+               return EUSERS;
+#else
+               goto not_there;
+#endif
+           break;
+       case 'W':
+           if (strEQ(name, "EWOULDBLOCK"))
+#ifdef EWOULDBLOCK
+               return EWOULDBLOCK;
+#else
+               goto not_there;
+#endif
+           break;
        case 'X':
            if (strEQ(name, "EXIT_FAILURE"))
 #ifdef EXIT_FAILURE
@@ -1344,13 +1723,13 @@ int arg;
                    goto not_there;
 #endif
 #ifdef SIG_DFL
-               if (strEQ(name, "SIG_DFL")) return (int)SIG_DFL;
+               if (strEQ(name, "SIG_DFL")) return (IV)SIG_DFL;
 #endif
 #ifdef SIG_ERR
-               if (strEQ(name, "SIG_ERR")) return (int)SIG_ERR;
+               if (strEQ(name, "SIG_ERR")) return (IV)SIG_ERR;
 #endif
 #ifdef SIG_IGN
-               if (strEQ(name, "SIG_IGN")) return (int)SIG_IGN;
+               if (strEQ(name, "SIG_IGN")) return (IV)SIG_IGN;
 #endif
                if (strEQ(name, "SIG_SETMASK"))
 #ifdef SIG_SETMASK
@@ -1483,21 +1862,6 @@ int arg;
            break;
        }
        if (name[1] == '_') {
-#ifdef S_ISBLK
-           if (strEQ(name, "S_ISBLK")) return S_ISBLK(arg);
-#endif
-#ifdef S_ISCHR
-           if (strEQ(name, "S_ISCHR")) return S_ISCHR(arg);
-#endif
-#ifdef S_ISDIR
-           if (strEQ(name, "S_ISDIR")) return S_ISDIR(arg);
-#endif
-#ifdef S_ISFIFO
-           if (strEQ(name, "S_ISFIFO")) return S_ISFIFO(arg);
-#endif
-#ifdef S_ISREG
-           if (strEQ(name, "S_ISREG")) return S_ISREG(arg);
-#endif
            if (strEQ(name, "S_ISGID"))
 #ifdef S_ISGID
                return S_ISGID;
@@ -1582,6 +1946,22 @@ int arg;
 #else
                goto not_there;
 #endif
+           errno = EAGAIN;             /* the following aren't constants */
+#ifdef S_ISBLK
+           if (strEQ(name, "S_ISBLK")) return S_ISBLK(arg);
+#endif
+#ifdef S_ISCHR
+           if (strEQ(name, "S_ISCHR")) return S_ISCHR(arg);
+#endif
+#ifdef S_ISDIR
+           if (strEQ(name, "S_ISDIR")) return S_ISDIR(arg);
+#endif
+#ifdef S_ISFIFO
+           if (strEQ(name, "S_ISFIFO")) return S_ISFIFO(arg);
+#endif
+#ifdef S_ISREG
+           if (strEQ(name, "S_ISREG")) return S_ISREG(arg);
+#endif
            break;
        }
        if (strEQ(name, "SEEK_CUR"))
@@ -1620,12 +2000,51 @@ int arg;
 #else
            goto not_there;
 #endif
-       if (strEQ(name, "SA_NOCLDSTOP"))
+       if (strnEQ(name, "SA_", 3)) {
+           if (strEQ(name, "SA_NOCLDSTOP"))
 #ifdef SA_NOCLDSTOP
-           return SA_NOCLDSTOP;
+               return SA_NOCLDSTOP;
 #else
-           goto not_there;
+               goto not_there;
+#endif
+           if (strEQ(name, "SA_NOCLDWAIT"))
+#ifdef SA_NOCLDWAIT
+               return SA_NOCLDWAIT;
+#else
+               goto not_there;
+#endif
+           if (strEQ(name, "SA_NODEFER"))
+#ifdef SA_NODEFER
+               return SA_NODEFER;
+#else
+               goto not_there;
+#endif
+           if (strEQ(name, "SA_ONSTACK"))
+#ifdef SA_ONSTACK
+               return SA_ONSTACK;
+#else
+               goto not_there;
+#endif
+           if (strEQ(name, "SA_RESETHAND"))
+#ifdef SA_RESETHAND
+               return SA_RESETHAND;
+#else
+               goto not_there;
+#endif
+           if (strEQ(name, "SA_RESTART"))
+#ifdef SA_RESTART
+               return SA_RESTART;
+#else
+               goto not_there;
 #endif
+           if (strEQ(name, "SA_SIGINFO"))
+#ifdef SA_SIGINFO
+               return SA_SIGINFO;
+#else
+               goto not_there;
+#endif
+           break;
+       }
        if (strEQ(name, "SCHAR_MAX"))
 #ifdef SCHAR_MAX
            return SCHAR_MAX;
@@ -1844,6 +2263,19 @@ int arg;
 #else
            goto not_there;
 #endif
+       if (strEQ(name, "WNOHANG"))
+#ifdef WNOHANG
+           return WNOHANG;
+#else
+           goto not_there;
+#endif
+       if (strEQ(name, "WUNTRACED"))
+#ifdef WUNTRACED
+           return WUNTRACED;
+#else
+           goto not_there;
+#endif
+       errno = EAGAIN;         /* the following aren't constants */
 #ifdef WEXITSTATUS
        if (strEQ(name, "WEXITSTATUS")) return WEXITSTATUS(arg);
 #endif
@@ -1856,24 +2288,12 @@ int arg;
 #ifdef WIFSTOPPED
        if (strEQ(name, "WIFSTOPPED")) return WIFSTOPPED(arg);
 #endif
-       if (strEQ(name, "WNOHANG"))
-#ifdef WNOHANG
-           return WNOHANG;
-#else
-           goto not_there;
-#endif
 #ifdef WSTOPSIG
        if (strEQ(name, "WSTOPSIG")) return WSTOPSIG(arg);
 #endif
 #ifdef WTERMSIG
        if (strEQ(name, "WTERMSIG")) return WTERMSIG(arg);
 #endif
-       if (strEQ(name, "WUNTRACED"))
-#ifdef WUNTRACED
-           return WUNTRACED;
-#else
-           goto not_there;
-#endif
        break;
     case 'X':
        if (strEQ(name, "X_OK"))
@@ -1886,55 +2306,55 @@ int arg;
     case '_':
        if (strnEQ(name, "_PC_", 4)) {
            if (strEQ(name, "_PC_CHOWN_RESTRICTED"))
-#ifdef _PC_CHOWN_RESTRICTED
+#if defined(_PC_CHOWN_RESTRICTED) || HINT_SC_EXIST
                return _PC_CHOWN_RESTRICTED;
 #else
                goto not_there;
 #endif
            if (strEQ(name, "_PC_LINK_MAX"))
-#ifdef _PC_LINK_MAX
+#if defined(_PC_LINK_MAX) || HINT_SC_EXIST
                return _PC_LINK_MAX;
 #else
                goto not_there;
 #endif
            if (strEQ(name, "_PC_MAX_CANON"))
-#ifdef _PC_MAX_CANON
+#if defined(_PC_MAX_CANON) || HINT_SC_EXIST
                return _PC_MAX_CANON;
 #else
                goto not_there;
 #endif
            if (strEQ(name, "_PC_MAX_INPUT"))
-#ifdef _PC_MAX_INPUT
+#if defined(_PC_MAX_INPUT) || HINT_SC_EXIST
                return _PC_MAX_INPUT;
 #else
                goto not_there;
 #endif
            if (strEQ(name, "_PC_NAME_MAX"))
-#ifdef _PC_NAME_MAX
+#if defined(_PC_NAME_MAX) || HINT_SC_EXIST
                return _PC_NAME_MAX;
 #else
                goto not_there;
 #endif
            if (strEQ(name, "_PC_NO_TRUNC"))
-#ifdef _PC_NO_TRUNC
+#if defined(_PC_NO_TRUNC) || HINT_SC_EXIST
                return _PC_NO_TRUNC;
 #else
                goto not_there;
 #endif
            if (strEQ(name, "_PC_PATH_MAX"))
-#ifdef _PC_PATH_MAX
+#if defined(_PC_PATH_MAX) || HINT_SC_EXIST
                return _PC_PATH_MAX;
 #else
                goto not_there;
 #endif
            if (strEQ(name, "_PC_PIPE_BUF"))
-#ifdef _PC_PIPE_BUF
+#if defined(_PC_PIPE_BUF) || HINT_SC_EXIST
                return _PC_PIPE_BUF;
 #else
                goto not_there;
 #endif
            if (strEQ(name, "_PC_VDISABLE"))
-#ifdef _PC_VDISABLE
+#if defined(_PC_VDISABLE) || HINT_SC_EXIST
                return _PC_VDISABLE;
 #else
                goto not_there;
@@ -2060,86 +2480,67 @@ int arg;
        }
        if (strnEQ(name, "_SC_", 4)) {
            if (strEQ(name, "_SC_ARG_MAX"))
-#ifdef _SC_ARG_MAX
+#if defined(_SC_ARG_MAX) || HINT_SC_EXIST
                return _SC_ARG_MAX;
 #else
                goto not_there;
 #endif
            if (strEQ(name, "_SC_CHILD_MAX"))
-#ifdef _SC_CHILD_MAX
+#if defined(_SC_CHILD_MAX) || HINT_SC_EXIST
                return _SC_CHILD_MAX;
 #else
                goto not_there;
 #endif
            if (strEQ(name, "_SC_CLK_TCK"))
-#ifdef _SC_CLK_TCK
+#if defined(_SC_CLK_TCK) || HINT_SC_EXIST
                return _SC_CLK_TCK;
 #else
                goto not_there;
 #endif
            if (strEQ(name, "_SC_JOB_CONTROL"))
-#ifdef _SC_JOB_CONTROL
+#if defined(_SC_JOB_CONTROL) || HINT_SC_EXIST
                return _SC_JOB_CONTROL;
 #else
                goto not_there;
 #endif
            if (strEQ(name, "_SC_NGROUPS_MAX"))
-#ifdef _SC_NGROUPS_MAX
+#if defined(_SC_NGROUPS_MAX) || HINT_SC_EXIST
                return _SC_NGROUPS_MAX;
 #else
                goto not_there;
 #endif
            if (strEQ(name, "_SC_OPEN_MAX"))
-#ifdef _SC_OPEN_MAX
+#if defined(_SC_OPEN_MAX) || HINT_SC_EXIST
                return _SC_OPEN_MAX;
 #else
                goto not_there;
 #endif
            if (strEQ(name, "_SC_SAVED_IDS"))
-#ifdef _SC_SAVED_IDS
+#if defined(_SC_SAVED_IDS) || HINT_SC_EXIST
                return _SC_SAVED_IDS;
 #else
                goto not_there;
 #endif
            if (strEQ(name, "_SC_STREAM_MAX"))
-#ifdef _SC_STREAM_MAX
+#if defined(_SC_STREAM_MAX) || HINT_SC_EXIST
                return _SC_STREAM_MAX;
 #else
                goto not_there;
 #endif
            if (strEQ(name, "_SC_TZNAME_MAX"))
-#ifdef _SC_TZNAME_MAX
+#if defined(_SC_TZNAME_MAX) || HINT_SC_EXIST
                return _SC_TZNAME_MAX;
 #else
                goto not_there;
 #endif
            if (strEQ(name, "_SC_VERSION"))
-#ifdef _SC_VERSION
+#if defined(_SC_VERSION) || HINT_SC_EXIST
                return _SC_VERSION;
 #else
                goto not_there;
 #endif
            break;
        }
-       if (strEQ(name, "_IOFBF"))
-#ifdef _IOFBF
-           return _IOFBF;
-#else
-           goto not_there;
-#endif
-       if (strEQ(name, "_IOLBF"))
-#ifdef _IOLBF
-           return _IOLBF;
-#else
-           goto not_there;
-#endif
-       if (strEQ(name, "_IONBF"))
-#ifdef _IONBF
-           return _IONBF;
-#else
-           goto not_there;
-#endif
-       break;
     }
     errno = EINVAL;
     return 0;
@@ -2206,6 +2607,7 @@ new(packname = "POSIX::Termios", ...)
            RETVAL = (struct termios*)safemalloc(sizeof(struct termios));
 #else
            not_here("termios");
+        RETVAL = 0;
 #endif
        }
     OUTPUT:
@@ -2255,7 +2657,8 @@ getiflag(termios_ref)
 #ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
        RETVAL = termios_ref->c_iflag;
 #else
-           not_here("getiflag");
+     not_here("getiflag");
+     RETVAL = 0;
 #endif
     OUTPUT:
        RETVAL
@@ -2267,7 +2670,8 @@ getoflag(termios_ref)
 #ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
        RETVAL = termios_ref->c_oflag;
 #else
-           not_here("getoflag");
+     not_here("getoflag");
+     RETVAL = 0;
 #endif
     OUTPUT:
        RETVAL
@@ -2279,7 +2683,8 @@ getcflag(termios_ref)
 #ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
        RETVAL = termios_ref->c_cflag;
 #else
-           not_here("getcflag");
+     not_here("getcflag");
+     RETVAL = 0;
 #endif
     OUTPUT:
        RETVAL
@@ -2291,7 +2696,8 @@ getlflag(termios_ref)
 #ifdef I_TERMIOS /* References a termios structure member so ifdef it out. */
        RETVAL = termios_ref->c_lflag;
 #else
-           not_here("getlflag");
+     not_here("getlflag");
+     RETVAL = 0;
 #endif
     OUTPUT:
        RETVAL
@@ -2306,7 +2712,8 @@ getcc(termios_ref, ccix)
            croak("Bad getcc subscript");
        RETVAL = termios_ref->c_cc[ccix];
 #else
-           not_here("getcc");
+     not_here("getcc");
+     RETVAL = 0;
 #endif
     OUTPUT:
        RETVAL
@@ -2380,65 +2787,6 @@ setcc(termios_ref, ccix, cc)
 #endif
 
 
-
-MODULE = FileHandle    PACKAGE = FileHandle    PREFIX = f
-
-SV *
-fgetpos(handle)
-       InputStream     handle
-    CODE:
-       {
-           Fpos_t pos;
-           fgetpos(handle, &pos);
-           ST(0) = sv_2mortal(newSVpv((char*)&pos, sizeof(Fpos_t)));
-       }
-
-SysRet
-fsetpos(handle, pos)
-       InputStream     handle
-       SV *            pos
-    CODE:
-       RETVAL = fsetpos(handle, (Fpos_t*)SvPVX(pos));
-    OUTPUT:
-       RETVAL
-
-int
-ungetc(handle, c)
-       InputStream     handle
-       int             c
-    CODE:
-       RETVAL = ungetc(c, handle);
-    OUTPUT:
-       RETVAL
-
-OutputStream
-new_tmpfile(packname = "FileHandle")
-    char *             packname
-    CODE:
-       RETVAL = tmpfile();
-    OUTPUT:
-       RETVAL
-
-int
-ferror(handle)
-       InputStream     handle
-
-SysRet
-fflush(handle)
-       OutputStream    handle
-
-void
-setbuf(handle, buf)
-       OutputStream    handle
-       char *          buf = SvPOK(ST(1)) ? sv_grow(ST(1), BUFSIZ) : 0;
-
-SysRet
-setvbuf(handle, buf, type, size)
-       OutputStream    handle
-       char *          buf = SvPOK(ST(1)) ? sv_grow(ST(1), SvIV(ST(3))) : 0;
-       int             type
-       int             size
-
 MODULE = POSIX         PACKAGE = POSIX
 
 double
@@ -2448,11 +2796,11 @@ constant(name,arg)
 
 int
 isalnum(charstring)
-       char *          charstring
+       unsigned char * charstring
     CODE:
-       char *s;
-       RETVAL = 1;
-       for (s = charstring; *s && RETVAL; s++)
+       unsigned char *s = charstring;
+       unsigned char *e = s + na;      /* "na" set by typemap side effect */
+       for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isalnum(*s))
                RETVAL = 0;
     OUTPUT:
@@ -2460,11 +2808,11 @@ isalnum(charstring)
 
 int
 isalpha(charstring)
-       char *          charstring
+       unsigned char * charstring
     CODE:
-       char *s;
-       RETVAL = 1;
-       for (s = charstring; *s && RETVAL; s++)
+       unsigned char *s = charstring;
+       unsigned char *e = s + na;      /* "na" set by typemap side effect */
+       for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isalpha(*s))
                RETVAL = 0;
     OUTPUT:
@@ -2472,11 +2820,11 @@ isalpha(charstring)
 
 int
 iscntrl(charstring)
-       char *          charstring
+       unsigned char * charstring
     CODE:
-       char *s;
-       RETVAL = 1;
-       for (s = charstring; *s && RETVAL; s++)
+       unsigned char *s = charstring;
+       unsigned char *e = s + na;      /* "na" set by typemap side effect */
+       for (RETVAL = 1; RETVAL && s < e; s++)
            if (!iscntrl(*s))
                RETVAL = 0;
     OUTPUT:
@@ -2484,11 +2832,11 @@ iscntrl(charstring)
 
 int
 isdigit(charstring)
-       char *          charstring
+       unsigned char * charstring
     CODE:
-       char *s;
-       RETVAL = 1;
-       for (s = charstring; *s && RETVAL; s++)
+       unsigned char *s = charstring;
+       unsigned char *e = s + na;      /* "na" set by typemap side effect */
+       for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isdigit(*s))
                RETVAL = 0;
     OUTPUT:
@@ -2496,11 +2844,11 @@ isdigit(charstring)
 
 int
 isgraph(charstring)
-       char *          charstring
+       unsigned char * charstring
     CODE:
-       char *s;
-       RETVAL = 1;
-       for (s = charstring; *s && RETVAL; s++)
+       unsigned char *s = charstring;
+       unsigned char *e = s + na;      /* "na" set by typemap side effect */
+       for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isgraph(*s))
                RETVAL = 0;
     OUTPUT:
@@ -2508,11 +2856,11 @@ isgraph(charstring)
 
 int
 islower(charstring)
-       char *          charstring
+       unsigned char * charstring
     CODE:
-       char *s;
-       RETVAL = 1;
-       for (s = charstring; *s && RETVAL; s++)
+       unsigned char *s = charstring;
+       unsigned char *e = s + na;      /* "na" set by typemap side effect */
+       for (RETVAL = 1; RETVAL && s < e; s++)
            if (!islower(*s))
                RETVAL = 0;
     OUTPUT:
@@ -2520,11 +2868,11 @@ islower(charstring)
 
 int
 isprint(charstring)
-       char *          charstring
+       unsigned char * charstring
     CODE:
-       char *s;
-       RETVAL = 1;
-       for (s = charstring; *s && RETVAL; s++)
+       unsigned char *s = charstring;
+       unsigned char *e = s + na;      /* "na" set by typemap side effect */
+       for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isprint(*s))
                RETVAL = 0;
     OUTPUT:
@@ -2532,11 +2880,11 @@ isprint(charstring)
 
 int
 ispunct(charstring)
-       char *          charstring
+       unsigned char * charstring
     CODE:
-       char *s;
-       RETVAL = 1;
-       for (s = charstring; *s && RETVAL; s++)
+       unsigned char *s = charstring;
+       unsigned char *e = s + na;      /* "na" set by typemap side effect */
+       for (RETVAL = 1; RETVAL && s < e; s++)
            if (!ispunct(*s))
                RETVAL = 0;
     OUTPUT:
@@ -2544,11 +2892,11 @@ ispunct(charstring)
 
 int
 isspace(charstring)
-       char *          charstring
+       unsigned char * charstring
     CODE:
-       char *s;
-       RETVAL = 1;
-       for (s = charstring; *s && RETVAL; s++)
+       unsigned char *s = charstring;
+       unsigned char *e = s + na;      /* "na" set by typemap side effect */
+       for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isspace(*s))
                RETVAL = 0;
     OUTPUT:
@@ -2556,11 +2904,11 @@ isspace(charstring)
 
 int
 isupper(charstring)
-       char *          charstring
+       unsigned char * charstring
     CODE:
-       char *s;
-       RETVAL = 1;
-       for (s = charstring; *s && RETVAL; s++)
+       unsigned char *s = charstring;
+       unsigned char *e = s + na;      /* "na" set by typemap side effect */
+       for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isupper(*s))
                RETVAL = 0;
     OUTPUT:
@@ -2568,11 +2916,11 @@ isupper(charstring)
 
 int
 isxdigit(charstring)
-       char *          charstring
+       unsigned char * charstring
     CODE:
-       char *s;
-       RETVAL = 1;
-       for (s = charstring; *s && RETVAL; s++)
+       unsigned char *s = charstring;
+       unsigned char *e = s + na;      /* "na" set by typemap side effect */
+       for (RETVAL = 1; RETVAL && s < e; s++)
            if (!isxdigit(*s))
                RETVAL = 0;
     OUTPUT:
@@ -2597,6 +2945,7 @@ localeconv()
 #ifdef HAS_LOCALECONV
        struct lconv *lcbuf;
        RETVAL = newHV();
+       SET_NUMERIC_LOCAL();
        if (lcbuf = localeconv()) {
            /* the strings */
            if (lcbuf->decimal_point && *lcbuf->decimal_point)
@@ -2617,9 +2966,11 @@ localeconv()
            if (lcbuf->mon_decimal_point && *lcbuf->mon_decimal_point)
                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,
                    newSVpv(lcbuf->mon_thousands_sep, 0), 0);
+#endif                    
            if (lcbuf->mon_grouping && *lcbuf->mon_grouping)
                hv_store(RETVAL, "mon_grouping", 12,
                    newSVpv(lcbuf->mon_grouping, 0), 0);
@@ -2662,9 +3013,67 @@ localeconv()
        RETVAL
 
 char *
-setlocale(category, locale)
+setlocale(category, locale = 0)
        int             category
        char *          locale
+    CODE:
+       RETVAL = setlocale(category, locale);
+       if (RETVAL) {
+#ifdef USE_LOCALE_CTYPE
+           if (category == LC_CTYPE
+#ifdef LC_ALL
+               || category == LC_ALL
+#endif
+               )
+           {
+               char *newctype;
+#ifdef LC_ALL
+               if (category == LC_ALL)
+                   newctype = setlocale(LC_CTYPE, NULL);
+               else
+#endif
+                   newctype = RETVAL;
+               perl_new_ctype(newctype);
+           }
+#endif /* USE_LOCALE_CTYPE */
+#ifdef USE_LOCALE_COLLATE
+           if (category == LC_COLLATE
+#ifdef LC_ALL
+               || category == LC_ALL
+#endif
+               )
+           {
+               char *newcoll;
+#ifdef LC_ALL
+               if (category == LC_ALL)
+                   newcoll = setlocale(LC_COLLATE, NULL);
+               else
+#endif
+                   newcoll = RETVAL;
+               perl_new_collate(newcoll);
+           }
+#endif /* USE_LOCALE_COLLATE */
+#ifdef USE_LOCALE_NUMERIC
+           if (category == LC_NUMERIC
+#ifdef LC_ALL
+               || category == LC_ALL
+#endif
+               )
+           {
+               char *newnum;
+#ifdef LC_ALL
+               if (category == LC_ALL)
+                   newnum = setlocale(LC_NUMERIC, NULL);
+               else
+#endif
+                   newnum = RETVAL;
+               perl_new_numeric(newnum);
+           }
+#endif /* USE_LOCALE_NUMERIC */
+       }
+    OUTPUT:
+       RETVAL
+
 
 double
 acos(x)
@@ -2740,7 +3149,9 @@ sigaction(sig, action, oldaction = 0)
        POSIX::SigAction        action
        POSIX::SigAction        oldaction
     CODE:
-
+#ifdef WIN32
+       RETVAL = not_here("sigaction");
+#else
 # This code is really grody because we're trying to make the signal
 # interface look beautiful, which is hard.
 
@@ -2794,9 +3205,9 @@ sigaction(sig, action, oldaction = 0)
            if (action && oldaction)
                RETVAL = sigaction(sig, & act, & oact);
            else if (action)
-               RETVAL = sigaction(sig, & act, (struct sigaction*)0);
+               RETVAL = sigaction(sig, & act, (struct sigaction *)0);
            else if (oldaction)
-               RETVAL = sigaction(sig, (struct sigaction*)0, & oact);
+               RETVAL = sigaction(sig, (struct sigaction *)0, & oact);
            else
                RETVAL = -1;
 
@@ -2819,6 +3230,7 @@ sigaction(sig, action, oldaction = 0)
                sv_setiv(*svp, oact.sa_flags);
            }
        }
+#endif
     OUTPUT:
        RETVAL
 
@@ -2868,28 +3280,26 @@ pipe()
     PPCODE:
        int fds[2];
        if (pipe(fds) != -1) {
-           EXTEND(sp,2);
+           EXTEND(SP,2);
            PUSHs(sv_2mortal(newSViv(fds[0])));
            PUSHs(sv_2mortal(newSViv(fds[1])));
        }
 
 SysRet
 read(fd, buffer, nbytes)
-       int             fd
-       char *          buffer = sv_grow(ST(1),SvIV(ST(2))+1);
-       size_t          nbytes
+    PREINIT:
+        SV *sv_buffer = SvROK(ST(1)) ? SvRV(ST(1)) : ST(1);
+    INPUT:
+        int             fd
+        size_t          nbytes
+        char *          buffer = sv_grow( sv_buffer, nbytes+1 );
     CLEANUP:
-       if (RETVAL >= 0) {
-           SvCUR(ST(1)) = RETVAL;
-           SvPOK_only(ST(1));
-           *SvEND(ST(1)) = '\0';
-           if (tainting)
-               sv_magic(ST(1), 0, 't', 0, 0);
-       }
-
-SysRet
-setgid(gid)
-       Gid_t           gid
+        if (RETVAL >= 0) {
+            SvCUR(sv_buffer) = RETVAL;
+            SvPOK_only(sv_buffer);
+            *SvEND(sv_buffer) = '\0';
+            SvTAINTED_on(sv_buffer);
+        }
 
 SysRet
 setpgid(pid, pgid)
@@ -2899,10 +3309,6 @@ setpgid(pid, pgid)
 pid_t
 setsid()
 
-SysRet
-setuid(uid)
-       Uid_t           uid
-
 pid_t
 tcgetpgrp(fd)
        int             fd
@@ -2918,7 +3324,7 @@ uname()
 #ifdef HAS_UNAME
        struct utsname buf;
        if (uname(&buf) >= 0) {
-           EXTEND(sp, 5);
+           EXTEND(SP, 5);
            PUSHs(sv_2mortal(newSVpv(buf.sysname, 0)));
            PUSHs(sv_2mortal(newSVpv(buf.nodename, 0)));
            PUSHs(sv_2mortal(newSVpv(buf.release, 0)));
@@ -2975,6 +3381,66 @@ strcoll(s1, s2)
        char *          s1
        char *          s2
 
+void
+strtod(str)
+       char *          str
+    PREINIT:
+       double num;
+       char *unparsed;
+    PPCODE:
+       SET_NUMERIC_LOCAL();
+       num = strtod(str, &unparsed);
+       PUSHs(sv_2mortal(newSVnv(num)));
+       if (GIMME == G_ARRAY) {
+           EXTEND(SP, 1);
+           if (unparsed)
+               PUSHs(sv_2mortal(newSViv(strlen(unparsed))));
+           else
+               PUSHs(&sv_undef);
+       }
+
+void
+strtol(str, base = 0)
+       char *          str
+       int             base
+    PREINIT:
+       long num;
+       char *unparsed;
+    PPCODE:
+       num = strtol(str, &unparsed, base);
+       if (num >= IV_MIN && num <= IV_MAX)
+           PUSHs(sv_2mortal(newSViv((IV)num)));
+       else
+           PUSHs(sv_2mortal(newSVnv((double)num)));
+       if (GIMME == G_ARRAY) {
+           EXTEND(SP, 1);
+           if (unparsed)
+               PUSHs(sv_2mortal(newSViv(strlen(unparsed))));
+           else
+               PUSHs(&sv_undef);
+       }
+
+void
+strtoul(str, base = 0)
+       char *          str
+       int             base
+    PREINIT:
+       unsigned long num;
+       char *unparsed;
+    PPCODE:
+       num = strtoul(str, &unparsed, base);
+       if (num <= IV_MAX)
+           PUSHs(sv_2mortal(newSViv((IV)num)));
+       else
+           PUSHs(sv_2mortal(newSVnv((double)num)));
+       if (GIMME == G_ARRAY) {
+           EXTEND(SP, 1);
+           if (unparsed)
+               PUSHs(sv_2mortal(newSViv(strlen(unparsed))));
+           else
+               PUSHs(&sv_undef);
+       }
+
 SV *
 strxfrm(src)
        SV *            src
@@ -3041,6 +3507,7 @@ asctime(sec, min, hour, mday, mon, year, wday = 0, yday = 0, isdst = 0)
     CODE:
        {
            struct tm mytm;
+           init_tm(&mytm);     /* XXX workaround - see init_tm() above */
            mytm.tm_sec = sec;
            mytm.tm_min = min;
            mytm.tm_hour = hour;
@@ -3062,6 +3529,19 @@ char *
 ctime(time)
        Time_t          &time
 
+void
+times()
+       PPCODE:
+       struct tms tms;
+       clock_t realtime;
+       realtime = times( &tms );
+       EXTEND(SP,5);
+       PUSHs( sv_2mortal( newSViv( (IV) realtime ) ) );
+       PUSHs( sv_2mortal( newSViv( (IV) tms.tms_utime ) ) );
+       PUSHs( sv_2mortal( newSViv( (IV) tms.tms_stime ) ) );
+       PUSHs( sv_2mortal( newSViv( (IV) tms.tms_cutime ) ) );
+       PUSHs( sv_2mortal( newSViv( (IV) tms.tms_cstime ) ) );
+
 double
 difftime(time1, time2)
        Time_t          time1
@@ -3081,6 +3561,7 @@ mktime(sec, min, hour, mday, mon, year, wday = 0, yday = 0, isdst = 0)
     CODE:
        {
            struct tm mytm;
+           init_tm(&mytm);     /* XXX workaround - see init_tm() above */
            mytm.tm_sec = sec;
            mytm.tm_min = min;
            mytm.tm_hour = hour;
@@ -3112,6 +3593,7 @@ strftime(fmt, sec, min, hour, mday, mon, year, wday = 0, yday = 0, isdst = 0)
            char tmpbuf[128];
            struct tm mytm;
            int len;
+           init_tm(&mytm);     /* XXX workaround - see init_tm() above */
            mytm.tm_sec = sec;
            mytm.tm_min = min;
            mytm.tm_hour = hour;
@@ -3131,7 +3613,7 @@ tzset()
 void
 tzname()
     PPCODE:
-       EXTEND(sp,2);
+       EXTEND(SP,2);
        PUSHs(sv_2mortal(newSVpv(tzname[0],strlen(tzname[0]))));
        PUSHs(sv_2mortal(newSVpv(tzname[1],strlen(tzname[1]))));