package POSIX;
+=head1 NAME
+
+POSIX - Perl interface to IEEE 1003.1 namespace
+
+=head1 SYNOPSIS
+
+ use POSIX;
+ use POSIX 'strftime';
+
+=head1 DESCRIPTION
+
+The POSIX module permits you to access all (or nearly all) the standard
+POSIX 1003.1 identifiers. Things which are C<#defines> in C, like EINTR
+or O_NDELAY, are automatically exported into your namespace. All
+functions are only exported if you ask for them explicitly. Most likely
+people will prefer to use the fully-qualified function names.
+
+To get a list of all the possible identifiers available to you--and
+their semantics--you should pick up a 1003.1 spec, or look in the
+F<POSIX.pm> module.
+
+=head1 EXAMPLES
+
+ printf "EINTR is %d\n", EINTR;
+
+ POSIX::setsid(0);
+
+ $fd = POSIX::open($path, O_CREAT|O_EXCL|O_WRONLY, 0644);
+ # note: that's a filedescriptor, *NOT* a filehandle
+
+=head1 NOTE
+
+The POSIX module is probably the most complex Perl module supplied with
+the standard distribution. It incorporates autoloading, namespace games,
+and dynamic loading of code that's in Perl, C, or both. It's a great
+source of wisdom.
+
+=head1 CAVEATS
+
+A few functions are not implemented because they are C specific. If you
+attempt to call these, they will print a message telling you that they
+aren't implemented, and suggest using the Perl equivalent should one
+exist. For example, trying to access the setjmp() call will elicit the
+message "setjmp() is C-specific: use eval {} instead".
+
+Furthermore, some evil vendors will claim 1003.1 compliance, but in fact
+are not so: they will not pass the PCTS (POSIX Compliance Test Suites).
+For example, one vendor may not define EDEADLK, or the semantics of the
+errno values set by open(2) might not be quite right. Perl does not
+attempt to verify POSIX compliance. That means you can currently
+successfully say "use POSIX", and then later in your program you find
+that your vendor has been lax and there's no usable ICANON macro after
+all. This could be construed to be a bug.
+
+=cut
+
use Carp;
require Exporter;
-require AutoLoader;
+use AutoLoader;
require DynaLoader;
require Config;
@ISA = qw(Exporter DynaLoader);
LC_TIME NULL localeconv setlocale)],
math_h => [qw(HUGE_VAL acos asin atan ceil cosh fabs floor fmod
- frexp ldexp log10 modf pow sinh tanh)],
+ frexp ldexp log10 modf pow sinh tan tanh)],
pwd_h => [qw()],
closedir opendir readdir rewinddir
fcntl open
getgrgid getgrnam
- atan2 cos exp log sin sqrt tan
+ atan2 cos exp log sin sqrt
getpwnam getpwuid
kill
fileno getc printf rename sprintf
Exporter::import($this,@list);
}
+
+bootstrap POSIX;
+
+my $EINVAL = constant("EINVAL", 0);
+my $EAGAIN = constant("EAGAIN", 0);
+
sub AUTOLOAD {
if ($AUTOLOAD =~ /::(_?[a-z])/) {
$AutoLoader::AUTOLOAD = $AUTOLOAD;
goto &AutoLoader::AUTOLOAD
}
- local $constname = $AUTOLOAD;
+ local $! = 0;
+ my $constname = $AUTOLOAD;
$constname =~ s/.*:://;
- $val = constant($constname, $_[0]);
- if ($! != 0) {
- if ($! =~ /Invalid/) {
- croak "$constname is not a valid POSIX macro";
- }
- else {
- croak "Your vendor has not defined POSIX macro $constname, used";
- }
+ my $val = constant($constname, $_[0]);
+ if ($! == 0) {
+ *$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";
}
- eval "sub $AUTOLOAD { $val }";
+ else {
+ croak "Your vendor has not defined POSIX macro $constname, used";
+ }
+
goto &$AUTOLOAD;
}
-
-@liblist = ();
-@liblist = split ' ', $Config::Config{"POSIX_loadlibs"}
- if defined $Config::Config{"POSIX_loadlibs"};
-bootstrap POSIX @liblist;
-
sub usage {
local ($mess) = @_;
croak "Usage: POSIX::$mess";
croak "Unimplemented: POSIX::$mess";
}
-$gensym = "SYM000";
-
sub gensym {
- *{"POSIX::" . $gensym++};
+ my $pkg = @_ ? ref($_[0]) || $_[0] : "";
+ local *{$pkg . "::GLOB" . ++$seq};
+ \delete ${$pkg . "::"}{'GLOB' . $seq};
}
sub ungensym {
- local($x) = shift;
- $x =~ s/.*:://;
- delete $POSIX::{$x};
}
############################
sub new {
POSIX::usage "FileHandle->new(filename, posixmode)" if @_ != 3;
local($class,$filename,$mode) = @_;
- local($glob) = &POSIX::gensym;
+ local($sym) = $class->POSIX::gensym;
$mode =~ s/a.*/>>/ ||
$mode =~ s/w.*/>/ ||
($mode = '<');
- open($glob, "$mode $filename") and
- bless \$glob;
+ open($sym, "$mode $filename") and
+ bless $sym => $class;
}
sub new_from_fd {
POSIX::usage "FileHandle->new_from_fd(fd,mode)" if @_ != 3;
local($class,$fd,$mode) = @_;
- local($glob) = &POSIX::gensym;
+ local($sym) = $class->POSIX::gensym;
$mode =~ s/a.*/>>/ ||
$mode =~ s/w.*/>/ ||
($mode = '<');
- open($glob, "$mode&=$fd") and
- bless \$glob;
+ open($sym, "$mode&=$fd") and
+ bless $sym => $class;
}
sub clearerr {
sub DESTROY {
close($_[0]);
- ungensym($_[0]);
}
sub eof {
sub closedir {
usage "closedir(dirhandle)" if @_ != 1;
closedir($_[0]);
- ungensym($_[0]);
}
sub opendir {
usage "opendir(directory)" if @_ != 1;
- local($dirhandle) = &gensym;
+ local($dirhandle) = POSIX->gensym;
opendir($dirhandle, $_[0])
? $dirhandle
- : (ungensym($dirhandle), undef);
+ : undef;
}
sub readdir {
sqrt($_[0]);
}
-sub tan {
- usage "tan(x)" if @_ != 1;
- tan($_[0]);
-}
-
sub getpwnam {
usage "getpwnam(name)" if @_ != 1;
getpwnam($_[0]);
}
sub chmod {
- usage "chmod(filename, mode)" if @_ != 2;
+ usage "chmod(mode, filename)" if @_ != 2;
chmod($_[0], $_[1]);
}