In POSIX, drastically simplify the wrappers for "unimplemented" functions.
[perl.git] / ext / POSIX / lib / POSIX.pm
1 package POSIX;
2 use strict;
3 use warnings;
4
5 our(@ISA, %EXPORT_TAGS, @EXPORT_OK, @EXPORT, $AUTOLOAD, %SIGRT) = ();
6
7 our $VERSION = '1.25';
8
9 use AutoLoader;
10
11 require XSLoader;
12
13 use Fcntl qw(FD_CLOEXEC F_DUPFD F_GETFD F_GETFL F_GETLK F_RDLCK F_SETFD
14              F_SETFL F_SETLK F_SETLKW F_UNLCK F_WRLCK O_ACCMODE O_APPEND
15              O_CREAT O_EXCL O_NOCTTY O_NONBLOCK O_RDONLY O_RDWR O_TRUNC
16              O_WRONLY SEEK_CUR SEEK_END SEEK_SET
17              S_ISBLK S_ISCHR S_ISDIR S_ISFIFO S_ISREG
18              S_IRGRP S_IROTH S_IRUSR S_IRWXG S_IRWXO S_IRWXU S_ISGID S_ISUID
19              S_IWGRP S_IWOTH S_IWUSR S_IXGRP S_IXOTH S_IXUSR);
20
21 my $loaded;
22
23 sub import {
24     my $pkg = shift;
25
26     load_imports() unless $loaded++;
27
28     # Grandfather old foo_h form to new :foo_h form
29     s/^(?=\w+_h$)/:/ for my @list = @_;
30
31     local $Exporter::ExportLevel = 1;
32     Exporter::import($pkg,@list);
33 }
34
35 sub croak { require Carp;  goto &Carp::croak }
36 # declare usage to assist AutoLoad
37 sub usage;
38
39 XSLoader::load();
40
41 my %replacement = (
42     atexit      => 'END {}',
43     atof        => undef,
44     atoi        => undef,
45     atol        => undef,
46     bsearch     => \'not supplied',
47     calloc      => undef,
48     clearerr    => 'IO::Handle::clearerr',
49     div         => '/, % and int',
50     execl       => undef,
51     execle      => undef,
52     execlp      => undef,
53     execv       => undef,
54     execve      => undef,
55     execvp      => undef,
56     fclose      => 'IO::Handle::close',
57     fdopen      => 'IO::Handle::new_from_fd',
58     feof        => 'IO::Handle::eof',
59     ferror      => 'IO::Handle::error',
60     fflush      => 'IO::Handle::flush',
61     fgetc       => 'IO::Handle::getc',
62     fgetpos     => 'IO::Seekable::getpos',
63     fgets       => 'IO::Handle::gets',
64     fileno      => 'IO::Handle::fileno',
65     fopen       => 'IO::File::open',
66     fprintf     => 'printf',
67     fputc       => 'print',
68     fputs       => 'print',
69     fread       => 'read',
70     free        => undef,
71     freopen     => 'open',
72     fscanf      => '<> and regular expressions',
73     fseek       => 'IO::Seekable::seek',
74     fsetpos     => 'IO::Seekable::setpos',
75     fsync       => 'IO::Handle::sync',
76     ftell       => 'IO::Seekable::tell',
77     fwrite      => 'print',
78     labs        => 'abs',
79     ldiv        => '/, % and int',
80     longjmp     => 'die',
81     malloc      => undef,
82     memchr      => 'index()',
83     memcmp      => 'eq',
84     memcpy      => '=',
85     memmove     => '=',
86     memset      => 'x',
87     offsetof    => undef,
88     putc        => 'print',
89     putchar     => 'print',
90     puts        => 'print',
91     qsort       => 'sort',
92     rand        => \'non-portable, use Perl\'s rand instead',
93     realloc     => undef,
94     scanf       => '<> and regular expressions',
95     setbuf      => 'IO::Handle::setbuf',
96     setjmp      => 'eval {}',
97     setvbuf     => 'IO::Handle::setvbuf',
98     siglongjmp  => 'die',
99     sigsetjmp   => 'eval {}',
100     srand       => \'not supplied, refer to Perl\'s srand documentation',
101     sscanf      => 'regular expressions',
102     strcat      => '.=',
103     strchr      => 'index()',
104     strcmp      => 'eq',
105     strcpy      => '=',
106     strcspn     => 'regular expressions',
107     strlen      => 'length',
108     strncat     => '.=',
109     strncmp     => 'eq',
110     strncpy     => '=',
111     strpbrk     => undef,
112     strrchr     => 'rindex()',
113     strspn      => undef,
114     strtok      => undef,
115     tmpfile     => 'IO::File::new_tmpfile',
116     ungetc      => 'IO::Handle::ungetc',
117     vfprintf    => undef,
118     vprintf     => undef,
119     vsprintf    => undef,
120 );
121
122 eval "sub $_;" for keys %replacement;
123
124 sub AUTOLOAD {
125     no warnings 'uninitialized';
126
127     my ($func) = ($AUTOLOAD =~ /.*::(.*)/);
128
129     if (exists $replacement{$func}) {
130         my $how = $replacement{$func};
131         croak "Unimplemented: POSIX::$func() is C-specific, stopped"
132             unless defined $how;
133         croak "Unimplemented: POSIX::$func() is $$how" if ref $how;
134         croak "Use method $how() instead" if $how =~ /::/;
135         croak "Unimplemented: POSIX::$func() is C-specific, use $how instead";
136     }
137
138     if ($func =~ /^_?[a-z]/) {
139         $AutoLoader::AUTOLOAD = $AUTOLOAD;
140         goto &AutoLoader::AUTOLOAD
141     }
142
143     constant($func);
144 }
145
146 package POSIX::SigAction;
147
148 use AutoLoader 'AUTOLOAD';
149
150 package POSIX::SigRt;
151
152 use AutoLoader 'AUTOLOAD';
153
154 use Tie::Hash;
155
156 our @ISA = qw(Tie::StdHash);
157
158 our ($_SIGRTMIN, $_SIGRTMAX, $_sigrtn);
159
160 our $SIGACTION_FLAGS = 0;
161
162 tie %POSIX::SIGRT, 'POSIX::SigRt';
163
164 sub DESTROY {};
165
166 package POSIX;
167
168 1;
169 __END__
170
171 sub usage {
172     my ($mess) = @_;
173     croak "Usage: POSIX::$mess";
174 }
175
176 sub assert {
177     usage "assert(expr)" if @_ != 1;
178     if (!$_[0]) {
179         croak "Assertion failed";
180     }
181 }
182
183 sub tolower {
184     usage "tolower(string)" if @_ != 1;
185     lc($_[0]);
186 }
187
188 sub toupper {
189     usage "toupper(string)" if @_ != 1;
190     uc($_[0]);
191 }
192
193 sub closedir {
194     usage "closedir(dirhandle)" if @_ != 1;
195     CORE::closedir($_[0]);
196 }
197
198 sub opendir {
199     usage "opendir(directory)" if @_ != 1;
200     my $dirhandle;
201     CORE::opendir($dirhandle, $_[0])
202         ? $dirhandle
203         : undef;
204 }
205
206 sub readdir {
207     usage "readdir(dirhandle)" if @_ != 1;
208     CORE::readdir($_[0]);
209 }
210
211 sub rewinddir {
212     usage "rewinddir(dirhandle)" if @_ != 1;
213     CORE::rewinddir($_[0]);
214 }
215
216 sub errno {
217     usage "errno()" if @_ != 0;
218     $! + 0;
219 }
220
221 sub creat {
222     usage "creat(filename, mode)" if @_ != 2;
223     &open($_[0], &O_WRONLY | &O_CREAT | &O_TRUNC, $_[1]);
224 }
225
226 sub fcntl {
227     usage "fcntl(filehandle, cmd, arg)" if @_ != 3;
228     CORE::fcntl($_[0], $_[1], $_[2]);
229 }
230
231 sub getgrgid {
232     usage "getgrgid(gid)" if @_ != 1;
233     CORE::getgrgid($_[0]);
234 }
235
236 sub getgrnam {
237     usage "getgrnam(name)" if @_ != 1;
238     CORE::getgrnam($_[0]);
239 }
240
241 sub atan2 {
242     usage "atan2(x, y)" if @_ != 2;
243     CORE::atan2($_[0], $_[1]);
244 }
245
246 sub cos {
247     usage "cos(x)" if @_ != 1;
248     CORE::cos($_[0]);
249 }
250
251 sub exp {
252     usage "exp(x)" if @_ != 1;
253     CORE::exp($_[0]);
254 }
255
256 sub fabs {
257     usage "fabs(x)" if @_ != 1;
258     CORE::abs($_[0]);
259 }
260
261 sub log {
262     usage "log(x)" if @_ != 1;
263     CORE::log($_[0]);
264 }
265
266 sub pow {
267     usage "pow(x, exponent)" if @_ != 2;
268     $_[0] ** $_[1];
269 }
270
271 sub sin {
272     usage "sin(x)" if @_ != 1;
273     CORE::sin($_[0]);
274 }
275
276 sub sqrt {
277     usage "sqrt(x)" if @_ != 1;
278     CORE::sqrt($_[0]);
279 }
280
281 sub getpwnam {
282     usage "getpwnam(name)" if @_ != 1;
283     CORE::getpwnam($_[0]);
284 }
285
286 sub getpwuid {
287     usage "getpwuid(uid)" if @_ != 1;
288     CORE::getpwuid($_[0]);
289 }
290
291 sub kill {
292     usage "kill(pid, sig)" if @_ != 2;
293     CORE::kill $_[1], $_[0];
294 }
295
296 sub raise {
297     usage "raise(sig)" if @_ != 1;
298     CORE::kill $_[0], $$;       # Is this good enough?
299 }
300
301 sub getc {
302     usage "getc(handle)" if @_ != 1;
303     CORE::getc($_[0]);
304 }
305
306 sub getchar {
307     usage "getchar()" if @_ != 0;
308     CORE::getc(STDIN);
309 }
310
311 sub gets {
312     usage "gets()" if @_ != 0;
313     scalar <STDIN>;
314 }
315
316 sub perror {
317     print STDERR "@_: " if @_;
318     print STDERR $!,"\n";
319 }
320
321 sub printf {
322     usage "printf(pattern, args...)" if @_ < 1;
323     CORE::printf STDOUT @_;
324 }
325
326 sub remove {
327     usage "remove(filename)" if @_ != 1;
328     (-d $_[0]) ? CORE::rmdir($_[0]) : CORE::unlink($_[0]);
329 }
330
331 sub rename {
332     usage "rename(oldfilename, newfilename)" if @_ != 2;
333     CORE::rename($_[0], $_[1]);
334 }
335
336 sub rewind {
337     usage "rewind(filehandle)" if @_ != 1;
338     CORE::seek($_[0],0,0);
339 }
340
341 sub sprintf {
342     usage "sprintf(pattern, args...)" if @_ == 0;
343     CORE::sprintf(shift,@_);
344 }
345
346 sub abs {
347     usage "abs(x)" if @_ != 1;
348     CORE::abs($_[0]);
349 }
350
351 sub exit {
352     usage "exit(status)" if @_ != 1;
353     CORE::exit($_[0]);
354 }
355
356 sub getenv {
357     usage "getenv(name)" if @_ != 1;
358     $ENV{$_[0]};
359 }
360
361 sub system {
362     usage "system(command)" if @_ != 1;
363     CORE::system($_[0]);
364 }
365
366 sub strerror {
367     usage "strerror(errno)" if @_ != 1;
368     local $! = $_[0];
369     $! . "";
370 }
371
372 sub strstr {
373     usage "strstr(big, little)" if @_ != 2;
374     CORE::index($_[0], $_[1]);
375 }
376
377 sub chmod {
378     usage "chmod(mode, filename)" if @_ != 2;
379     CORE::chmod($_[0], $_[1]);
380 }
381
382 sub fstat {
383     usage "fstat(fd)" if @_ != 1;
384     local *TMP;
385     CORE::open(TMP, "<&$_[0]");         # Gross.
386     my @l = CORE::stat(TMP);
387     CORE::close(TMP);
388     @l;
389 }
390
391 sub mkdir {
392     usage "mkdir(directoryname, mode)" if @_ != 2;
393     CORE::mkdir($_[0], $_[1]);
394 }
395
396 sub stat {
397     usage "stat(filename)" if @_ != 1;
398     CORE::stat($_[0]);
399 }
400
401 sub umask {
402     usage "umask(mask)" if @_ != 1;
403     CORE::umask($_[0]);
404 }
405
406 sub wait {
407     usage "wait()" if @_ != 0;
408     CORE::wait();
409 }
410
411 sub waitpid {
412     usage "waitpid(pid, options)" if @_ != 2;
413     CORE::waitpid($_[0], $_[1]);
414 }
415
416 sub gmtime {
417     usage "gmtime(time)" if @_ != 1;
418     CORE::gmtime($_[0]);
419 }
420
421 sub localtime {
422     usage "localtime(time)" if @_ != 1;
423     CORE::localtime($_[0]);
424 }
425
426 sub time {
427     usage "time()" if @_ != 0;
428     CORE::time;
429 }
430
431 sub alarm {
432     usage "alarm(seconds)" if @_ != 1;
433     CORE::alarm($_[0]);
434 }
435
436 sub chdir {
437     usage "chdir(directory)" if @_ != 1;
438     CORE::chdir($_[0]);
439 }
440
441 sub chown {
442     usage "chown(uid, gid, filename)" if @_ != 3;
443     CORE::chown($_[0], $_[1], $_[2]);
444 }
445
446 sub fork {
447     usage "fork()" if @_ != 0;
448     CORE::fork;
449 }
450
451 sub getegid {
452     usage "getegid()" if @_ != 0;
453     $) + 0;
454 }
455
456 sub geteuid {
457     usage "geteuid()" if @_ != 0;
458     $> + 0;
459 }
460
461 sub getgid {
462     usage "getgid()" if @_ != 0;
463     $( + 0;
464 }
465
466 sub getgroups {
467     usage "getgroups()" if @_ != 0;
468     my %seen;
469     grep(!$seen{$_}++, split(' ', $) ));
470 }
471
472 sub getlogin {
473     usage "getlogin()" if @_ != 0;
474     CORE::getlogin();
475 }
476
477 sub getpgrp {
478     usage "getpgrp()" if @_ != 0;
479     CORE::getpgrp;
480 }
481
482 sub getpid {
483     usage "getpid()" if @_ != 0;
484     $$;
485 }
486
487 sub getppid {
488     usage "getppid()" if @_ != 0;
489     CORE::getppid;
490 }
491
492 sub getuid {
493     usage "getuid()" if @_ != 0;
494     $<;
495 }
496
497 sub isatty {
498     usage "isatty(filehandle)" if @_ != 1;
499     -t $_[0];
500 }
501
502 sub link {
503     usage "link(oldfilename, newfilename)" if @_ != 2;
504     CORE::link($_[0], $_[1]);
505 }
506
507 sub rmdir {
508     usage "rmdir(directoryname)" if @_ != 1;
509     CORE::rmdir($_[0]);
510 }
511
512 sub sleep {
513     usage "sleep(seconds)" if @_ != 1;
514     $_[0] - CORE::sleep($_[0]);
515 }
516
517 sub unlink {
518     usage "unlink(filename)" if @_ != 1;
519     CORE::unlink($_[0]);
520 }
521
522 sub utime {
523     usage "utime(filename, atime, mtime)" if @_ != 3;
524     CORE::utime($_[1], $_[2], $_[0]);
525 }
526
527 sub load_imports {
528 our %EXPORT_TAGS = (
529
530     assert_h => [qw(assert NDEBUG)],
531
532     ctype_h =>  [qw(isalnum isalpha iscntrl isdigit isgraph islower
533                 isprint ispunct isspace isupper isxdigit tolower toupper)],
534
535     dirent_h => [],
536
537     errno_h =>  [qw(E2BIG EACCES EADDRINUSE EADDRNOTAVAIL EAFNOSUPPORT
538                 EAGAIN EALREADY EBADF EBUSY ECHILD ECONNABORTED
539                 ECONNREFUSED ECONNRESET EDEADLK EDESTADDRREQ EDOM EDQUOT
540                 EEXIST EFAULT EFBIG EHOSTDOWN EHOSTUNREACH EINPROGRESS
541                 EINTR EINVAL EIO EISCONN EISDIR ELOOP EMFILE EMLINK
542                 EMSGSIZE ENAMETOOLONG ENETDOWN ENETRESET ENETUNREACH
543                 ENFILE ENOBUFS ENODEV ENOENT ENOEXEC ENOLCK ENOMEM
544                 ENOPROTOOPT ENOSPC ENOSYS ENOTBLK ENOTCONN ENOTDIR
545                 ENOTEMPTY ENOTSOCK ENOTTY ENXIO EOPNOTSUPP EPERM
546                 EPFNOSUPPORT EPIPE EPROCLIM EPROTONOSUPPORT EPROTOTYPE
547                 ERANGE EREMOTE ERESTART EROFS ESHUTDOWN ESOCKTNOSUPPORT
548                 ESPIPE ESRCH ESTALE ETIMEDOUT ETOOMANYREFS ETXTBSY
549                 EUSERS EWOULDBLOCK EXDEV errno)],
550
551     fcntl_h =>  [qw(FD_CLOEXEC F_DUPFD F_GETFD F_GETFL F_GETLK F_RDLCK
552                 F_SETFD F_SETFL F_SETLK F_SETLKW F_UNLCK F_WRLCK
553                 O_ACCMODE O_APPEND O_CREAT O_EXCL O_NOCTTY O_NONBLOCK
554                 O_RDONLY O_RDWR O_TRUNC O_WRONLY
555                 creat
556                 SEEK_CUR SEEK_END SEEK_SET
557                 S_IRGRP S_IROTH S_IRUSR S_IRWXG S_IRWXO S_IRWXU
558                 S_ISBLK S_ISCHR S_ISDIR S_ISFIFO S_ISGID S_ISREG S_ISUID
559                 S_IWGRP S_IWOTH S_IWUSR)],
560
561     float_h =>  [qw(DBL_DIG DBL_EPSILON DBL_MANT_DIG
562                 DBL_MAX DBL_MAX_10_EXP DBL_MAX_EXP
563                 DBL_MIN DBL_MIN_10_EXP DBL_MIN_EXP
564                 FLT_DIG FLT_EPSILON FLT_MANT_DIG
565                 FLT_MAX FLT_MAX_10_EXP FLT_MAX_EXP
566                 FLT_MIN FLT_MIN_10_EXP FLT_MIN_EXP
567                 FLT_RADIX FLT_ROUNDS
568                 LDBL_DIG LDBL_EPSILON LDBL_MANT_DIG
569                 LDBL_MAX LDBL_MAX_10_EXP LDBL_MAX_EXP
570                 LDBL_MIN LDBL_MIN_10_EXP LDBL_MIN_EXP)],
571
572     grp_h =>    [],
573
574     limits_h => [qw( ARG_MAX CHAR_BIT CHAR_MAX CHAR_MIN CHILD_MAX
575                 INT_MAX INT_MIN LINK_MAX LONG_MAX LONG_MIN MAX_CANON
576                 MAX_INPUT MB_LEN_MAX NAME_MAX NGROUPS_MAX OPEN_MAX
577                 PATH_MAX PIPE_BUF SCHAR_MAX SCHAR_MIN SHRT_MAX SHRT_MIN
578                 SSIZE_MAX STREAM_MAX TZNAME_MAX UCHAR_MAX UINT_MAX
579                 ULONG_MAX USHRT_MAX _POSIX_ARG_MAX _POSIX_CHILD_MAX
580                 _POSIX_LINK_MAX _POSIX_MAX_CANON _POSIX_MAX_INPUT
581                 _POSIX_NAME_MAX _POSIX_NGROUPS_MAX _POSIX_OPEN_MAX
582                 _POSIX_PATH_MAX _POSIX_PIPE_BUF _POSIX_SSIZE_MAX
583                 _POSIX_STREAM_MAX _POSIX_TZNAME_MAX)],
584
585     locale_h => [qw(LC_ALL LC_COLLATE LC_CTYPE LC_MESSAGES
586                     LC_MONETARY LC_NUMERIC LC_TIME NULL
587                     localeconv setlocale)],
588
589     math_h =>   [qw(HUGE_VAL acos asin atan ceil cosh fabs floor fmod
590                 frexp ldexp log10 modf pow sinh tan tanh)],
591
592     pwd_h =>    [],
593
594     setjmp_h => [qw(longjmp setjmp siglongjmp sigsetjmp)],
595
596     signal_h => [qw(SA_NOCLDSTOP SA_NOCLDWAIT SA_NODEFER SA_ONSTACK
597                 SA_RESETHAND SA_RESTART SA_SIGINFO SIGABRT SIGALRM
598                 SIGCHLD SIGCONT SIGFPE SIGHUP SIGILL SIGINT SIGKILL
599                 SIGPIPE %SIGRT SIGRTMIN SIGRTMAX SIGQUIT SIGSEGV SIGSTOP
600                 SIGTERM SIGTSTP SIGTTIN SIGTTOU SIGUSR1 SIGUSR2 SIGBUS
601                 SIGPOLL SIGPROF SIGSYS SIGTRAP SIGURG SIGVTALRM SIGXCPU SIGXFSZ
602                 SIG_BLOCK SIG_DFL SIG_ERR SIG_IGN SIG_SETMASK SIG_UNBLOCK
603                 raise sigaction signal sigpending sigprocmask sigsuspend)],
604
605     stdarg_h => [],
606
607     stddef_h => [qw(NULL offsetof)],
608
609     stdio_h =>  [qw(BUFSIZ EOF FILENAME_MAX L_ctermid L_cuserid
610                 L_tmpname NULL SEEK_CUR SEEK_END SEEK_SET
611                 STREAM_MAX TMP_MAX stderr stdin stdout
612                 clearerr fclose fdopen feof ferror fflush fgetc fgetpos
613                 fgets fopen fprintf fputc fputs fread freopen
614                 fscanf fseek fsetpos ftell fwrite getchar gets
615                 perror putc putchar puts remove rewind
616                 scanf setbuf setvbuf sscanf tmpfile tmpnam
617                 ungetc vfprintf vprintf vsprintf)],
618
619     stdlib_h => [qw(EXIT_FAILURE EXIT_SUCCESS MB_CUR_MAX NULL RAND_MAX
620                 abort atexit atof atoi atol bsearch calloc div
621                 free getenv labs ldiv malloc mblen mbstowcs mbtowc
622                 qsort realloc strtod strtol strtoul wcstombs wctomb)],
623
624     string_h => [qw(NULL memchr memcmp memcpy memmove memset strcat
625                 strchr strcmp strcoll strcpy strcspn strerror strlen
626                 strncat strncmp strncpy strpbrk strrchr strspn strstr
627                 strtok strxfrm)],
628
629     sys_stat_h => [qw(S_IRGRP S_IROTH S_IRUSR S_IRWXG S_IRWXO S_IRWXU
630                 S_ISBLK S_ISCHR S_ISDIR S_ISFIFO S_ISGID S_ISREG
631                 S_ISUID S_IWGRP S_IWOTH S_IWUSR S_IXGRP S_IXOTH S_IXUSR
632                 fstat mkfifo)],
633
634     sys_times_h => [],
635
636     sys_types_h => [],
637
638     sys_utsname_h => [qw(uname)],
639
640     sys_wait_h => [qw(WEXITSTATUS WIFEXITED WIFSIGNALED WIFSTOPPED
641                 WNOHANG WSTOPSIG WTERMSIG WUNTRACED)],
642
643     termios_h => [qw( B0 B110 B1200 B134 B150 B1800 B19200 B200 B2400
644                 B300 B38400 B4800 B50 B600 B75 B9600 BRKINT CLOCAL
645                 CREAD CS5 CS6 CS7 CS8 CSIZE CSTOPB ECHO ECHOE ECHOK
646                 ECHONL HUPCL ICANON ICRNL IEXTEN IGNBRK IGNCR IGNPAR
647                 INLCR INPCK ISIG ISTRIP IXOFF IXON NCCS NOFLSH OPOST
648                 PARENB PARMRK PARODD TCIFLUSH TCIOFF TCIOFLUSH TCION
649                 TCOFLUSH TCOOFF TCOON TCSADRAIN TCSAFLUSH TCSANOW
650                 TOSTOP VEOF VEOL VERASE VINTR VKILL VMIN VQUIT VSTART
651                 VSTOP VSUSP VTIME
652                 cfgetispeed cfgetospeed cfsetispeed cfsetospeed tcdrain
653                 tcflow tcflush tcgetattr tcsendbreak tcsetattr )],
654
655     time_h =>   [qw(CLK_TCK CLOCKS_PER_SEC NULL asctime clock ctime
656                 difftime mktime strftime tzset tzname)],
657
658     unistd_h => [qw(F_OK NULL R_OK SEEK_CUR SEEK_END SEEK_SET
659                 STDERR_FILENO STDIN_FILENO STDOUT_FILENO W_OK X_OK
660                 _PC_CHOWN_RESTRICTED _PC_LINK_MAX _PC_MAX_CANON
661                 _PC_MAX_INPUT _PC_NAME_MAX _PC_NO_TRUNC _PC_PATH_MAX
662                 _PC_PIPE_BUF _PC_VDISABLE _POSIX_CHOWN_RESTRICTED
663                 _POSIX_JOB_CONTROL _POSIX_NO_TRUNC _POSIX_SAVED_IDS
664                 _POSIX_VDISABLE _POSIX_VERSION _SC_ARG_MAX
665                 _SC_CHILD_MAX _SC_CLK_TCK _SC_JOB_CONTROL
666                 _SC_NGROUPS_MAX _SC_OPEN_MAX _SC_PAGESIZE _SC_SAVED_IDS
667                 _SC_STREAM_MAX _SC_TZNAME_MAX _SC_VERSION
668                 _exit access ctermid cuserid
669                 dup2 dup execl execle execlp execv execve execvp
670                 fpathconf fsync getcwd getegid geteuid getgid getgroups
671                 getpid getuid isatty lseek pathconf pause setgid setpgid
672                 setsid setuid sysconf tcgetpgrp tcsetpgrp ttyname)],
673
674     utime_h =>  [],
675 );
676
677 # Exporter::export_tags();
678 {
679   # De-duplicate the export list: 
680   my %export;
681   @export{map {@$_} values %EXPORT_TAGS} = ();
682   # Doing the de-dup with a temporary hash has the advantage that the SVs in
683   # @EXPORT are actually shared hash key scalars, which will save some memory.
684   our @EXPORT = keys %export;
685 }
686
687 our @EXPORT_OK = qw(
688                 abs
689                 alarm
690                 atan2
691                 chdir
692                 chmod
693                 chown
694                 close
695                 closedir
696                 cos
697                 exit
698                 exp
699                 fcntl
700                 fileno
701                 fork
702                 getc
703                 getgrgid
704                 getgrnam
705                 getlogin
706                 getpgrp
707                 getppid
708                 getpwnam
709                 getpwuid
710                 gmtime
711                 isatty
712                 kill
713                 lchown
714                 link
715                 localtime
716                 log
717                 mkdir
718                 nice
719                 open
720                 opendir
721                 pipe
722                 printf
723                 rand
724                 read
725                 readdir
726                 rename
727                 rewinddir
728                 rmdir
729                 sin
730                 sleep
731                 sprintf
732                 sqrt
733                 srand
734                 stat
735                 system
736                 time
737                 times
738                 umask
739                 unlink
740                 utime
741                 wait
742                 waitpid
743                 write
744 );
745
746 require Exporter;
747 }
748
749 package POSIX::SigAction;
750
751 sub new { bless {HANDLER => $_[1], MASK => $_[2], FLAGS => $_[3] || 0, SAFE => 0}, $_[0] }
752 sub handler { $_[0]->{HANDLER} = $_[1] if @_ > 1; $_[0]->{HANDLER} };
753 sub mask    { $_[0]->{MASK}    = $_[1] if @_ > 1; $_[0]->{MASK} };
754 sub flags   { $_[0]->{FLAGS}   = $_[1] if @_ > 1; $_[0]->{FLAGS} };
755 sub safe    { $_[0]->{SAFE}    = $_[1] if @_ > 1; $_[0]->{SAFE} };
756
757 package POSIX::SigRt;
758
759 sub _init {
760     $_SIGRTMIN = &POSIX::SIGRTMIN;
761     $_SIGRTMAX = &POSIX::SIGRTMAX;
762     $_sigrtn   = $_SIGRTMAX - $_SIGRTMIN;
763 }
764
765 sub _croak {
766     &_init unless defined $_sigrtn;
767     die "POSIX::SigRt not available" unless defined $_sigrtn && $_sigrtn > 0;
768 }
769
770 sub _getsig {
771     &_croak;
772     my $rtsig = $_[0];
773     # Allow (SIGRT)?MIN( + n)?, a common idiom when doing these things in C.
774     $rtsig = $_SIGRTMIN + ($1 || 0)
775         if $rtsig =~ /^(?:(?:SIG)?RT)?MIN(\s*\+\s*(\d+))?$/;
776     return $rtsig;
777 }
778
779 sub _exist {
780     my $rtsig = _getsig($_[1]);
781     my $ok    = $rtsig >= $_SIGRTMIN && $rtsig <= $_SIGRTMAX;
782     ($rtsig, $ok);
783 }
784
785 sub _check {
786     my ($rtsig, $ok) = &_exist;
787     die "No POSIX::SigRt signal $_[1] (valid range SIGRTMIN..SIGRTMAX, or $_SIGRTMIN..$_SIGRTMAX)"
788         unless $ok;
789     return $rtsig;
790 }
791
792 sub new {
793     my ($rtsig, $handler, $flags) = @_;
794     my $sigset = POSIX::SigSet->new($rtsig);
795     my $sigact = POSIX::SigAction->new($handler, $sigset, $flags);
796     POSIX::sigaction($rtsig, $sigact);
797 }
798
799 sub EXISTS { &_exist }
800 sub FETCH  { my $rtsig = &_check;
801              my $oa = POSIX::SigAction->new();
802              POSIX::sigaction($rtsig, undef, $oa);
803              return $oa->{HANDLER} }
804 sub STORE  { my $rtsig = &_check; new($rtsig, $_[2], $SIGACTION_FLAGS) }
805 sub DELETE { delete $SIG{ &_check } }
806 sub CLEAR  { &_exist; delete @SIG{ &POSIX::SIGRTMIN .. &POSIX::SIGRTMAX } }
807 sub SCALAR { &_croak; $_sigrtn + 1 }