summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Class/Template.pm241
-rw-r--r--lib/ExtUtils/Embed.pm10
-rw-r--r--lib/File/Path.pm2
-rw-r--r--lib/File/stat.pm111
-rw-r--r--lib/FileHandle.pm227
-rw-r--r--lib/Net/hostent.pm147
-rw-r--r--lib/Net/netent.pm165
-rw-r--r--lib/Net/protoent.pm92
-rw-r--r--lib/Net/servent.pm109
-rw-r--r--lib/Pod/Text.pm2
-rw-r--r--lib/Sys/Syslog.pm2
-rw-r--r--lib/Time/gmtime.pm87
-rw-r--r--lib/Time/localtime.pm83
-rw-r--r--lib/Time/tm.pm27
-rw-r--r--lib/User/grent.pm91
-rw-r--r--lib/User/pwent.pm101
-rw-r--r--lib/perl5db.pl117
-rw-r--r--lib/sigtrap.pm16
-rw-r--r--lib/syslog.pl2
19 files changed, 1581 insertions, 51 deletions
diff --git a/lib/Class/Template.pm b/lib/Class/Template.pm
new file mode 100644
index 0000000000..e45a5d3f17
--- /dev/null
+++ b/lib/Class/Template.pm
@@ -0,0 +1,241 @@
+package Class::Template;
+require 5.000;
+require Exporter;
+
+@ISA = qw(Exporter);
+@EXPORT = qw(members struct);
+use strict;
+
+# Template.pm --- struct/member template builder
+# 12mar95
+# Dean Roehrich
+#
+# changes/bugs fixed since 28nov94 version:
+# - podified
+# changes/bugs fixed since 21nov94 version:
+# - Fixed examples.
+# changes/bugs fixed since 02sep94 version:
+# - Moved to Class::Template.
+# changes/bugs fixed since 20feb94 version:
+# - Updated to be a more proper module.
+# - Added "use strict".
+# - Bug in build_methods, was using @var when @$var needed.
+# - Now using my() rather than local().
+#
+# Uses perl5 classes to create nested data types.
+# This is offered as one implementation of Tom Christiansen's "structs.pl"
+# idea.
+
+=head1 NAME
+
+Class::Template - struct/member template builder
+
+=head1 EXAMPLES
+
+=item * Example 1
+
+ use Class::Template;
+
+ struct( rusage => {
+ ru_utime => timeval,
+ ru_stime => timeval,
+ });
+
+ struct( timeval => [
+ tv_secs => '$',
+ tv_usecs => '$',
+ ]);
+
+ my $s = new rusage;
+
+=item * Example 2
+
+ package OBJ;
+ use Class::Template;
+
+ members OBJ {
+ 'a' => '$',
+ 'b' => '$',
+ };
+
+ members OBJ2 {
+ 'd' => '@',
+ 'c' => '$',
+ };
+
+ package OBJ2; @ISA = (OBJ);
+
+ sub new {
+ my $r = InitMembers( &OBJ::InitMembers() );
+ bless $r;
+ }
+
+=head1 NOTES
+
+Use '%' if the member should point to an anonymous hash. Use '@' if the
+member should point to an anonymous array.
+
+When using % and @ the method requires one argument for the key or index
+into the hash or array.
+
+Prefix the %, @, or $ with '*' to indicate you want to retrieve pointers to
+the values rather than the values themselves.
+
+=cut
+
+Var: {
+ $Class::Template::print = 0;
+ sub printem { $Class::Template::print++ }
+}
+
+
+sub struct {
+ my( $struct, $ref ) = @_;
+ my @methods = ();
+ my %refs = ();
+ my %arrays = ();
+ my %hashes = ();
+ my $out = '';
+
+ $out = "{\n package $struct;\n sub new {\n";
+ parse_fields( $ref, \$out, \@methods, \%refs, \%arrays, \%hashes, 0 );
+ $out .= " bless \$r;\n }\n";
+ build_methods( $ref, \$out, \@methods, \%refs, \%arrays, \%hashes );
+ $out .= "}\n1;\n";
+
+ ( $Class::Template::print ) ? print( $out ) : eval $out;
+}
+
+sub members {
+ my( $pkg, $ref ) = @_;
+ my @methods = ();
+ my %refs = ();
+ my %arrays = ();
+ my %hashes = ();
+ my $out = '';
+
+ $out = "{\n package $pkg;\n sub InitMembers {\n";
+ parse_fields( $ref, \$out, \@methods, \%refs, \%arrays, \%hashes, 1 );
+ $out .= " bless \$r;\n }\n";
+ build_methods( $ref, \$out, \@methods, \%refs, \%arrays, \%hashes );
+ $out .= "}\n1;\n";
+
+ ( $Class::Template::print ) ? print( $out ) : eval $out;
+}
+
+
+sub parse_fields {
+ my( $ref, $out, $methods, $refs, $arrays, $hashes, $member ) = @_;
+ my $type = ref $ref;
+ my @keys;
+ my $val;
+ my $cnt = 0;
+ my $idx = 0;
+ my( $cmt, $n );
+
+ if( $type eq 'HASH' ){
+ if( $member ){
+ $$out .= " my(\$r) = \@_ ? shift : {};\n";
+ }
+ else{
+ $$out .= " my(\$r) = {};\n";
+ }
+ @keys = keys %$ref;
+ foreach (@keys){
+ $val = $ref->{$_};
+ if( $val =~ /^\*(.)/ ){
+ $refs->{$_}++;
+ $val = $1;
+ }
+ if( $val eq '@' ){
+ $$out .= " \$r->{'$_'} = [];\n";
+ $arrays->{$_}++;
+ }
+ elsif( $val eq '%' ){
+ $$out .= " \$r->{'$_'} = {};\n";
+ $hashes->{$_}++;
+ }
+ elsif( $val ne '$' ){
+ $$out .= " \$r->{'$_'} = \&${val}::new();\n";
+ }
+ else{
+ $$out .= " \$r->{'$_'} = undef;\n";
+ }
+ push( @$methods, $_ );
+ }
+ }
+ elsif( $type eq 'ARRAY' ){
+ if( $member ){
+ $$out .= " my(\$r) = \@_ ? shift : [];\n";
+ }
+ else{
+ $$out .= " my(\$r) = [];\n";
+ }
+ while( $idx < @$ref ){
+ $n = $ref->[$idx];
+ push( @$methods, $n );
+ $val = $ref->[$idx+1];
+ $cmt = "# $n";
+ if( $val =~ /^\*(.)/ ){
+ $refs->{$n}++;
+ $val = $1;
+ }
+ if( $val eq '@' ){
+ $$out .= " \$r->[$cnt] = []; $cmt\n";
+ $arrays->{$n}++;
+ }
+ elsif( $val eq '%' ){
+ $$out .= " \$r->[$cnt] = {}; $cmt\n";
+ $hashes->{$n}++;
+ }
+ elsif( $val ne '$' ){
+ $$out .= " \$r->[$cnt] = \&${val}::new();\n";
+ }
+ else{
+ $$out .= " \$r->[$cnt] = undef; $cmt\n";
+ }
+ ++$cnt;
+ $idx += 2;
+ }
+ }
+}
+
+
+sub build_methods {
+ my( $ref, $out, $methods, $refs, $arrays, $hashes ) = @_;
+ my $type = ref $ref;
+ my $elem = '';
+ my $cnt = 0;
+ my( $pre, $pst, $cmt, $idx );
+
+ foreach (@$methods){
+ $pre = $pst = $cmt = $idx = '';
+ if( defined $refs->{$_} ){
+ $pre = "\\(";
+ $pst = ")";
+ $cmt = " # returns ref";
+ }
+ $$out .= " sub $_ {$cmt\n my \$r = shift;\n";
+ if( $type eq 'ARRAY' ){
+ $elem = "[$cnt]";
+ ++$cnt;
+ }
+ elsif( $type eq 'HASH' ){
+ $elem = "{'$_'}";
+ }
+ if( defined $arrays->{$_} ){
+ $$out .= " my \$i;\n";
+ $$out .= " \@_ ? (\$i = shift) : return \$r->$elem;\n";
+ $idx = "->[\$i]";
+ }
+ elsif( defined $hashes->{$_} ){
+ $$out .= " my \$i;\n";
+ $$out .= " \@_ ? (\$i = shift) : return \$r->$elem;\n";
+ $idx = "->{\$i}";
+ }
+ $$out .= " \@_ ? (\$r->$elem$idx = shift) : $pre\$r->$elem$idx$pst;\n";
+ $$out .= " }\n";
+ }
+}
+
+1;
diff --git a/lib/ExtUtils/Embed.pm b/lib/ExtUtils/Embed.pm
index c4a3c68bb0..fb2664c86f 100644
--- a/lib/ExtUtils/Embed.pm
+++ b/lib/ExtUtils/Embed.pm
@@ -1,4 +1,4 @@
-# $Id: Embed.pm,v 1.18 1996/07/02 13:48:17 dougm Exp $
+# $Id: Embed.pm,v 1.21 1996/11/29 17:26:23 dougm Exp $
require 5.002;
package ExtUtils::Embed;
@@ -17,7 +17,7 @@ use vars qw(@ISA @EXPORT $VERSION
);
use strict;
-$VERSION = sprintf("%d.%02d", q$Revision: 1.18 $ =~ /(\d+)\.(\d+)/);
+$VERSION = sprintf("%d.%02d", q$Revision: 1.21 $ =~ /(\d+)\.(\d+)/);
#for the namespace change
$Devel::embed::VERSION = "99.99";
@@ -201,7 +201,7 @@ sub ldopts {
my($extralibs, $bsloadlibs, $ldloadlibs, $ld_run_path) =
$MM->ext(join ' ',
- $MM->catdir("-L$Config{archlib}", "CORE"), " -lperl",
+ $MM->catdir("-L$Config{archlibexp}", "CORE"), " -lperl",
@potential_libs);
my $ld_or_bs = $bsloadlibs || $ldloadlibs;
@@ -419,11 +419,11 @@ conflict, the additional arguments will be part of the output.
For including perl header files this function simply prints:
- -I$Config{archlib}/CORE
+ -I$Config{archlibexp}/CORE
So, rather than having to say:
- perl -MConfig -e 'print "-I$Config{archlib}/CORE"'
+ perl -MConfig -e 'print "-I$Config{archlibexp}/CORE"'
Just say:
diff --git a/lib/File/Path.pm b/lib/File/Path.pm
index 62f3b504bb..2e35303bb3 100644
--- a/lib/File/Path.pm
+++ b/lib/File/Path.pm
@@ -156,7 +156,7 @@ sub rmtree {
print "unlink $root\n" if $verbose;
while (-e $root || -l $root) { # delete all versions under VMS
(unlink($root) && ++$count)
- or carp "Can't unlink file $root: $!";
+ or croak "Can't unlink file $root: $!";
}
}
}
diff --git a/lib/File/stat.pm b/lib/File/stat.pm
new file mode 100644
index 0000000000..581fbf3214
--- /dev/null
+++ b/lib/File/stat.pm
@@ -0,0 +1,111 @@
+package File::stat;
+use strict;
+
+BEGIN {
+ use Exporter ();
+ use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
+ @ISA = qw(Exporter);
+ @EXPORT = qw(stat lstat);
+ @EXPORT_OK = qw( $st_dev $st_ino $st_mode
+ $st_nlink $st_uid $st_gid
+ $st_rdev $st_size
+ $st_atime $st_mtime $st_ctime
+ $st_blksize $st_blocks
+ );
+ %EXPORT_TAGS = ( FIELDS => [ @EXPORT_OK, @EXPORT ] );
+}
+use vars @EXPORT_OK;
+
+use Class::Template qw(struct);
+struct 'File::stat' => [
+ map { $_ => '$' } qw{
+ dev ino mode nlink uid gid rdev size
+ atime mtime ctime blksize blocks
+ }
+];
+
+sub populate (@) {
+ return unless @_;
+ my $stob = new();
+ @$stob = (
+ $st_dev, $st_ino, $st_mode, $st_nlink, $st_uid, $st_gid, $st_rdev,
+ $st_size, $st_atime, $st_mtime, $st_ctime, $st_blksize, $st_blocks )
+ = @_;
+ return $stob;
+}
+
+sub lstat (*) { populate(CORE::lstat(shift)) }
+
+sub stat ($) {
+ my $arg = shift;
+ my $st = populate(CORE::stat $arg);
+ return $st if $st;
+ no strict 'refs';
+ require Symbol;
+ return populate(CORE::stat \*{Symbol::qualify($arg)});
+}
+
+1;
+__END__
+
+=head1 NAME
+
+File::stat.pm - by-name interface to Perl's built-in stat() functions
+
+=head1 SYNOPSIS
+
+ use File::stat;
+ $st = stat($file) or die "No $file: $!";
+ if ( ($st->mode & 0111) && $st->nlink > 1) ) {
+ print "$file is executable with lotsa links\n";
+ }
+
+ use File::stat qw(:FIELDS);
+ stat($file) or die "No $file: $!";
+ if ( ($st_mode & 0111) && $st_nlink > 1) ) {
+ print "$file is executable with lotsa links\n";
+ }
+
+=head1 DESCRIPTION
+
+This module's default exports override the core stat()
+and lstat() functions, replacing them with versions that return
+"File::stat" objects. This object has methods that
+return the similarly named structure field name from the
+stat(2) function; namely,
+dev,
+ino,
+mode,
+nlink,
+uid,
+gid,
+rdev,
+size,
+atime,
+mtime,
+ctime,
+blksize,
+and
+blocks.
+
+You may also import all the structure fields directly into your namespace
+as regular variables using the :FIELDS import tag. (Note that this still
+overrides your stat() and lstat() functions.) Access these fields as
+variables named with a preceding C<st_> in front their method names.
+Thus, C<$stat_obj-E<gt>dev()> corresponds to $st_dev if you import
+the fields.
+
+To access this functionality without the core overrides,
+pass the C<use> an empty import list, and then access
+function functions with their full qualified names.
+On the other hand, the built-ins are still available
+via the C<CORE::> pseudo-package.
+
+=head1 NOTE
+
+While this class is currently implemented using the Class::Template
+module to build a struct-like class, you shouldn't rely upon this.
+
+=head1 AUTHOR
+
+Tom Christiansen
diff --git a/lib/FileHandle.pm b/lib/FileHandle.pm
new file mode 100644
index 0000000000..b215147590
--- /dev/null
+++ b/lib/FileHandle.pm
@@ -0,0 +1,227 @@
+package FileHandle;
+
+require 5.003;
+use strict;
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
+
+$VERSION = "2.00";
+
+require IO::File;
+@ISA = qw(IO::File);
+
+@EXPORT = qw(_IOFBF _IOLBF _IONBF);
+
+@EXPORT_OK = qw(
+ pipe
+
+ autoflush
+ output_field_separator
+ output_record_separator
+ input_record_separator
+ input_line_number
+ format_page_number
+ format_lines_per_page
+ format_lines_left
+ format_name
+ format_top_name
+ format_line_break_characters
+ format_formfeed
+
+ print
+ printf
+ getline
+ getlines
+);
+
+#
+# Everything we're willing to export, we must first import.
+#
+import IO::Handle grep { !defined(&$_) } @EXPORT, @EXPORT_OK;
+
+#
+# Specialized importer for Fcntl magic.
+#
+sub import {
+ my $pkg = shift;
+ my $callpkg = caller;
+ Exporter::export $pkg, $callpkg, @_;
+
+ #
+ # If the Fcntl extension is available,
+ # export its constants.
+ #
+ eval {
+ require Fcntl;
+ Exporter::export 'Fcntl', $callpkg;
+ };
+}
+
+################################################
+# This is the only exported function we define;
+# the rest come from other classes.
+#
+
+sub pipe {
+ my $r = new IO::Handle;
+ my $w = new IO::Handle;
+ CORE::pipe($r, $w) or return undef;
+ ($r, $w);
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+FileHandle - supply object methods for filehandles
+
+=head1 SYNOPSIS
+
+ use FileHandle;
+
+ $fh = new FileHandle;
+ if ($fh->open "< file") {
+ print <$fh>;
+ $fh->close;
+ }
+
+ $fh = new FileHandle "> FOO";
+ if (defined $fh) {
+ print $fh "bar\n";
+ $fh->close;
+ }
+
+ $fh = new FileHandle "file", "r";
+ if (defined $fh) {
+ print <$fh>;
+ undef $fh; # automatically closes the file
+ }
+
+ $fh = new FileHandle "file", O_WRONLY|O_APPEND;
+ if (defined $fh) {
+ print $fh "corge\n";
+ undef $fh; # automatically closes the file
+ }
+
+ $pos = $fh->getpos;
+ $fh->setpos $pos;
+
+ $fh->setvbuf($buffer_var, _IOLBF, 1024);
+
+ ($readfh, $writefh) = FileHandle::pipe;
+
+ autoflush STDOUT 1;
+
+=head1 DESCRIPTION
+
+NOTE: This class is now a front-end to the IO::* classes.
+
+C<FileHandle::new> creates a C<FileHandle>, which is a reference to a
+newly created symbol (see the C<Symbol> package). If it receives any
+parameters, they are passed to C<FileHandle::open>; if the open fails,
+the C<FileHandle> object is destroyed. Otherwise, it is returned to
+the caller.
+
+C<FileHandle::new_from_fd> creates a C<FileHandle> like C<new> does.
+It requires two parameters, which are passed to C<FileHandle::fdopen>;
+if the fdopen fails, the C<FileHandle> object is destroyed.
+Otherwise, it is returned to the caller.
+
+C<FileHandle::open> accepts one parameter or two. With one parameter,
+it is just a front end for the built-in C<open> function. With two
+parameters, the first parameter is a filename that may include
+whitespace or other special characters, and the second parameter is
+the open mode, optionally followed by a file permission value.
+
+If C<FileHandle::open> receives a Perl mode string (">", "+<", etc.)
+or a POSIX fopen() mode string ("w", "r+", etc.), it uses the basic
+Perl C<open> operator.
+
+If C<FileHandle::open> is given a numeric mode, it passes that mode
+and the optional permissions value to the Perl C<sysopen> operator.
+For convenience, C<FileHandle::import> tries to import the O_XXX
+constants from the Fcntl module. If dynamic loading is not available,
+this may fail, but the rest of FileHandle will still work.
+
+C<FileHandle::fdopen> is like C<open> except that its first parameter
+is not a filename but rather a file handle name, a FileHandle object,
+or a file descriptor number.
+
+If the C functions fgetpos() and fsetpos() are available, then
+C<FileHandle::getpos> returns an opaque value that represents the
+current position of the FileHandle, and C<FileHandle::setpos> uses
+that value to return to a previously visited position.
+
+If the C function setvbuf() is available, then C<FileHandle::setvbuf>
+sets the buffering policy for the FileHandle. The calling sequence
+for the Perl function is the same as its C counterpart, including the
+macros C<_IOFBF>, C<_IOLBF>, and C<_IONBF>, except that the buffer
+parameter specifies a scalar variable to use as a buffer. WARNING: A
+variable used as a buffer by C<FileHandle::setvbuf> must not be
+modified in any way until the FileHandle is closed or until
+C<FileHandle::setvbuf> is called again, or memory corruption may
+result!
+
+See L<perlfunc> for complete descriptions of each of the following
+supported C<FileHandle> methods, which are just front ends for the
+corresponding built-in functions:
+
+ close
+ fileno
+ getc
+ gets
+ eof
+ clearerr
+ seek
+ tell
+
+See L<perlvar> for complete descriptions of each of the following
+supported C<FileHandle> methods:
+
+ autoflush
+ output_field_separator
+ output_record_separator
+ input_record_separator
+ input_line_number
+ format_page_number
+ format_lines_per_page
+ format_lines_left
+ format_name
+ format_top_name
+ format_line_break_characters
+ format_formfeed
+
+Furthermore, for doing normal I/O you might need these:
+
+=over
+
+=item $fh->print
+
+See L<perlfunc/print>.
+
+=item $fh->printf
+
+See L<perlfunc/printf>.
+
+=item $fh->getline
+
+This works like <$fh> described in L<perlop/"I/O Operators">
+except that it's more readable and can be safely called in an
+array context but still returns just one line.
+
+=item $fh->getlines
+
+This works like <$fh> when called in an array context to
+read all the remaining lines in a file, except that it's more readable.
+It will also croak() if accidentally called in a scalar context.
+
+=back
+
+=head1 SEE ALSO
+
+The B<IO> extension,
+L<perlfunc>,
+L<perlop/"I/O Operators">.
+
+=cut
diff --git a/lib/Net/hostent.pm b/lib/Net/hostent.pm
new file mode 100644
index 0000000000..1eeaae3393
--- /dev/null
+++ b/lib/Net/hostent.pm
@@ -0,0 +1,147 @@
+package Net::hostent;
+use strict;
+
+BEGIN {
+ use Exporter ();
+ use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
+ @ISA = qw(Exporter);
+ @EXPORT = qw(gethostbyname gethostbyaddr gethost);
+ @EXPORT_OK = qw(
+ $h_name @h_aliases
+ $h_addrtype $h_length
+ @h_addr_list $h_addr
+ );
+ %EXPORT_TAGS = ( FIELDS => [ @EXPORT_OK, @EXPORT ] );
+}
+use vars @EXPORT_OK;
+
+use Class::Template qw(struct);
+struct 'Net::hostent' => [
+ name => '$',
+ aliases => '@',
+ addrtype => '$',
+ 'length' => '$',
+ addr_list => '@',
+];
+
+sub addr { shift->addr_list->[0] }
+
+sub populate (@) {
+ return unless @_;
+ my $hob = new();
+ $h_name = $hob->[0] = $_[0];
+ @h_aliases = @{ $hob->[1] } = split ' ', $_[1];
+ $h_addrtype = $hob->[2] = $_[2];
+ $h_length = $hob->[3] = $_[3];
+ $h_addr = $_[4];
+ @h_addr_list = @{ $hob->[4] } = @_[ (4 .. $#_) ];
+ return $hob;
+}
+
+sub gethostbyname ($) { populate(CORE::gethostbyname(shift)) }
+
+sub gethostbyaddr ($;$) {
+ my ($addr, $addrtype);
+ $addr = shift;
+ require Socket unless @_;
+ $addrtype = @_ ? shift : Socket::AF_INET();
+ populate(CORE::gethostbyaddr($addr, $addrtype))
+}
+
+sub gethost($) {
+ if ($_[0] =~ /^\d+(?:\.\d+(?:\.\d+(?:\.\d+)?)?)?$/) {
+ require Socket;
+ &gethostbyaddr(Socket::inet_aton(shift));
+ } else {
+ &gethostbyname;
+ }
+}
+
+1;
+__END__
+
+=head1 NAME
+
+Net::hostent - by-name interface to Perl's built-in gethost*() functions
+
+=head1 SYNOPSIS
+
+ use Net::hostnet;
+
+=head1 DESCRIPTION
+
+This module's default exports override the core gethostbyname() and
+gethostbyaddr() functions, replacing them with versions that return
+"Net::hostent" objects. This object has methods that return the similarly
+named structure field name from the C's hostent structure from F<netdb.h>;
+namely name, aliases, addrtype, length, and addresses. The aliases and
+addresses methods return array reference, the rest scalars. The addr
+method is equivalent to the zeroth element in the addresses array
+reference.
+
+You may also import all the structure fields directly into your namespace
+as regular variables using the :FIELDS import tag. (Note that this still
+overrides your core functions.) Access these fields as variables named
+with a preceding C<h_>. Thus, C<$host_obj-E<gt>name()> corresponds to
+$h_name if you import the fields. Array references are available as
+regular array variables, so for example C<@{ $host_obj-E<gt>aliases()
+}> would be simply @h_aliases.
+
+The gethost() funtion is a simple front-end that forwards a numeric
+argument to gethostbyaddr() by way of Socket::inet_aton, and the rest
+to gethostbyname().
+
+To access this functionality without the core overrides,
+pass the C<use> an empty import list, and then access
+function functions with their full qualified names.
+On the other hand, the built-ins are still available
+via the C<CORE::> pseudo-package.
+
+=head1 EXAMPLES
+
+ use Net::hostent;
+ use Socket;
+
+ @ARGV = ('netscape.com') unless @ARGV;
+
+ for $host ( @ARGV ) {
+
+ unless ($h = gethost($host)) {
+ warn "$0: no such host: $host\n";
+ next;
+ }
+
+ printf "\n%s is %s%s\n",
+ $host,
+ lc($h->name) eq lc($host) ? "" : "*really* ",
+ $h->name;
+
+ print "\taliases are ", join(", ", @{$h->aliases}), "\n"
+ if @{$h->aliases};
+
+ if ( @{$h->addr_list} > 1 ) {
+ my $i;
+ for $addr ( @{$h->addr_list} ) {
+ printf "\taddr #%d is [%s]\n", $i++, inet_ntoa($addr);
+ }
+ } else {
+ printf "\taddress is [%s]\n", inet_ntoa($h->addr);
+ }
+
+ if ($h = gethostbyaddr($h->addr)) {
+ if (lc($h->name) ne lc($host)) {
+ printf "\tThat addr reverses to host %s!\n", $h->name;
+ $host = $h->name;
+ redo;
+ }
+ }
+ }
+
+=head1 NOTE
+
+While this class is currently implemented using the Class::Template
+module to build a struct-like class, you shouldn't rely upon this.
+
+=head1 AUTHOR
+
+Tom Christiansen
diff --git a/lib/Net/netent.pm b/lib/Net/netent.pm
new file mode 100644
index 0000000000..9f385b06d1
--- /dev/null
+++ b/lib/Net/netent.pm
@@ -0,0 +1,165 @@
+package Net::netent;
+use strict;
+
+BEGIN {
+ use Exporter ();
+ use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
+ @ISA = qw(Exporter);
+ @EXPORT = qw(getnetbyname getnetbyaddr getnet);
+ @EXPORT_OK = qw(
+ $n_name @n_aliases
+ $n_addrtype $n_net
+ );
+ %EXPORT_TAGS = ( FIELDS => [ @EXPORT_OK, @EXPORT ] );
+}
+use vars @EXPORT_OK;
+
+use Class::Template qw(struct);
+struct 'Net::netent' => [
+ name => '$',
+ aliases => '@',
+ addrtype => '$',
+ net => '$',
+];
+
+sub populate (@) {
+ return unless @_;
+ my $nob = new();
+ $n_name = $nob->[0] = $_[0];
+ @n_aliases = @{ $nob->[1] } = split ' ', $_[1];
+ $n_addrtype = $nob->[2] = $_[2];
+ $n_net = $nob->[3] = $_[3];
+ return $nob;
+}
+
+sub getnetbyname ($) { populate(CORE::getnetbyname(shift)) }
+
+sub getnetbyaddr ($;$) {
+ my ($net, $addrtype);
+ $net = shift;
+ require Socket if @_;
+ $addrtype = @_ ? shift : Socket::AF_INET();
+ populate(CORE::getnetbyaddr($net, $addrtype))
+}
+
+sub getnet($) {
+ if ($_[0] =~ /^\d+(?:\.\d+(?:\.\d+(?:\.\d+)?)?)?$/) {
+ require Socket;
+ &getnetbyaddr(Socket::inet_aton(shift));
+ } else {
+ &getnetbyname;
+ }
+}
+
+1;
+__END__
+
+=head1 NAME
+
+Net::netent - by-name interface to Perl's built-in getnet*() functions
+
+=head1 SYNOPSIS
+
+ use Net::netent qw(:FIELDS);
+ getnetbyname("loopback") or die "bad net";
+ printf "%s is %08X\n", $n_name, $n_net;
+
+ use Net::netent;
+
+ $n = getnetbyname("loopback") or die "bad net";
+ { # there's gotta be a better way, eh?
+ @bytes = unpack("C4", pack("N", $n->net));
+ shift @bytes while @bytes && $bytes[0] == 0;
+ }
+ printf "%s is %08X [%d.%d.%d.%d]\n", $n->name, $n->net, @bytes;
+
+=head1 DESCRIPTION
+
+This module's default exports override the core getnetbyname() and
+getnetbyaddr() functions, replacing them with versions that return
+"Net::netent" objects. This object has methods that return the similarly
+named structure field name from the C's netent structure from F<netdb.h>;
+namely name, aliases, addrtype, and net. The aliases
+method returns an array reference, the rest scalars.
+
+You may also import all the structure fields directly into your namespace
+as regular variables using the :FIELDS import tag. (Note that this still
+overrides your core functions.) Access these fields as variables named
+with a preceding C<n_>. Thus, C<$net_obj-E<gt>name()> corresponds to
+$n_name if you import the fields. Array references are available as
+regular array variables, so for example C<@{ $net_obj-E<gt>aliases()
+}> would be simply @n_aliases.
+
+The getnet() funtion is a simple front-end that forwards a numeric
+argument to getnetbyaddr(), and the rest
+to getnetbyname().
+
+To access this functionality without the core overrides,
+pass the C<use> an empty import list, and then access
+function functions with their full qualified names.
+On the other hand, the built-ins are still available
+via the C<CORE::> pseudo-package.
+
+=head1 EXAMPLES
+
+The getnet() functions do this in the Perl core:
+
+ sv_setiv(sv, (I32)nent->n_net);
+
+The gethost() functions do this in the Perl core:
+
+ sv_setpvn(sv, hent->h_addr, len);
+
+That means that the address comes back in binary for the
+host functions, and as a regular perl integer for the net ones.
+This seems a bug, but here's how to deal with it:
+
+ use strict;
+ use Socket;
+ use Net::netent;
+
+ @ARGV = ('loopback') unless @ARGV;
+
+ my($n, $net);
+
+ for $net ( @ARGV ) {
+
+ unless ($n = getnetbyname($net)) {
+ warn "$0: no such net: $net\n";
+ next;
+ }
+
+ printf "\n%s is %s%s\n",
+ $net,
+ lc($n->name) eq lc($net) ? "" : "*really* ",
+ $n->name;
+
+ print "\taliases are ", join(", ", @{$n->aliases}), "\n"
+ if @{$n->aliases};
+
+ # this is stupid; first, why is this not in binary?
+ # second, why am i going through these convolutions
+ # to make it looks right
+ {
+ my @a = unpack("C4", pack("N", $n->net));
+ shift @a while @a && $a[0] == 0;
+ printf "\taddr is %s [%d.%d.%d.%d]\n", $n->net, @a;
+ }
+
+ if ($n = getnetbyaddr($n->net)) {
+ if (lc($n->name) ne lc($net)) {
+ printf "\tThat addr reverses to net %s!\n", $n->name;
+ $net = $n->name;
+ redo;
+ }
+ }
+ }
+
+=head1 NOTE
+
+While this class is currently implemented using the Class::Template
+module to build a struct-like class, you shouldn't rely upon this.
+
+=head1 AUTHOR
+
+Tom Christiansen
diff --git a/lib/Net/protoent.pm b/lib/Net/protoent.pm
new file mode 100644
index 0000000000..ffd6acd587
--- /dev/null
+++ b/lib/Net/protoent.pm
@@ -0,0 +1,92 @@
+package Net::protoent;
+use strict;
+
+BEGIN {
+ use Exporter ();
+ use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
+ @ISA = qw(Exporter);
+ @EXPORT = qw(getprotobyname getprotobynumber getprotoent);
+ @EXPORT_OK = qw( $p_name @p_aliases $p_proto );
+ %EXPORT_TAGS = ( FIELDS => [ @EXPORT_OK, @EXPORT ] );
+}
+use vars @EXPORT_OK;
+
+use Class::Template qw(struct);
+struct 'Net::protoent' => [
+ name => '$',
+ aliases => '@',
+ proto => '$',
+];
+
+sub populate (@) {
+ return unless @_;
+ my $pob = new();
+ $p_name = $pob->[0] = $_[0];
+ @p_aliases = @{ $pob->[1] } = split ' ', $_[1];
+ $p_proto = $pob->[2] = $_[2];
+ return $pob;
+}
+
+sub getprotoent ( ) { populate(CORE::getprotoent()) }
+sub getprotobyname ($) { populate(CORE::getprotobyname(shift)) }
+sub getprotobynumber ($) { populate(CORE::getprotobynumber(shift)) }
+
+sub getproto ($;$) {
+ no strict 'refs';
+ return &{'getprotoby' . ($_[0]=~/^\d+$/ ? 'number' : 'name')}(@_);
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Net::protoent - by-name interface to Perl's built-in getproto*() functions
+
+=head1 SYNOPSIS
+
+ use Net::protoent;
+ $p = getprotobyname(shift || 'tcp') || die "no proto";
+ printf "proto for %s is %d, aliases are %s\n",
+ $p->name, $p->proto, "@{$p->aliases}";
+
+ use Net::protoent qw(:FIELDS);
+ getprotobyname(shift || 'tcp') || die "no proto";
+ print "proto for $p_name is $p_proto, aliases are @p_aliases\n";
+
+=head1 DESCRIPTION
+
+This module's default exports override the core getprotoent(),
+getprotobyname(), and getnetbyport() functions, replacing them with
+versions that return "Net::protoent" objects. They take default
+second arguments of "tcp". This object has methods that return the
+similarly named structure field name from the C's protoent structure
+from F<netdb.h>; namely name, aliases, and proto. The aliases method
+returns an array reference, the rest scalars.
+
+You may also import all the structure fields directly into your namespace
+as regular variables using the :FIELDS import tag. (Note that this still
+overrides your core functions.) Access these fields as variables named
+with a preceding C<p_>. Thus, C<$proto_obj-E<gt>name()> corresponds to
+$p_name if you import the fields. Array references are available as
+regular array variables, so for example C<@{ $proto_obj-E<gt>aliases()
+}> would be simply @p_aliases.
+
+The getproto() function is a simple front-end that forwards a numeric
+argument to getprotobyport(), and the rest to getprotobyname().
+
+To access this functionality without the core overrides,
+pass the C<use> an empty import list, and then access
+function functions with their full qualified names.
+On the other hand, the built-ins are still available
+via the C<CORE::> pseudo-package.
+
+=head1 NOTE
+
+While this class is currently implemented using the Class::Template
+module to build a struct-like class, you shouldn't rely upon this.
+
+=head1 AUTHOR
+
+Tom Christiansen
diff --git a/lib/Net/servent.pm b/lib/Net/servent.pm
new file mode 100644
index 0000000000..8c0fc13890
--- /dev/null
+++ b/lib/Net/servent.pm
@@ -0,0 +1,109 @@
+package Net::servent;
+use strict;
+
+BEGIN {
+ use Exporter ();
+ use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
+ @ISA = qw(Exporter);
+ @EXPORT = qw(getservbyname getservbyport getservent getserv);
+ @EXPORT_OK = qw( $s_name @s_aliases $s_port $s_proto );
+ %EXPORT_TAGS = ( FIELDS => [ @EXPORT_OK, @EXPORT ] );
+}
+use vars @EXPORT_OK;
+
+use Class::Template qw(struct);
+struct 'Net::servent' => [
+ name => '$',
+ aliases => '@',
+ port => '$',
+ proto => '$',
+];
+
+sub populate (@) {
+ return unless @_;
+ my $sob = new();
+ $s_name = $sob->[0] = $_[0];
+ @s_aliases = @{ $sob->[1] } = split ' ', $_[1];
+ $s_port = $sob->[2] = $_[2];
+ $s_proto = $sob->[3] = $_[3];
+ return $sob;
+}
+
+sub getservent ( ) { populate(CORE::getservent()) }
+sub getservbyname ($;$) { populate(CORE::getservbyname(shift,shift||'tcp')) }
+sub getservbyport ($;$) { populate(CORE::getservbyport(shift,shift||'tcp')) }
+
+sub getserv ($;$) {
+ no strict 'refs';
+ return &{'getservby' . ($_[0]=~/^\d+$/ ? 'port' : 'name')}(@_);
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Net::servent - by-name interface to Perl's built-in getserv*() functions
+
+=head1 SYNOPSIS
+
+ use Net::servent;
+ $s = getservbyname(shift || 'ftp') || die "no service";
+ printf "port for %s is %s, aliases are %s\n",
+ $s->name, $s->port, "@{$s->aliases}";
+
+ use Net::servent qw(:FIELDS);
+ getservbyname(shift || 'ftp') || die "no service";
+ print "port for $s_name is $s_port, aliases are @s_aliases\n";
+
+=head1 DESCRIPTION
+
+This module's default exports override the core getservent(),
+getservbyname(), and
+getnetbyport() functions, replacing them with versions that return
+"Net::servent" objects. They take default second arguments of "tcp". This object has methods that return the similarly
+named structure field name from the C's servent structure from F<netdb.h>;
+namely name, aliases, port, and proto. The aliases
+method returns an array reference, the rest scalars.
+
+You may also import all the structure fields directly into your namespace
+as regular variables using the :FIELDS import tag. (Note that this still
+overrides your core functions.) Access these fields as variables named
+with a preceding C<n_>. Thus, C<$serv_obj-E<gt>name()> corresponds to
+$s_name if you import the fields. Array references are available as
+regular array variables, so for example C<@{ $serv_obj-E<gt>aliases()
+}> would be simply @s_aliases.
+
+The getserv() function is a simple front-end that forwards a numeric
+argument to getservbyport(), and the rest to getservbyname().
+
+To access this functionality without the core overrides,
+pass the C<use> an empty import list, and then access
+function functions with their full qualified names.
+On the other hand, the built-ins are still available
+via the C<CORE::> pseudo-package.
+
+=head1 EXAMPLES
+
+ use Net::servent qw(:FIELDS);
+
+ while (@ARGV) {
+ my ($service, $proto) = ((split m!/!, shift), 'tcp');
+ my $valet = getserv($service, $proto);
+ unless ($valet) {
+ warn "$0: No service: $service/$proto\n"
+ next;
+ }
+ printf "service $service/$proto is port %d\n", $valet->port;
+ print "alias are @s_aliases\n" if @s_aliases;
+ }
+
+=head1 NOTE
+
+While this class is currently implemented using the Class::Template
+module to build a struct-like class, you shouldn't rely upon this.
+
+=head1 AUTHOR
+
+Tom Christiansen
diff --git a/lib/Pod/Text.pm b/lib/Pod/Text.pm
index 9998c48e24..c43172854a 100644
--- a/lib/Pod/Text.pm
+++ b/lib/Pod/Text.pm
@@ -73,8 +73,8 @@ if($termcap and !$setuptermcap) {
}
$SCREEN = ($_[0] =~ /^-(\d+)/ && (shift, $1))
- || ($ENV{TERMCAP} =~ /co#(\d+)/)[0]
|| $ENV{COLUMNS}
+ || ($ENV{TERMCAP} =~ /co#(\d+)/)[0]
|| (`stty -a 2>/dev/null` =~ /(\d+) columns/)[0]
|| 72;
diff --git a/lib/Sys/Syslog.pm b/lib/Sys/Syslog.pm
index c5241703da..ee90127340 100644
--- a/lib/Sys/Syslog.pm
+++ b/lib/Sys/Syslog.pm
@@ -194,7 +194,7 @@ sub xlate {
$name = uc $name;
$name = "LOG_$name" unless $name =~ /^LOG_/;
$name = "Sys::Syslog::$name";
- eval(&$name) || -1;
+ defined &$name ? &$name : -1;
}
sub connect {
diff --git a/lib/Time/gmtime.pm b/lib/Time/gmtime.pm
new file mode 100644
index 0000000000..35233f586a
--- /dev/null
+++ b/lib/Time/gmtime.pm
@@ -0,0 +1,87 @@
+package Time::gmtime;
+use strict;
+use Time::tm;
+
+BEGIN {
+ use Exporter ();
+ use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
+ @ISA = qw(Exporter Time::tm);
+ @EXPORT = qw(gmtime gmctime);
+ @EXPORT_OK = qw(
+ $tm_sec $tm_min $tm_hour $tm_mday
+ $tm_mon $tm_year $tm_wday $tm_yday
+ $tm_isdst
+ );
+ %EXPORT_TAGS = ( FIELDS => [ @EXPORT_OK, @EXPORT ] );
+}
+use vars @EXPORT_OK;
+
+sub populate (@) {
+ return unless @_;
+ my $tmob = Time::tm->new();
+ @$tmob = (
+ $tm_sec, $tm_min, $tm_hour, $tm_mday,
+ $tm_mon, $tm_year, $tm_wday, $tm_yday,
+ $tm_isdst )
+ = @_;
+ return $tmob;
+}
+
+sub gmtime (;$) { populate CORE::gmtime(shift||time)}
+sub gmctime (;$) { scalar CORE::gmtime(shift||time)}
+
+1;
+__END__
+
+=head1 NAME
+
+Time::gmtime.pm - by-name interface to Perl's built-in gmtime() function
+
+=head1 SYNOPSIS
+
+ use Time::gmtime;
+ $gm = gmtime();
+ printf "The day in Greenwich is %s\n",
+ (qw(Sun Mon Tue Wed Thu Fri Sat Sun))[ gm->wday() ];
+
+ use Time::gmtime w(:FIELDS;
+ printf "The day in Greenwich is %s\n",
+ (qw(Sun Mon Tue Wed Thu Fri Sat Sun))[ gm_wday() ];
+
+ $now = gmctime();
+
+ use Time::gmtime;
+ use File::stat;
+ $date_string = gmctime(stat($file)->mtime);
+
+=head1 DESCRIPTION
+
+This module's default exports override the core gmtime() function,
+replacing it with a version that returns "Time::tm" objects.
+This object has methods that return the similarly named structure field
+name from the C's tm structure from F<time.h>; namely sec, min, hour,
+mday, mon, year, wday, yday, and isdst.
+
+You may also import all the structure fields directly into your namespace
+as regular variables using the :FIELDS import tag. (Note that this
+still overrides your core functions.) Access these fields as variables
+named with a preceding C<tm_> in front their method names. Thus,
+C<$tm_obj-E<gt>mday()> corresponds to $tm_mday if you import the fields.
+
+The gmctime() funtion provides a way of getting at the
+scalar sense of the original CORE::gmtime() function.
+
+To access this functionality without the core overrides,
+pass the C<use> an empty import list, and then access
+function functions with their full qualified names.
+On the other hand, the built-ins are still available
+via the C<CORE::> pseudo-package.
+
+=head1 NOTE
+
+While this class is currently implemented using the Class::Template
+module to build a struct-like class, you shouldn't rely upon this.
+
+=head1 AUTHOR
+
+Tom Christiansen
diff --git a/lib/Time/localtime.pm b/lib/Time/localtime.pm
new file mode 100644
index 0000000000..2e811e627f
--- /dev/null
+++ b/lib/Time/localtime.pm
@@ -0,0 +1,83 @@
+package Time::localtime;
+use strict;
+use Time::tm;
+
+BEGIN {
+ use Exporter ();
+ use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
+ @ISA = qw(Exporter Time::tm);
+ @EXPORT = qw(localtime ctime);
+ @EXPORT_OK = qw(
+ $tm_sec $tm_min $tm_hour $tm_mday
+ $tm_mon $tm_year $tm_wday $tm_yday
+ $tm_isdst
+ );
+ %EXPORT_TAGS = ( FIELDS => [ @EXPORT_OK, @EXPORT ] );
+}
+use vars @EXPORT_OK;
+
+sub populate (@) {
+ return unless @_;
+ my $tmob = Time::tm->new();
+ @$tmob = (
+ $tm_sec, $tm_min, $tm_hour, $tm_mday,
+ $tm_mon, $tm_year, $tm_wday, $tm_yday,
+ $tm_isdst )
+ = @_;
+ return $tmob;
+}
+
+sub localtime (;$) { populate CORE::localtime(shift||time)}
+sub ctime (;$) { scalar CORE::localtime(shift||time) }
+
+1;
+
+__END__
+
+=head1 NAME
+
+Time::localtime.pm - by-name interface to Perl's built-in localtime() function
+
+=head1 SYNOPSIS
+
+ use Time::localtime;
+ printf "Year is %d\n", localtime->year() + 1900;
+
+ $now = ctime();
+
+ use Time::localtime;
+ use File::stat;
+ $date_string = ctime(stat($file)->mtime);
+
+=head1 DESCRIPTION
+
+This module's default exports override the core localtime() function,
+replacing it with a version that returns "Time::tm" objects.
+This object has methods that return the similarly named structure field
+name from the C's tm structure from F<time.h>; namely sec, min, hour,
+mday, mon, year, wday, yday, and isdst.
+
+You may also import all the structure fields directly into your namespace
+as regular variables using the :FIELDS import tag. (Note that this still
+overrides your core functions.) Access these fields as
+variables named with a preceding C<tm_> in front their method names.
+Thus, C<$tm_obj-E<gt>mday()> corresponds to $tm_mday if you import
+the fields.
+
+The ctime() funtion provides a way of getting at the
+scalar sense of the original CORE::localtime() function.
+
+To access this functionality without the core overrides,
+pass the C<use> an empty import list, and then access
+function functions with their full qualified names.
+On the other hand, the built-ins are still available
+via the C<CORE::> pseudo-package.
+
+=head1 NOTE
+
+While this class is currently implemented using the Class::Template
+module to build a struct-like class, you shouldn't rely upon this.
+
+=head1 AUTHOR
+
+Tom Christiansen
diff --git a/lib/Time/tm.pm b/lib/Time/tm.pm
new file mode 100644
index 0000000000..87fc883b88
--- /dev/null
+++ b/lib/Time/tm.pm
@@ -0,0 +1,27 @@
+package Time::tm;
+use strict;
+
+use Class::Template qw(struct);
+struct('Time::tm' => [
+ map { $_ => '$' } qw{ sec min hour mday mon year wday yday isdst }
+]);
+
+1;
+__END__
+
+=head1 NAME
+
+Time::tm.pm - internal object used by Time::gmtime and Time::localtime
+
+=head1 DESCRIPTION
+
+This module is used internally as a base class by Time::localtime And
+Time::gmtime functions. It creates a Time::tm struct object which is
+addressable just like's C's tm structure from F<time.h>; namely with sec,
+min, hour, mday, mon, year, wday, yday, and isdst.
+
+This class is an internal interface only.
+
+=head1 AUTHOR
+
+Tom Christiansen
diff --git a/lib/User/grent.pm b/lib/User/grent.pm
new file mode 100644
index 0000000000..1185958430
--- /dev/null
+++ b/lib/User/grent.pm
@@ -0,0 +1,91 @@
+package User::grent;
+use strict;
+
+BEGIN {
+ use Exporter ();
+ use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
+ @ISA = qw(Exporter);
+ @EXPORT = qw(getgrent getgrgid getgrnam getgr);
+ @EXPORT_OK = qw($gr_name $gr_gid $gr_passwd $gr_mem @gr_members);
+ %EXPORT_TAGS = ( FIELDS => [ @EXPORT_OK, @EXPORT ] );
+}
+use vars @EXPORT_OK;
+
+use Class::Template qw(struct);
+struct 'User::grent' => [
+ name => '$',
+ passwd => '$',
+ gid => '$',
+ members => '@',
+];
+
+sub populate (@) {
+ return unless @_;
+ my $gob = new();
+ ($gr_name, $gr_passwd, $gr_gid) = @$gob[0,1,2] = @_[0,1,2];
+ @gr_members = @{$gob->[3]} = split ' ', $_[3];
+ return $gob;
+}
+
+sub getgrent ( ) { populate(CORE::getgrent()) }
+sub getgrnam ($) { populate(CORE::getgrnam(shift)) }
+sub getgrgid ($) { populate(CORE::getgrgid(shift)) }
+sub getgr ($) { ($_[0] =~ /^\d+/) ? &getgrgid : &getgrnam }
+
+1;
+__END__
+
+=head1 NAME
+
+User::grent.pm - by-name interface to Perl's built-in getgr*() functions
+
+=head1 SYNOPSIS
+
+ use User::grent;
+ $gr = getgrgid(0) or die "No group zero";
+ if ( $gr->name eq 'wheel' && @{$gr->members} > 1 ) {
+ print "gid zero name wheel, with other members";
+ }
+
+ use User::grent qw(:FIELDS;
+ getgrgid(0) or die "No group zero";
+ if ( $gr_name eq 'wheel' && @gr_members > 1 ) {
+ print "gid zero name wheel, with other members";
+ }
+
+ $gr = getgr($whoever);
+
+=head1 DESCRIPTION
+
+This module's default exports override the core getgrent(), getgruid(),
+and getgrnam() functions, replacing them with versions that return
+"User::grent" objects. This object has methods that return the similarly
+named structure field name from the C's passwd structure from F<grp.h>;
+namely name, passwd, gid, and members (not mem). The first three
+return scalars, the last an array reference.
+
+You may also import all the structure fields directly into your namespace
+as regular variables using the :FIELDS import tag. (Note that this still
+overrides your core functions.) Access these fields as variables named
+with a preceding C<gr_>. Thus, C<$group_obj-E<gt>gid()> corresponds
+to $gr_gid if you import the fields. Array references are available as
+regular array variables, so C<@{ $group_obj-E<gt>members() }> would be
+simply @gr_members.
+
+The getpw() funtion is a simple front-end that forwards
+a numeric argument to getpwuid() and the rest to getpwnam().
+
+To access this functionality without the core overrides,
+pass the C<use> an empty import list, and then access
+function functions with their full qualified names.
+On the other hand, the built-ins are still available
+via the C<CORE::> pseudo-package.
+
+=head1 NOTE
+
+While this class is currently implemented using the Class::Template
+module to build a struct-like class, you shouldn't rely upon this.
+
+=head1 AUTHOR
+
+Tom Christiansen
diff --git a/lib/User/pwent.pm b/lib/User/pwent.pm
new file mode 100644
index 0000000000..fd4eb4f09d
--- /dev/null
+++ b/lib/User/pwent.pm
@@ -0,0 +1,101 @@
+package User::pwent;
+use strict;
+
+BEGIN {
+ use Exporter ();
+ use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
+ @ISA = qw(Exporter);
+ @EXPORT = qw(getpwent getpwuid getpwnam getpw);
+ @EXPORT_OK = qw(
+ $pw_name $pw_passwd $pw_uid
+ $pw_gid $pw_quota $pw_comment
+ $pw_gecos $pw_dir $pw_shell
+ );
+ %EXPORT_TAGS = ( FIELDS => [ @EXPORT_OK, @EXPORT ] );
+}
+use vars @EXPORT_OK;
+
+use Class::Template qw(struct);
+struct 'User::pwent' => [
+ name => '$',
+ passwd => '$',
+ uid => '$',
+ gid => '$',
+ quota => '$',
+ comment => '$',
+ gcos => '$',
+ dir => '$',
+ shell => '$',
+];
+
+sub populate (@) {
+ return unless @_;
+ my $pwob = new();
+
+ ( $pw_name, $pw_passwd, $pw_uid,
+ $pw_gid, $pw_quota, $pw_comment,
+ $pw_gecos, $pw_dir, $pw_shell, ) = @$pwob = @_;
+
+ return $pwob;
+}
+
+sub getpwent ( ) { populate(CORE::getpwent()) }
+sub getpwnam ($) { populate(CORE::getpwnam(shift)) }
+sub getpwgid ($) { populate(CORE::getpwgid(shift)) }
+sub getpw ($) { ($_[0] =~ /^\d+/) ? &getpwgid : &getpwnam }
+
+1;
+__END__
+
+=head1 NAME
+
+User::pwent.pm - by-name interface to Perl's built-in getpw*() functions
+
+=head1 SYNOPSIS
+
+ use User::pwent;
+ $pw = getpwnam('daemon') or die "No daemon user";
+ if ( $pw->uid == 1 && $pw->dir =~ m#^/(bin|tmp)?$# ) {
+ print "gid 1 on root dir";
+ }
+
+ use User::pwent qw(:FIELDS);
+ getpwnam('daemon') or die "No daemon user";
+ if ( $pw_uid == 1 && $pw_dir =~ m#^/(bin|tmp)?$# ) {
+ print "gid 1 on root dir";
+ }
+
+ $pw = getpw($whoever);
+
+=head1 DESCRIPTION
+
+This module's default exports override the core getpwent(), getpwuid(),
+and getpwnam() functions, replacing them with versions that return
+"User::pwent" objects. This object has methods that return the similarly
+named structure field name from the C's passwd structure from F<pwd.h>;
+namely name, passwd, uid, gid, quota, comment, gecos, dir, and shell.
+
+You may also import all the structure fields directly into your namespace
+as regular variables using the :FIELDS import tag. (Note that this still
+overrides your core functions.) Access these fields as
+variables named with a preceding C<pw_> in front their method names.
+Thus, C<$passwd_obj-E<gt>shell()> corresponds to $pw_shell if you import
+the fields.
+
+The getpw() funtion is a simple front-end that forwards
+a numeric argument to getpwuid() and the rest to getpwnam().
+
+To access this functionality without the core overrides,
+pass the C<use> an empty import list, and then access
+function functions with their full qualified names.
+On the other hand, the built-ins are still available
+via the C<CORE::> pseudo-package.
+
+=head1 NOTE
+
+While this class is currently implemented using the Class::Template
+module to build a struct-like class, you shouldn't rely upon this.
+
+=head1 AUTHOR
+
+Tom Christiansen
diff --git a/lib/perl5db.pl b/lib/perl5db.pl
index 7f3756fffb..fcc30c6e7c 100644
--- a/lib/perl5db.pl
+++ b/lib/perl5db.pl
@@ -17,8 +17,8 @@ $header = "perl5db.pl patch level $VERSION";
# This file is automatically included if you do perl -d.
# It's probably not useful to include this yourself.
#
-# Perl supplies the values for @line and %sub. It effectively inserts
-# a &DB'DB(<linenum>); in front of every place that can have a
+# Perl supplies the values for %sub. It effectively inserts
+# a &DB'DB(); in front of every place that can have a
# breakpoint. Instead of a subroutine call it calls &DB::sub with
# $DB::sub being the called subroutine. It also inserts a BEGIN
# {require 'perl5db.pl'} before the first line.
@@ -45,7 +45,7 @@ $header = "perl5db.pl patch level $VERSION";
# The scalar ${"_<$filename"} contains "_<$filename".
#
# Note that no subroutine call is possible until &DB::sub is defined
-# (for subroutines defined outside this file). In fact the same is
+# (for subroutines defined outside of the package DB). In fact the same is
# true if $deep is not defined.
#
# $Log: perldb.pl,v $
@@ -120,6 +120,9 @@ $header = "perl5db.pl patch level $VERSION";
# When restarting debugger breakpoints/actions persist.
# Buglet: When restarting debugger only one breakpoint/action per
# autoloaded function persists.
+# Changes: 0.97: NonStop will not stop in at_exit().
+# Option AutoTrace implemented.
+# Trace printed differently if frames are printed too.
####################################################################
@@ -140,7 +143,7 @@ warn ( # Do not ;-)
@ARGS,
$Carp::CarpLevel,
$panic,
- $first_time,
+ $second_time,
) if 0;
# Command-line + PERLLIB:
@@ -154,10 +157,10 @@ $inhibit_exit = $option{PrintRet} = 1;
@options = qw(hashDepth arrayDepth DumpDBFiles DumpPackages
compactDump veryCompact quote HighBit undefPrint
- globPrint PrintRet UsageOnly frame
+ globPrint PrintRet UsageOnly frame AutoTrace
TTY noTTY ReadLine NonStop LineInfo
recallCommand ShellBang pager tkRunning
- signalLevel warnLevel dieLevel);
+ signalLevel warnLevel dieLevel inhibit_exit);
%optionVars = (
hashDepth => \$dumpvar::hashDepth,
@@ -169,7 +172,9 @@ $inhibit_exit = $option{PrintRet} = 1;
globPrint => \$dumpvar::globPrint,
tkRunning => \$readline::Tk_toloop,
UsageOnly => \$dumpvar::usageOnly,
- frame => \$frame,
+ frame => \$frame,
+ AutoTrace => \$trace,
+ inhibit_exit => \$inhibit_exit,
);
%optionAction = (
@@ -317,15 +322,17 @@ if (defined &afterinit) { # May be defined in $rcfile
############################################################ Subroutines
sub DB {
- unless ($first_time++) { # Do when-running init
- if ($runnonstop) { # Disable until signal
+ # _After_ the perl program is compiled, $single is set to 1:
+ if ($single and not $second_time++) {
+ if ($runnonstop) { # Disable until signal
for ($i=0; $i <= $#stack; ) {
$stack[$i++] &= ~1;
}
$single = 0;
- return;
+ # return; # Would not print trace!
}
}
+ $runnonstop = 0 if $single or $signal; # Disable it if interactive.
&save;
($package, $filename, $line) = caller;
$filename_ini = $filename;
@@ -341,7 +348,9 @@ sub DB {
$dbline{$line} =~ s/;9($|\0)/$1/;
}
}
- if ($single || $trace || $signal) {
+ my $was_signal = $signal;
+ $signal = 0;
+ if ($single || $trace || $was_signal) {
$term || &setterm;
if ($emacs) {
$position = "\032\032$filename:$line:0\n";
@@ -353,25 +362,33 @@ sub DB {
$after = ($dbline[$line] =~ /\n$/ ? '' : "\n");
if (length($prefix) > 30) {
$position = "$prefix$line):\n$line:\t$dbline[$line]$after";
- print $LINEINFO $position;
$prefix = "";
$infix = ":\t";
} else {
$infix = "):\t";
$position = "$prefix$line$infix$dbline[$line]$after";
+ }
+ if ($frame) {
+ print $LINEINFO ' ' x $#stack, "$line:\t$dbline[$line]$after";
+ } else {
print $LINEINFO $position;
}
for ($i = $line + 1; $i <= $max && $dbline[$i] == 0; ++$i) { #{ vi
last if $dbline[$i] =~ /^\s*[\;\}\#\n]/;
+ last if $signal;
$after = ($dbline[$i] =~ /\n$/ ? '' : "\n");
$incr_pos = "$prefix$i$infix$dbline[$i]$after";
- print $LINEINFO $incr_pos;
$position .= $incr_pos;
+ if ($frame) {
+ print $LINEINFO ' ' x $#stack, "$i:\t$dbline[$i]$after";
+ } else {
+ print $LINEINFO $incr_pos;
+ }
}
}
}
$evalarg = $action, &eval if $action;
- if ($single || $signal) {
+ if ($single || $was_signal) {
local $level = $level + 1;
map {$evalarg = $_, &eval} @$pre;
print $OUT $#stack . " levels deep in subroutine calls!\n"
@@ -528,7 +545,7 @@ sub DB {
$arrow = ($i==$line
and $filename eq $filename_ini)
? '==>'
- : ':' ;
+ : ($dbline[$i]+0 ? ':' : ' ') ;
$arrow .= 'b' if $stop;
$arrow .= 'a' if $action;
print $OUT "$i$arrow\t", $dbline[$i];
@@ -848,7 +865,7 @@ sub DB {
print $OUT "exec failed: $!\n";
last CMD; };
$cmd =~ /^T$/ && do {
- print_trace($OUT, 3); # skip DB print_trace dump_trace
+ print_trace($OUT, 1); # skip DB
next CMD; };
$cmd =~ /^\/(.*)$/ && do {
$inpat = $1;
@@ -1030,7 +1047,11 @@ sub sub {
if ($sub =~ /::AUTOLOAD$/) {
$al = " for $ {$` . '::AUTOLOAD'}";
}
- print $LINEINFO ' ' x $#stack, "entering $sub$al\n" if $frame;
+ ($frame & 4
+ ? ( (print $LINEINFO ' ' x $#stack, "in "),
+ # Why -1? But it works! :-(
+ print_trace($LINEINFO, -1, 1, 1, "$sub$al") )
+ : print $LINEINFO ' ' x $#stack, "entering $sub$al\n") if $frame;
push(@stack, $single);
$single &= 1;
$single |= 4 if $#stack == $deep;
@@ -1039,14 +1060,20 @@ sub sub {
$single |= pop(@stack);
print ($OUT "list context return from $sub:\n"), dumpit( \@ret ),
$doret = -2 if $doret eq $#stack;
- print $LINEINFO ' ' x $#stack, "exited $sub$al\n" if $frame > 1;
+ ($frame & 4
+ ? ( (print $LINEINFO ' ' x $#stack, "out "),
+ print_trace($LINEINFO, -1, 1, 1, "$sub$al") )
+ : print $LINEINFO ' ' x $#stack, "exited $sub$al\n") if $frame & 2;
@ret;
} else {
$ret = &$sub;
$single |= pop(@stack);
print ($OUT "scalar context return from $sub: "), dumpit( $ret ),
$doret = -2 if $doret eq $#stack;
- print $LINEINFO ' ' x $#stack, "exited $sub$al\n" if $frame > 1;
+ ($frame & 4
+ ? ( (print $LINEINFO ' ' x $#stack, "out "),
+ print_trace($LINEINFO, -1, 1, 1, "$sub$al") )
+ : print $LINEINFO ' ' x $#stack, "exited $sub$al\n") if $frame & 2;
$ret;
}
}
@@ -1071,6 +1098,7 @@ sub eval {
$^D = $od;
}
my $at = $@;
+ local $saved[0]; # Preserve the old value of $@
eval "&DB::save";
if ($at) {
print $OUT $at;
@@ -1098,7 +1126,7 @@ sub postponed_sub {
}
return;
}
- print $OUT "In postponed_sub for `$subname'.\n";
+ #print $OUT "In postponed_sub for `$subname'.\n";
}
sub postponed {
@@ -1108,7 +1136,9 @@ sub postponed {
local *dbline = shift;
my $filename = $dbline;
$filename =~ s/^_<//;
- $signal = 1, print $OUT "'$filename' loaded...\n" if $break_on_load{$filename};
+ $signal = 1, print $OUT "'$filename' loaded...\n"
+ if $break_on_load{$filename};
+ print $LINEINFO ' ' x $#stack, "Package $filename.\n" if $frame;
return unless %{$postponed_file{$filename}};
$had_breakpoints{$filename}++;
#%dbline = %{$postponed_file{$filename}}; # Cannot be done: unsufficient magic
@@ -1139,28 +1169,39 @@ sub dumpit {
select ($savout);
}
+# Tied method do not create a context, so may get wrong message:
+
sub print_trace {
my $fh = shift;
- my @sub = dump_trace(@_);
+ my @sub = dump_trace($_[0] + 1, $_[1]);
+ my $short = $_[2]; # Print short report, next one for sub name
for ($i=0; $i <= $#sub; $i++) {
last if $signal;
local $" = ', ';
my $args = defined $sub[$i]{args}
? "(@{ $sub[$i]{args} })"
: '' ;
- $file = $sub[$i]{file} eq '-e' ? $sub[$i]{file} :
- "file `$sub[$i]{file}'";
- print $fh "$sub[$i]{context}$sub[$i]{sub}$args" .
- " called from $file" .
- " line $sub[$i]{line}\n";
+ my $file = $sub[$i]{file};
+ $file = $file eq '-e' ? $file : "file `$file'" unless $short;
+ if ($short) {
+ my $sub = @_ >= 4 ? $_[3] : $sub[$i]{sub};
+ print $fh "$sub[$i]{context}=$sub$args from $file:$sub[$i]{line}\n";
+ } else {
+ print $fh "$sub[$i]{context} = $sub[$i]{sub}$args" .
+ " called from $file" .
+ " line $sub[$i]{line}\n";
+ }
}
}
sub dump_trace {
my $skip = shift;
+ my $count = shift || 1e9;
+ $skip++;
+ $count += $skip;
my ($p,$file,$line,$sub,$h,$args,$e,$r,@a,@sub,$context);
for ($i = $skip;
- ($p,$file,$line,$sub,$h,$context,$e,$r) = caller($i);
+ $i < $count and ($p,$file,$line,$sub,$h,$context,$e,$r) = caller($i);
$i++) {
@a = ();
for $arg (@args) {
@@ -1172,7 +1213,7 @@ sub dump_trace {
s/([\0-\37\177])/sprintf("^%c",ord($1)^64)/eg;
push(@a, $_);
}
- $context = $context ? '@ = ' : '$ = ';
+ $context = $context ? '@' : '$';
$args = $h ? [@a] : undef;
$e =~ s/\n\s*\;\s*\Z// if $e;
$e =~ s/[\\\']/\\$1/g if $e;
@@ -1514,7 +1555,7 @@ w [line] List window around line.
f filename Switch to viewing filename.
/pattern/ Search forwards for pattern; final / is optional.
?pattern? Search backwards for pattern; final ? is optional.
-L List all breakpoints and actions for the current file.
+L List all breakpoints and actions.
S [[!]pattern] List subroutine names [not] matching pattern.
t Toggle trace mode.
t expr Trace through execution of expr.
@@ -1543,6 +1584,9 @@ O [opt[=val]] [opt\"val\"] [opt?]...
be abbreviated. Several options can be listed.
recallCommand, ShellBang: chars used to recall command or spawn shell;
pager: program for output of \"|cmd\";
+ tkRunning: run Tk while prompting (with ReadLine);
+ signalLevel warnLevel dieLevel: level of verbosity;
+ inhibit_exit Allows stepping off the end of the script.
The following options affect what happens with V, X, and x commands:
arrayDepth, hashDepth: print only first N elements ('' for all);
compactDump, veryCompact: change style of array and hash dump;
@@ -1550,10 +1594,9 @@ O [opt[=val]] [opt\"val\"] [opt?]...
DumpDBFiles: dump arrays holding debugged files;
DumpPackages: dump symbol tables of packages;
quote, HighBit, undefPrint: change style of string dump;
- tkRunning: run Tk while prompting (with ReadLine);
- signalLevel warnLevel dieLevel: level of verbosity;
Option PrintRet affects printing of return value after r command,
frame affects printing messages on entry and exit from subroutines.
+ AutoTrace affects printing messages on every possible breaking point.
During startup options are initialized from \$ENV{PERLDB_OPTS}.
You can put additional initialization options TTY, noTTY,
ReadLine, and NonStop there.
@@ -1580,6 +1623,9 @@ command Execute as a perl statement in current package.
v Show versions of loaded modules.
R Pure-man-restart of debugger, some of debugger state
and command-line options may be lost.
+ Currently the following setting are preserved:
+ history, breakpoints and actions, debugger Options
+ and the following command-line options: -w, -I, -e.
h [db_command] Get help [on a specific debugger command], enter |h to page.
h h Summary of debugger commands.
q or ^D Quit. Set \$DB::finished to 0 to debug global destruction.
@@ -1818,8 +1864,9 @@ sub end_report { print $OUT "Use `q' to quit and `R' to restart. `h q' for detai
END {
$finished = $inhibit_exit; # So that some keys may be disabled.
- $DB::single = !$exiting; # Do not trace destructors on exit
- DB::fake::at_exit() unless $exiting;
+ # Do not stop in at_exit() and destructors on exit:
+ $DB::single = !$exiting && !$runnonstop;
+ DB::fake::at_exit() unless $exiting or $runnonstop;
}
package DB::fake;
@@ -1828,4 +1875,6 @@ sub at_exit {
"Debuggee terminated. Use `q' to quit and `R' to restart.";
}
+package DB; # Do not trace this 1; below!
+
1;
diff --git a/lib/sigtrap.pm b/lib/sigtrap.pm
index ed5925b0ab..c081123b6b 100644
--- a/lib/sigtrap.pm
+++ b/lib/sigtrap.pm
@@ -167,9 +167,9 @@ installed signals.
=item B<stack-trace>
-The handler used for subsequently installed signals will output a Perl
-stack trace to STDERR and then tries to dump core. This is the default
-signal handler.
+The handler used for subsequently installed signals outputs a Perl stack
+trace to STDERR and then tries to dump core. This is the default signal
+handler.
=item B<die>
@@ -186,7 +186,7 @@ assignment to an element of C<%SIG>.
=head2 SIGNAL LISTS
-B<sigtrap> has two built-in lists of signals to trap. They are:
+B<sigtrap> has a few built-in lists of signals to trap. They are:
=over 4
@@ -222,7 +222,7 @@ silently ignored.
=item B<untrapped>
-This token tells B<sigtrap> only to install handlers for subsequently
+This token tells B<sigtrap> to install handlers only for subsequently
listed signals which aren't already trapped or ignored.
=item B<any>
@@ -232,9 +232,9 @@ listed signals. This is the default behavior.
=item I<signal>
-Any argument which looks like a signals name (that is,
-C</^[A-Z][A-Z0-9]*$/>) is taken as a signal name and indicates that
-B<sigtrap> should install a handler for it.
+Any argument which looks like a signal name (that is,
+C</^[A-Z][A-Z0-9]*$/>) indicates that B<sigtrap> should install a
+handler for that name.
=item I<number>
diff --git a/lib/syslog.pl b/lib/syslog.pl
index 8807ef027d..9e03399e4d 100644
--- a/lib/syslog.pl
+++ b/lib/syslog.pl
@@ -143,7 +143,7 @@ sub xlate {
$name = uc $name;
$name = "LOG_$name" unless $name =~ /^LOG_/;
$name = "syslog'$name";
- eval(&$name) || -1;
+ defined &$name ? &$name : -1;
}
sub connect {