diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Class/Template.pm | 241 | ||||
-rw-r--r-- | lib/ExtUtils/Embed.pm | 10 | ||||
-rw-r--r-- | lib/File/Path.pm | 2 | ||||
-rw-r--r-- | lib/File/stat.pm | 111 | ||||
-rw-r--r-- | lib/FileHandle.pm | 227 | ||||
-rw-r--r-- | lib/Net/hostent.pm | 147 | ||||
-rw-r--r-- | lib/Net/netent.pm | 165 | ||||
-rw-r--r-- | lib/Net/protoent.pm | 92 | ||||
-rw-r--r-- | lib/Net/servent.pm | 109 | ||||
-rw-r--r-- | lib/Pod/Text.pm | 2 | ||||
-rw-r--r-- | lib/Sys/Syslog.pm | 2 | ||||
-rw-r--r-- | lib/Time/gmtime.pm | 87 | ||||
-rw-r--r-- | lib/Time/localtime.pm | 83 | ||||
-rw-r--r-- | lib/Time/tm.pm | 27 | ||||
-rw-r--r-- | lib/User/grent.pm | 91 | ||||
-rw-r--r-- | lib/User/pwent.pm | 101 | ||||
-rw-r--r-- | lib/perl5db.pl | 117 | ||||
-rw-r--r-- | lib/sigtrap.pm | 16 | ||||
-rw-r--r-- | lib/syslog.pl | 2 |
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 { |