This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
It transpires that POSIX.xs also duplicated several constants defined
[perl5.git] / ext / POSIX / POSIX.pm
index 32010d6..9704d4f 100644 (file)
 package POSIX;
+use strict;
+use warnings;
 
-use vars qw($VERSION @ISA %EXPORT_TAGS @EXPORT_OK $AUTOLOAD); 
+our(@ISA, %EXPORT_TAGS, @EXPORT_OK, @EXPORT, $AUTOLOAD, %SIGRT) = ();
 
-use Carp;
-use AutoLoader;
-require Config;
-use Symbol;
-
-require Exporter;
-require DynaLoader;
-@ISA = qw(Exporter DynaLoader);
-
-$VERSION = "1.02" ;
-
-%EXPORT_TAGS = (
-
-    assert_h =>        [qw(assert NDEBUG)],
-
-    ctype_h => [qw(isalnum isalpha iscntrl isdigit isgraph islower
-               isprint ispunct isspace isupper isxdigit tolower toupper)],
-
-    dirent_h =>        [qw()],
-
-    errno_h => [qw(E2BIG EACCES EADDRINUSE EADDRNOTAVAIL EAFNOSUPPORT
-               EAGAIN EALREADY EBADF EBUSY ECHILD ECONNABORTED
-               ECONNREFUSED ECONNRESET EDEADLK EDESTADDRREQ EDOM EDQUOT
-               EEXIST EFAULT EFBIG EHOSTDOWN EHOSTUNREACH EINPROGRESS
-               EINTR EINVAL EIO EISCONN EISDIR ELOOP EMFILE EMLINK
-               EMSGSIZE ENAMETOOLONG ENETDOWN ENETRESET ENETUNREACH
-               ENFILE ENOBUFS ENODEV ENOENT ENOEXEC ENOLCK ENOMEM
-               ENOPROTOOPT ENOSPC ENOSYS ENOTBLK ENOTCONN ENOTDIR
-               ENOTEMPTY ENOTSOCK ENOTTY ENXIO EOPNOTSUPP EPERM
-               EPFNOSUPPORT EPIPE EPROCLIM EPROTONOSUPPORT EPROTOTYPE
-               ERANGE EREMOTE ERESTART EROFS ESHUTDOWN ESOCKTNOSUPPORT
-               ESPIPE ESRCH ESTALE ETIMEDOUT ETOOMANYREFS ETXTBSY
-               EUSERS EWOULDBLOCK EXDEV errno)],
-
-    fcntl_h => [qw(FD_CLOEXEC F_DUPFD F_GETFD F_GETFL F_GETLK F_RDLCK
-               F_SETFD F_SETFL F_SETLK F_SETLKW F_UNLCK F_WRLCK
-               O_ACCMODE O_APPEND O_CREAT O_EXCL O_NOCTTY O_NONBLOCK
-               O_RDONLY O_RDWR O_TRUNC O_WRONLY
-               creat
-               SEEK_CUR SEEK_END SEEK_SET
-               S_IRGRP S_IROTH S_IRUSR S_IRWXG S_IRWXO S_IRWXU
-               S_ISBLK S_ISCHR S_ISDIR S_ISFIFO S_ISGID S_ISREG S_ISUID
-               S_IWGRP S_IWOTH S_IWUSR)],
-
-    float_h => [qw(DBL_DIG DBL_EPSILON DBL_MANT_DIG
-               DBL_MAX DBL_MAX_10_EXP DBL_MAX_EXP
-               DBL_MIN DBL_MIN_10_EXP DBL_MIN_EXP
-               FLT_DIG FLT_EPSILON FLT_MANT_DIG
-               FLT_MAX FLT_MAX_10_EXP FLT_MAX_EXP
-               FLT_MIN FLT_MIN_10_EXP FLT_MIN_EXP
-               FLT_RADIX FLT_ROUNDS
-               LDBL_DIG LDBL_EPSILON LDBL_MANT_DIG
-               LDBL_MAX LDBL_MAX_10_EXP LDBL_MAX_EXP
-               LDBL_MIN LDBL_MIN_10_EXP LDBL_MIN_EXP)],
-
-    grp_h =>   [qw()],
-
-    limits_h =>        [qw( ARG_MAX CHAR_BIT CHAR_MAX CHAR_MIN CHILD_MAX
-               INT_MAX INT_MIN LINK_MAX LONG_MAX LONG_MIN MAX_CANON
-               MAX_INPUT MB_LEN_MAX NAME_MAX NGROUPS_MAX OPEN_MAX
-               PATH_MAX PIPE_BUF SCHAR_MAX SCHAR_MIN SHRT_MAX SHRT_MIN
-               SSIZE_MAX STREAM_MAX TZNAME_MAX UCHAR_MAX UINT_MAX
-               ULONG_MAX USHRT_MAX _POSIX_ARG_MAX _POSIX_CHILD_MAX
-               _POSIX_LINK_MAX _POSIX_MAX_CANON _POSIX_MAX_INPUT
-               _POSIX_NAME_MAX _POSIX_NGROUPS_MAX _POSIX_OPEN_MAX
-               _POSIX_PATH_MAX _POSIX_PIPE_BUF _POSIX_SSIZE_MAX
-               _POSIX_STREADM_MAX _POSIX_TZNAME_MAX)],
-
-    locale_h =>        [qw(LC_ALL LC_COLLATE LC_CTYPE LC_MONETARY LC_NUMERIC
-               LC_TIME NULL localeconv setlocale)],
-
-    math_h =>  [qw(HUGE_VAL acos asin atan ceil cosh fabs floor fmod
-               frexp ldexp log10 modf pow sinh tan tanh)],
-
-    pwd_h =>   [qw()],
-
-    setjmp_h =>        [qw(longjmp setjmp siglongjmp sigsetjmp)],
-
-    signal_h =>        [qw(SA_NOCLDSTOP SA_NOCLDWAIT SA_NODEFER SA_ONSTACK
-               SA_RESETHAND SA_RESTART SA_SIGINFO SIGABRT SIGALRM
-               SIGCHLD SIGCONT SIGFPE SIGHUP SIGILL SIGINT SIGKILL
-               SIGPIPE SIGQUIT SIGSEGV SIGSTOP SIGTERM SIGTSTP SIGTTIN
-               SIGTTOU SIGUSR1 SIGUSR2 SIG_BLOCK SIG_DFL SIG_ERR
-               SIG_IGN SIG_SETMASK SIG_UNBLOCK raise sigaction signal
-               sigpending sigprocmask sigsuspend)],
-
-    stdarg_h =>        [qw()],
-
-    stddef_h =>        [qw(NULL offsetof)],
-
-    stdio_h => [qw(BUFSIZ EOF FILENAME_MAX L_ctermid L_cuserid
-               L_tmpname NULL SEEK_CUR SEEK_END SEEK_SET
-               STREAM_MAX TMP_MAX stderr stdin stdout
-               clearerr fclose fdopen feof ferror fflush fgetc fgetpos
-               fgets fopen fprintf fputc fputs fread freopen
-               fscanf fseek fsetpos ftell fwrite getchar gets
-               perror putc putchar puts remove rewind
-               scanf setbuf setvbuf sscanf tmpfile tmpnam
-               ungetc vfprintf vprintf vsprintf)],
+our $VERSION = "1.15";
 
-    stdlib_h =>        [qw(EXIT_FAILURE EXIT_SUCCESS MB_CUR_MAX NULL RAND_MAX
-               abort atexit atof atoi atol bsearch calloc div
-               free getenv labs ldiv malloc mblen mbstowcs mbtowc
-               qsort realloc strtod strtol strtoul wcstombs wctomb)],
-
-    string_h =>        [qw(NULL memchr memcmp memcpy memmove memset strcat
-               strchr strcmp strcoll strcpy strcspn strerror strlen
-               strncat strncmp strncpy strpbrk strrchr strspn strstr
-               strtok strxfrm)],
-
-    sys_stat_h => [qw(S_IRGRP S_IROTH S_IRUSR S_IRWXG S_IRWXO S_IRWXU
-               S_ISBLK S_ISCHR S_ISDIR S_ISFIFO S_ISGID S_ISREG
-               S_ISUID S_IWGRP S_IWOTH S_IWUSR S_IXGRP S_IXOTH S_IXUSR
-               fstat mkfifo)],
-
-    sys_times_h => [qw()],
-
-    sys_types_h => [qw()],
-
-    sys_utsname_h => [qw(uname)],
-
-    sys_wait_h => [qw(WEXITSTATUS WIFEXITED WIFSIGNALED WIFSTOPPED
-               WNOHANG WSTOPSIG WTERMSIG WUNTRACED)],
-
-    termios_h => [qw( B0 B110 B1200 B134 B150 B1800 B19200 B200 B2400
-               B300 B38400 B4800 B50 B600 B75 B9600 BRKINT CLOCAL
-               CREAD CS5 CS6 CS7 CS8 CSIZE CSTOPB ECHO ECHOE ECHOK
-               ECHONL HUPCL ICANON ICRNL IEXTEN IGNBRK IGNCR IGNPAR
-               INLCR INPCK ISIG ISTRIP IXOFF IXON NCCS NOFLSH OPOST
-               PARENB PARMRK PARODD TCIFLUSH TCIOFF TCIOFLUSH TCION
-               TCOFLUSH TCOOFF TCOON TCSADRAIN TCSAFLUSH TCSANOW
-               TOSTOP VEOF VEOL VERASE VINTR VKILL VMIN VQUIT VSTART
-               VSTOP VSUSP VTIME
-               cfgetispeed cfgetospeed cfsetispeed cfsetospeed tcdrain
-               tcflow tcflush tcgetattr tcsendbreak tcsetattr )],
-
-    time_h =>  [qw(CLK_TCK CLOCKS_PER_SEC NULL asctime clock ctime
-               difftime mktime strftime tzset tzname)],
-
-    unistd_h =>        [qw(F_OK NULL R_OK SEEK_CUR SEEK_END SEEK_SET
-               STRERR_FILENO STDIN_FILENO STDOUT_FILENO W_OK X_OK
-               _PC_CHOWN_RESTRICTED _PC_LINK_MAX _PC_MAX_CANON
-               _PC_MAX_INPUT _PC_NAME_MAX _PC_NO_TRUNC _PC_PATH_MAX
-               _PC_PIPE_BUF _PC_VDISABLE _POSIX_CHOWN_RESTRICTED
-               _POSIX_JOB_CONTROL _POSIX_NO_TRUNC _POSIX_SAVED_IDS
-               _POSIX_VDISABLE _POSIX_VERSION _SC_ARG_MAX
-               _SC_CHILD_MAX _SC_CLK_TCK _SC_JOB_CONTROL
-               _SC_NGROUPS_MAX _SC_OPEN_MAX _SC_SAVED_IDS
-               _SC_STREAM_MAX _SC_TZNAME_MAX _SC_VERSION
-               _exit access ctermid cuserid
-               dup2 dup execl execle execlp execv execve execvp
-               fpathconf getcwd getegid geteuid getgid getgroups
-               getpid getuid isatty lseek pathconf pause setgid setpgid
-               setsid setuid sysconf tcgetpgrp tcsetpgrp ttyname)],
-
-    utime_h => [qw()],
-
-);
+use AutoLoader;
 
-Exporter::export_tags();
+use XSLoader ();
 
-@EXPORT_OK = qw(
-    closedir opendir readdir rewinddir
-    fcntl open
-    getgrgid getgrnam
-    atan2 cos exp log sin sqrt
-    getpwnam getpwuid
-    kill
-    fileno getc printf rename sprintf
-    abs exit rand srand system
-    chmod mkdir stat umask
-    times
-    wait waitpid
-    gmtime localtime time 
-    alarm chdir chown close fork getlogin getppid getpgrp link
-       pipe read rmdir sleep unlink write
-    utime
-    nice
-);
+use Fcntl qw(FD_CLOEXEC F_DUPFD F_GETFD F_GETFL F_GETLK F_RDLCK F_SETFD
+            F_SETFL F_SETLK F_SETLKW F_UNLCK F_WRLCK O_ACCMODE O_APPEND
+            O_CREAT O_EXCL O_NOCTTY O_NONBLOCK O_RDONLY O_RDWR O_TRUNC
+            O_WRONLY SEEK_CUR SEEK_END SEEK_SET
+            S_IRGRP S_IROTH S_IRUSR S_IRWXG S_IRWXO S_IRWXU S_ISGID S_ISUID
+            S_IWGRP S_IWOTH S_IWUSR S_IXGRP S_IXOTH S_IXUSR);
 
 # Grandfather old foo_h form to new :foo_h form
+my $loaded;
+
 sub import {
+    load_imports() unless $loaded++;
     my $this = shift;
     my @list = map { m/^\w+_h$/ ? ":$_" : $_ } @_;
     local $Exporter::ExportLevel = 1;
     Exporter::import($this,@list);
 }
 
+sub croak { require Carp;  goto &Carp::croak }
+# declare usage to assist AutoLoad
+sub usage;
 
-bootstrap POSIX $VERSION;
+XSLoader::load 'POSIX', $VERSION;
 
-my $EINVAL = constant("EINVAL", 0);
-my $EAGAIN = constant("EAGAIN", 0);
+my %NON_CONSTS = (map {($_,1)}
+                  qw(S_ISBLK S_ISCHR S_ISDIR S_ISFIFO S_ISREG WEXITSTATUS
+                     WIFEXITED WIFSIGNALED WIFSTOPPED WSTOPSIG WTERMSIG));
 
 sub AUTOLOAD {
+    no strict;
+    no warnings 'uninitialized';
     if ($AUTOLOAD =~ /::(_?[a-z])/) {
+       # require AutoLoader;
        $AutoLoader::AUTOLOAD = $AUTOLOAD;
        goto &AutoLoader::AUTOLOAD
     }
     local $! = 0;
     my $constname = $AUTOLOAD;
     $constname =~ s/.*:://;
-    my $val = constant($constname, @_ ? $_[0] : 0);
-    if ($! == 0) {
+    if ($NON_CONSTS{$constname}) {
+        my ($val, $error) = &int_macro_int($constname, $_[0]);
+        croak $error if $error;
+        *$AUTOLOAD = sub { &int_macro_int($constname, $_[0]) };
+    } else {
+        my ($error, $val) = constant($constname);
+        croak $error if $error;
        *$AUTOLOAD = sub { $val };
     }
-    elsif ($! == $EAGAIN) {    # Not really a constant, so always call.
-       *$AUTOLOAD = sub { constant($constname, $_[0]) };
-    }
-    elsif ($! == $EINVAL) {
-       croak "$constname is not a valid POSIX macro";
-    }
-    else {
-       croak "Your vendor has not defined POSIX macro $constname, used";
-    }
 
     goto &$AUTOLOAD;
 }
 
-sub usage { 
+package POSIX::SigAction;
+
+use AutoLoader 'AUTOLOAD';
+
+package POSIX::SigRt;
+
+use AutoLoader 'AUTOLOAD';
+
+use Tie::Hash;
+
+use vars qw($SIGACTION_FLAGS $_SIGRTMIN $_SIGRTMAX $_sigrtn @ISA);
+@POSIX::SigRt::ISA = qw(Tie::StdHash);
+
+$SIGACTION_FLAGS = 0;
+
+tie %POSIX::SIGRT, 'POSIX::SigRt';
+
+sub DESTROY {};
+
+package POSIX;
+
+1;
+__END__
+
+sub usage {
     my ($mess) = @_;
     croak "Usage: POSIX::$mess";
 }
 
-sub redef { 
+sub redef {
     my ($mess) = @_;
     croak "Use method $mess instead";
 }
 
-sub unimpl { 
+sub unimpl {
     my ($mess) = @_;
     $mess =~ s/xxx//;
     croak "Unimplemented: POSIX::$mess";
 }
 
-############################
-package POSIX::SigAction;
-
-sub new {
-    bless {HANDLER => $_[1], MASK => $_[2], FLAGS => $_[3] || 0}, $_[0];
-}
-
-############################
-package POSIX; # return to package POSIX so AutoSplit is happy
-1;
-__END__
-
 sub assert {
     usage "assert(expr)" if @_ != 1;
     if (!$_[0]) {
@@ -268,25 +121,25 @@ sub toupper {
 
 sub closedir {
     usage "closedir(dirhandle)" if @_ != 1;
-    closedir($_[0]);
+    CORE::closedir($_[0]);
 }
 
 sub opendir {
     usage "opendir(directory)" if @_ != 1;
-    my $dirhandle = gensym;
-    opendir($dirhandle, $_[0])
+    my $dirhandle;
+    CORE::opendir($dirhandle, $_[0])
        ? $dirhandle
        : undef;
 }
 
 sub readdir {
     usage "readdir(dirhandle)" if @_ != 1;
-    readdir($_[0]);
+    CORE::readdir($_[0]);
 }
 
 sub rewinddir {
     usage "rewinddir(dirhandle)" if @_ != 1;
-    rewinddir($_[0]);
+    CORE::rewinddir($_[0]);
 }
 
 sub errno {
@@ -301,42 +154,42 @@ sub creat {
 
 sub fcntl {
     usage "fcntl(filehandle, cmd, arg)" if @_ != 3;
-    fcntl($_[0], $_[1], $_[2]);
+    CORE::fcntl($_[0], $_[1], $_[2]);
 }
 
 sub getgrgid {
     usage "getgrgid(gid)" if @_ != 1;
-    getgrgid($_[0]);
+    CORE::getgrgid($_[0]);
 }
 
 sub getgrnam {
     usage "getgrnam(name)" if @_ != 1;
-    getgrnam($_[0]);
+    CORE::getgrnam($_[0]);
 }
 
 sub atan2 {
     usage "atan2(x,y)" if @_ != 2;
-    atan2($_[0], $_[1]);
+    CORE::atan2($_[0], $_[1]);
 }
 
 sub cos {
     usage "cos(x)" if @_ != 1;
-    cos($_[0]);
+    CORE::cos($_[0]);
 }
 
 sub exp {
     usage "exp(x)" if @_ != 1;
-    exp($_[0]);
+    CORE::exp($_[0]);
 }
 
 sub fabs {
     usage "fabs(x)" if @_ != 1;
-    abs($_[0]);
+    CORE::abs($_[0]);
 }
 
 sub log {
     usage "log(x)" if @_ != 1;
-    log($_[0]);
+    CORE::log($_[0]);
 }
 
 sub pow {
@@ -346,22 +199,22 @@ sub pow {
 
 sub sin {
     usage "sin(x)" if @_ != 1;
-    sin($_[0]);
+    CORE::sin($_[0]);
 }
 
 sub sqrt {
     usage "sqrt(x)" if @_ != 1;
-    sqrt($_[0]);
+    CORE::sqrt($_[0]);
 }
 
 sub getpwnam {
     usage "getpwnam(name)" if @_ != 1;
-    getpwnam($_[0]);
+    CORE::getpwnam($_[0]);
 }
 
 sub getpwuid {
     usage "getpwuid(uid)" if @_ != 1;
-    getpwuid($_[0]);
+    CORE::getpwuid($_[0]);
 }
 
 sub longjmp {
@@ -382,12 +235,12 @@ sub sigsetjmp {
 
 sub kill {
     usage "kill(pid, sig)" if @_ != 2;
-    kill $_[1], $_[0];
+    CORE::kill $_[1], $_[0];
 }
 
 sub raise {
     usage "raise(sig)" if @_ != 1;
-    kill $_[0], $$;    # Is this good enough?
+    CORE::kill $_[0], $$;      # Is this good enough?
 }
 
 sub offsetof {
@@ -454,6 +307,10 @@ sub fseek {
     redef "IO::Seekable::seek()";
 }
 
+sub fsync {
+    redef "IO::Handle::sync()";
+}
+
 sub ferror {
     redef "IO::Handle::error()";
 }
@@ -480,12 +337,12 @@ sub fwrite {
 
 sub getc {
     usage "getc(handle)" if @_ != 1;
-    getc($_[0]);
+    CORE::getc($_[0]);
 }
 
 sub getchar {
     usage "getchar()" if @_ != 0;
-    getc(STDIN);
+    CORE::getc(STDIN);
 }
 
 sub gets {
@@ -500,7 +357,7 @@ sub perror {
 
 sub printf {
     usage "printf(pattern, args...)" if @_ < 1;
-    printf STDOUT @_;
+    CORE::printf STDOUT @_;
 }
 
 sub putc {
@@ -517,17 +374,17 @@ sub puts {
 
 sub remove {
     usage "remove(filename)" if @_ != 1;
-    unlink($_[0]);
+    (-d $_[0]) ? CORE::rmdir($_[0]) : CORE::unlink($_[0]);
 }
 
 sub rename {
     usage "rename(oldfilename, newfilename)" if @_ != 2;
-    rename($_[0], $_[1]);
+    CORE::rename($_[0], $_[1]);
 }
 
 sub rewind {
     usage "rewind(filehandle)" if @_ != 1;
-    seek($_[0],0,0);
+    CORE::seek($_[0],0,0);
 }
 
 sub scanf {
@@ -536,7 +393,7 @@ sub scanf {
 
 sub sprintf {
     usage "sprintf(pattern,args)" if @_ == 0;
-    sprintf(shift,@_);
+    CORE::sprintf(shift,@_);
 }
 
 sub sscanf {
@@ -565,7 +422,7 @@ sub vsprintf {
 
 sub abs {
     usage "abs(x)" if @_ != 1;
-    abs($_[0]);
+    CORE::abs($_[0]);
 }
 
 sub atexit {
@@ -593,12 +450,12 @@ sub calloc {
 }
 
 sub div {
-    unimpl "div() is C-specific, stopped";
+    unimpl "div() is C-specific, use /, % and int instead";
 }
 
 sub exit {
     usage "exit(status)" if @_ != 1;
-    exit($_[0]);
+    CORE::exit($_[0]);
 }
 
 sub free {
@@ -615,7 +472,7 @@ sub labs {
 }
 
 sub ldiv {
-    unimpl "ldiv() is C-specific, use / and int instead";
+    unimpl "ldiv() is C-specific, use /, % and int instead";
 }
 
 sub malloc {
@@ -640,7 +497,7 @@ sub srand {
 
 sub system {
     usage "system(command)" if @_ != 1;
-    system($_[0]);
+    CORE::system($_[0]);
 }
 
 sub memchr {
@@ -719,7 +576,7 @@ sub strspn {
 
 sub strstr {
     usage "strstr(big, little)" if @_ != 2;
-    index($_[0], $_[1]);
+    CORE::index($_[0], $_[1]);
 }
 
 sub strtok {
@@ -728,71 +585,71 @@ sub strtok {
 
 sub chmod {
     usage "chmod(mode, filename)" if @_ != 2;
-    chmod($_[0], $_[1]);
+    CORE::chmod($_[0], $_[1]);
 }
 
 sub fstat {
     usage "fstat(fd)" if @_ != 1;
     local *TMP;
-    open(TMP, "<&$_[0]");              # Gross.
-    my @l = stat(TMP);
-    close(TMP);
+    CORE::open(TMP, "<&$_[0]");                # Gross.
+    my @l = CORE::stat(TMP);
+    CORE::close(TMP);
     @l;
 }
 
 sub mkdir {
     usage "mkdir(directoryname, mode)" if @_ != 2;
-    mkdir($_[0], $_[1]);
+    CORE::mkdir($_[0], $_[1]);
 }
 
 sub stat {
     usage "stat(filename)" if @_ != 1;
-    stat($_[0]);
+    CORE::stat($_[0]);
 }
 
 sub umask {
     usage "umask(mask)" if @_ != 1;
-    umask($_[0]);
+    CORE::umask($_[0]);
 }
 
 sub wait {
     usage "wait()" if @_ != 0;
-    wait();
+    CORE::wait();
 }
 
 sub waitpid {
     usage "waitpid(pid, options)" if @_ != 2;
-    waitpid($_[0], $_[1]);
+    CORE::waitpid($_[0], $_[1]);
 }
 
 sub gmtime {
     usage "gmtime(time)" if @_ != 1;
-    gmtime($_[0]);
+    CORE::gmtime($_[0]);
 }
 
 sub localtime {
     usage "localtime(time)" if @_ != 1;
-    localtime($_[0]);
+    CORE::localtime($_[0]);
 }
 
 sub time {
     usage "time()" if @_ != 0;
-    time;
+    CORE::time;
 }
 
 sub alarm {
     usage "alarm(seconds)" if @_ != 1;
-    alarm($_[0]);
+    CORE::alarm($_[0]);
 }
 
 sub chdir {
     usage "chdir(directory)" if @_ != 1;
-    chdir($_[0]);
+    CORE::chdir($_[0]);
 }
 
 sub chown {
-    usage "chown(filename, uid, gid)" if @_ != 3;
-    chown($_[0], $_[1], $_[2]);
+    usage "chown(uid, gid, filename)" if @_ != 3;
+    CORE::chown($_[0], $_[1], $_[2]);
 }
 
 sub execl {
@@ -821,21 +678,7 @@ sub execvp {
 
 sub fork {
     usage "fork()" if @_ != 0;
-    fork;
-}
-
-sub getcwd
-{
-    usage "getcwd()" if @_ != 0;
-    if ($^O eq 'MSWin32') {
-       # this perhaps applies to everyone else also?
-       require Cwd;
-       $cwd = &Cwd::cwd;
-    }
-    else {
-       chop($cwd = `pwd`);
-    }
-    $cwd;
+    CORE::fork;
 }
 
 sub getegid {
@@ -861,12 +704,12 @@ sub getgroups {
 
 sub getlogin {
     usage "getlogin()" if @_ != 0;
-    getlogin();
+    CORE::getlogin();
 }
 
 sub getpgrp {
     usage "getpgrp()" if @_ != 0;
-    getpgrp($_[0]);
+    CORE::getpgrp;
 }
 
 sub getpid {
@@ -876,7 +719,7 @@ sub getpid {
 
 sub getppid {
     usage "getppid()" if @_ != 0;
-    getppid;
+    CORE::getppid;
 }
 
 sub getuid {
@@ -891,36 +734,318 @@ sub isatty {
 
 sub link {
     usage "link(oldfilename, newfilename)" if @_ != 2;
-    link($_[0], $_[1]);
+    CORE::link($_[0], $_[1]);
 }
 
 sub rmdir {
     usage "rmdir(directoryname)" if @_ != 1;
-    rmdir($_[0]);
+    CORE::rmdir($_[0]);
 }
 
-sub setgid {
-    usage "setgid(gid)" if @_ != 1;
-    $( = $_[0];
+sub setbuf {
+    redef "IO::Handle::setbuf()";
 }
 
-sub setuid {
-    usage "setuid(uid)" if @_ != 1;
-    $< = $_[0];
+sub setvbuf {
+    redef "IO::Handle::setvbuf()";
 }
 
 sub sleep {
     usage "sleep(seconds)" if @_ != 1;
-    sleep($_[0]);
+    $_[0] - CORE::sleep($_[0]);
 }
 
 sub unlink {
     usage "unlink(filename)" if @_ != 1;
-    unlink($_[0]);
+    CORE::unlink($_[0]);
 }
 
 sub utime {
     usage "utime(filename, atime, mtime)" if @_ != 3;
-    utime($_[1], $_[2], $_[0]);
+    CORE::utime($_[1], $_[2], $_[0]);
 }
 
+sub load_imports {
+%EXPORT_TAGS = (
+
+    assert_h =>        [qw(assert NDEBUG)],
+
+    ctype_h => [qw(isalnum isalpha iscntrl isdigit isgraph islower
+               isprint ispunct isspace isupper isxdigit tolower toupper)],
+
+    dirent_h =>        [],
+
+    errno_h => [qw(E2BIG EACCES EADDRINUSE EADDRNOTAVAIL EAFNOSUPPORT
+               EAGAIN EALREADY EBADF EBUSY ECHILD ECONNABORTED
+               ECONNREFUSED ECONNRESET EDEADLK EDESTADDRREQ EDOM EDQUOT
+               EEXIST EFAULT EFBIG EHOSTDOWN EHOSTUNREACH EINPROGRESS
+               EINTR EINVAL EIO EISCONN EISDIR ELOOP EMFILE EMLINK
+               EMSGSIZE ENAMETOOLONG ENETDOWN ENETRESET ENETUNREACH
+               ENFILE ENOBUFS ENODEV ENOENT ENOEXEC ENOLCK ENOMEM
+               ENOPROTOOPT ENOSPC ENOSYS ENOTBLK ENOTCONN ENOTDIR
+               ENOTEMPTY ENOTSOCK ENOTTY ENXIO EOPNOTSUPP EPERM
+               EPFNOSUPPORT EPIPE EPROCLIM EPROTONOSUPPORT EPROTOTYPE
+               ERANGE EREMOTE ERESTART EROFS ESHUTDOWN ESOCKTNOSUPPORT
+               ESPIPE ESRCH ESTALE ETIMEDOUT ETOOMANYREFS ETXTBSY
+               EUSERS EWOULDBLOCK EXDEV errno)],
+
+    fcntl_h => [qw(FD_CLOEXEC F_DUPFD F_GETFD F_GETFL F_GETLK F_RDLCK
+               F_SETFD F_SETFL F_SETLK F_SETLKW F_UNLCK F_WRLCK
+               O_ACCMODE O_APPEND O_CREAT O_EXCL O_NOCTTY O_NONBLOCK
+               O_RDONLY O_RDWR O_TRUNC O_WRONLY
+               creat
+               SEEK_CUR SEEK_END SEEK_SET
+               S_IRGRP S_IROTH S_IRUSR S_IRWXG S_IRWXO S_IRWXU
+               S_ISBLK S_ISCHR S_ISDIR S_ISFIFO S_ISGID S_ISREG S_ISUID
+               S_IWGRP S_IWOTH S_IWUSR)],
+
+    float_h => [qw(DBL_DIG DBL_EPSILON DBL_MANT_DIG
+               DBL_MAX DBL_MAX_10_EXP DBL_MAX_EXP
+               DBL_MIN DBL_MIN_10_EXP DBL_MIN_EXP
+               FLT_DIG FLT_EPSILON FLT_MANT_DIG
+               FLT_MAX FLT_MAX_10_EXP FLT_MAX_EXP
+               FLT_MIN FLT_MIN_10_EXP FLT_MIN_EXP
+               FLT_RADIX FLT_ROUNDS
+               LDBL_DIG LDBL_EPSILON LDBL_MANT_DIG
+               LDBL_MAX LDBL_MAX_10_EXP LDBL_MAX_EXP
+               LDBL_MIN LDBL_MIN_10_EXP LDBL_MIN_EXP)],
+
+    grp_h =>   [],
+
+    limits_h =>        [qw( ARG_MAX CHAR_BIT CHAR_MAX CHAR_MIN CHILD_MAX
+               INT_MAX INT_MIN LINK_MAX LONG_MAX LONG_MIN MAX_CANON
+               MAX_INPUT MB_LEN_MAX NAME_MAX NGROUPS_MAX OPEN_MAX
+               PATH_MAX PIPE_BUF SCHAR_MAX SCHAR_MIN SHRT_MAX SHRT_MIN
+               SSIZE_MAX STREAM_MAX TZNAME_MAX UCHAR_MAX UINT_MAX
+               ULONG_MAX USHRT_MAX _POSIX_ARG_MAX _POSIX_CHILD_MAX
+               _POSIX_LINK_MAX _POSIX_MAX_CANON _POSIX_MAX_INPUT
+               _POSIX_NAME_MAX _POSIX_NGROUPS_MAX _POSIX_OPEN_MAX
+               _POSIX_PATH_MAX _POSIX_PIPE_BUF _POSIX_SSIZE_MAX
+               _POSIX_STREAM_MAX _POSIX_TZNAME_MAX)],
+
+    locale_h =>        [qw(LC_ALL LC_COLLATE LC_CTYPE LC_MESSAGES
+                   LC_MONETARY LC_NUMERIC LC_TIME NULL
+                   localeconv setlocale)],
+
+    math_h =>  [qw(HUGE_VAL acos asin atan ceil cosh fabs floor fmod
+               frexp ldexp log10 modf pow sinh tan tanh)],
+
+    pwd_h =>   [],
+
+    setjmp_h =>        [qw(longjmp setjmp siglongjmp sigsetjmp)],
+
+    signal_h =>        [qw(SA_NOCLDSTOP SA_NOCLDWAIT SA_NODEFER SA_ONSTACK
+               SA_RESETHAND SA_RESTART SA_SIGINFO SIGABRT SIGALRM
+               SIGCHLD SIGCONT SIGFPE SIGHUP SIGILL SIGINT SIGKILL
+               SIGPIPE %SIGRT SIGRTMIN SIGRTMAX SIGQUIT SIGSEGV SIGSTOP
+               SIGTERM SIGTSTP SIGTTIN SIGTTOU SIGUSR1 SIGUSR2
+               SIG_BLOCK SIG_DFL SIG_ERR SIG_IGN SIG_SETMASK SIG_UNBLOCK
+               raise sigaction signal sigpending sigprocmask sigsuspend)],
+
+    stdarg_h =>        [],
+
+    stddef_h =>        [qw(NULL offsetof)],
+
+    stdio_h => [qw(BUFSIZ EOF FILENAME_MAX L_ctermid L_cuserid
+               L_tmpname NULL SEEK_CUR SEEK_END SEEK_SET
+               STREAM_MAX TMP_MAX stderr stdin stdout
+               clearerr fclose fdopen feof ferror fflush fgetc fgetpos
+               fgets fopen fprintf fputc fputs fread freopen
+               fscanf fseek fsetpos ftell fwrite getchar gets
+               perror putc putchar puts remove rewind
+               scanf setbuf setvbuf sscanf tmpfile tmpnam
+               ungetc vfprintf vprintf vsprintf)],
+
+    stdlib_h =>        [qw(EXIT_FAILURE EXIT_SUCCESS MB_CUR_MAX NULL RAND_MAX
+               abort atexit atof atoi atol bsearch calloc div
+               free getenv labs ldiv malloc mblen mbstowcs mbtowc
+               qsort realloc strtod strtol strtoul wcstombs wctomb)],
+
+    string_h =>        [qw(NULL memchr memcmp memcpy memmove memset strcat
+               strchr strcmp strcoll strcpy strcspn strerror strlen
+               strncat strncmp strncpy strpbrk strrchr strspn strstr
+               strtok strxfrm)],
+
+    sys_stat_h => [qw(S_IRGRP S_IROTH S_IRUSR S_IRWXG S_IRWXO S_IRWXU
+               S_ISBLK S_ISCHR S_ISDIR S_ISFIFO S_ISGID S_ISREG
+               S_ISUID S_IWGRP S_IWOTH S_IWUSR S_IXGRP S_IXOTH S_IXUSR
+               fstat mkfifo)],
+
+    sys_times_h => [],
+
+    sys_types_h => [],
+
+    sys_utsname_h => [qw(uname)],
+
+    sys_wait_h => [qw(WEXITSTATUS WIFEXITED WIFSIGNALED WIFSTOPPED
+               WNOHANG WSTOPSIG WTERMSIG WUNTRACED)],
+
+    termios_h => [qw( B0 B110 B1200 B134 B150 B1800 B19200 B200 B2400
+               B300 B38400 B4800 B50 B600 B75 B9600 BRKINT CLOCAL
+               CREAD CS5 CS6 CS7 CS8 CSIZE CSTOPB ECHO ECHOE ECHOK
+               ECHONL HUPCL ICANON ICRNL IEXTEN IGNBRK IGNCR IGNPAR
+               INLCR INPCK ISIG ISTRIP IXOFF IXON NCCS NOFLSH OPOST
+               PARENB PARMRK PARODD TCIFLUSH TCIOFF TCIOFLUSH TCION
+               TCOFLUSH TCOOFF TCOON TCSADRAIN TCSAFLUSH TCSANOW
+               TOSTOP VEOF VEOL VERASE VINTR VKILL VMIN VQUIT VSTART
+               VSTOP VSUSP VTIME
+               cfgetispeed cfgetospeed cfsetispeed cfsetospeed tcdrain
+               tcflow tcflush tcgetattr tcsendbreak tcsetattr )],
+
+    time_h =>  [qw(CLK_TCK CLOCKS_PER_SEC NULL asctime clock ctime
+               difftime mktime strftime tzset tzname)],
+
+    unistd_h =>        [qw(F_OK NULL R_OK SEEK_CUR SEEK_END SEEK_SET
+               STDERR_FILENO STDIN_FILENO STDOUT_FILENO W_OK X_OK
+               _PC_CHOWN_RESTRICTED _PC_LINK_MAX _PC_MAX_CANON
+               _PC_MAX_INPUT _PC_NAME_MAX _PC_NO_TRUNC _PC_PATH_MAX
+               _PC_PIPE_BUF _PC_VDISABLE _POSIX_CHOWN_RESTRICTED
+               _POSIX_JOB_CONTROL _POSIX_NO_TRUNC _POSIX_SAVED_IDS
+               _POSIX_VDISABLE _POSIX_VERSION _SC_ARG_MAX
+               _SC_CHILD_MAX _SC_CLK_TCK _SC_JOB_CONTROL
+               _SC_NGROUPS_MAX _SC_OPEN_MAX _SC_PAGESIZE _SC_SAVED_IDS
+               _SC_STREAM_MAX _SC_TZNAME_MAX _SC_VERSION
+               _exit access ctermid cuserid
+               dup2 dup execl execle execlp execv execve execvp
+               fpathconf fsync getcwd getegid geteuid getgid getgroups
+               getpid getuid isatty lseek pathconf pause setgid setpgid
+               setsid setuid sysconf tcgetpgrp tcsetpgrp ttyname)],
+
+    utime_h => [],
+
+);
+
+# Exporter::export_tags();
+{
+  # De-duplicate the export list: 
+  my %export;
+  @export{map {@$_} values %EXPORT_TAGS} = ();
+  # Doing the de-dup with a temporary hash has the advantage that the SVs in
+  # @EXPORT are actually shared hash key sacalars, which will save some memory.
+  push @EXPORT, keys %export;
+}
+
+@EXPORT_OK = qw(
+               abs
+               alarm
+               atan2
+               chdir
+               chmod
+               chown
+               close
+               closedir
+               cos
+               exit
+               exp
+               fcntl
+               fileno
+               fork
+               getc
+               getgrgid
+               getgrnam
+               getlogin
+               getpgrp
+               getppid
+               getpwnam
+               getpwuid
+               gmtime
+               isatty
+               kill
+               lchown
+               link
+               localtime
+               log
+               mkdir
+               nice
+               open
+               opendir
+               pipe
+               printf
+               rand
+               read
+               readdir
+               rename
+               rewinddir
+               rmdir
+               sin
+               sleep
+               sprintf
+               sqrt
+               srand
+               stat
+               system
+               time
+               times
+               umask
+               unlink
+               utime
+               wait
+               waitpid
+               write
+);
+
+require Exporter;
+}
+
+package POSIX::SigAction;
+
+sub new { bless {HANDLER => $_[1], MASK => $_[2], FLAGS => $_[3] || 0, SAFE => 0}, $_[0] }
+sub handler { $_[0]->{HANDLER} = $_[1] if @_ > 1; $_[0]->{HANDLER} };
+sub mask    { $_[0]->{MASK}    = $_[1] if @_ > 1; $_[0]->{MASK} };
+sub flags   { $_[0]->{FLAGS}   = $_[1] if @_ > 1; $_[0]->{FLAGS} };
+sub safe    { $_[0]->{SAFE}    = $_[1] if @_ > 1; $_[0]->{SAFE} };
+
+package POSIX::SigRt;
+
+
+sub _init {
+    $_SIGRTMIN = &POSIX::SIGRTMIN;
+    $_SIGRTMAX = &POSIX::SIGRTMAX;
+    $_sigrtn   = $_SIGRTMAX - $_SIGRTMIN;
+}
+
+sub _croak {
+    &_init unless defined $_sigrtn;
+    die "POSIX::SigRt not available" unless defined $_sigrtn && $_sigrtn > 0;
+}
+
+sub _getsig {
+    &_croak;
+    my $rtsig = $_[0];
+    # Allow (SIGRT)?MIN( + n)?, a common idiom when doing these things in C.
+    $rtsig = $_SIGRTMIN + ($1 || 0)
+       if $rtsig =~ /^(?:(?:SIG)?RT)?MIN(\s*\+\s*(\d+))?$/;
+    return $rtsig;
+}
+
+sub _exist {
+    my $rtsig = _getsig($_[1]);
+    my $ok    = $rtsig >= $_SIGRTMIN && $rtsig <= $_SIGRTMAX;
+    ($rtsig, $ok);
+}
+
+sub _check {
+    my ($rtsig, $ok) = &_exist;
+    die "No POSIX::SigRt signal $_[1] (valid range SIGRTMIN..SIGRTMAX, or $_SIGRTMIN..$_SIGRTMAX)"
+       unless $ok;
+    return $rtsig;
+}
+
+sub new {
+    my ($rtsig, $handler, $flags) = @_;
+    my $sigset = POSIX::SigSet->new($rtsig);
+    my $sigact = POSIX::SigAction->new($handler,
+                                      $sigset,
+                                      $flags);
+    POSIX::sigaction($rtsig, $sigact);
+}
+
+sub EXISTS { &_exist }
+sub FETCH  { my $rtsig = &_check;
+            my $oa = POSIX::SigAction->new();
+            POSIX::sigaction($rtsig, undef, $oa);
+            return $oa->{HANDLER} }
+sub STORE  { my $rtsig = &_check; new($rtsig, $_[2], $SIGACTION_FLAGS) }
+sub DELETE { delete $SIG{ &_check } }
+sub CLEAR  { &_exist; delete @SIG{ &POSIX::SIGRTMIN .. &POSIX::SIGRTMAX } }
+sub SCALAR { &_croak; $_sigrtn + 1 }