This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Problems with SKIP in makemaker
[perl5.git] / lib / Net / netent.pm
1 package Net::netent;
2 use strict;
3
4 BEGIN { 
5     use Exporter   ();
6     use vars       qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
7     @ISA         = qw(Exporter);
8     @EXPORT      = qw(getnetbyname getnetbyaddr getnet);
9     @EXPORT_OK   = qw(
10                         $n_name         @n_aliases
11                         $n_addrtype     $n_net
12                    );
13     %EXPORT_TAGS = ( FIELDS => [ @EXPORT_OK, @EXPORT ] );
14 }
15 use vars      @EXPORT_OK;
16
17 use Class::Template qw(struct);
18 struct 'Net::netent' => [
19    name         => '$',
20    aliases      => '@',
21    addrtype     => '$',
22    net          => '$',
23 ];
24
25 sub populate (@) {
26     return unless @_;
27     my $nob = new();
28     $n_name      =    $nob->[0]              = $_[0];
29     @n_aliases   = @{ $nob->[1] } = split ' ', $_[1];
30     $n_addrtype  =    $nob->[2]              = $_[2];
31     $n_net       =    $nob->[3]              = $_[3];
32     return $nob;
33
34
35 sub getnetbyname ($)  { populate(CORE::getnetbyname(shift)) } 
36
37 sub getnetbyaddr ($;$) { 
38     my ($net, $addrtype);
39     $net = shift;
40     require Socket if @_;
41     $addrtype = @_ ? shift : Socket::AF_INET();
42     populate(CORE::getnetbyaddr($net, $addrtype)) 
43
44
45 sub getnet($) {
46     if ($_[0] =~ /^\d+(?:\.\d+(?:\.\d+(?:\.\d+)?)?)?$/) {
47         require Socket;
48         &getnetbyaddr(Socket::inet_aton(shift));
49     } else {
50         &getnetbyname;
51     } 
52
53
54 1;
55 __END__
56
57 =head1 NAME
58
59 Net::netent - by-name interface to Perl's built-in getnet*() functions
60
61 =head1 SYNOPSIS
62
63  use Net::netent qw(:FIELDS);
64  getnetbyname("loopback")               or die "bad net";
65  printf "%s is %08X\n", $n_name, $n_net;
66
67  use Net::netent;
68
69  $n = getnetbyname("loopback")          or die "bad net";
70  { # there's gotta be a better way, eh?
71      @bytes = unpack("C4", pack("N", $n->net));
72      shift @bytes while @bytes && $bytes[0] == 0;
73  }
74  printf "%s is %08X [%d.%d.%d.%d]\n", $n->name, $n->net, @bytes;
75
76 =head1 DESCRIPTION
77
78 This module's default exports override the core getnetbyname() and
79 getnetbyaddr() functions, replacing them with versions that return
80 "Net::netent" objects.  This object has methods that return the similarly
81 named structure field name from the C's netent structure from F<netdb.h>;
82 namely name, aliases, addrtype, and net.  The aliases 
83 method returns an array reference, the rest scalars.  
84
85 You may also import all the structure fields directly into your namespace
86 as regular variables using the :FIELDS import tag.  (Note that this still
87 overrides your core functions.)  Access these fields as variables named
88 with a preceding C<n_>.  Thus, C<$net_obj-E<gt>name()> corresponds to
89 $n_name if you import the fields.  Array references are available as
90 regular array variables, so for example C<@{ $net_obj-E<gt>aliases()
91 }> would be simply @n_aliases.
92
93 The getnet() funtion is a simple front-end that forwards a numeric
94 argument to getnetbyaddr(), and the rest
95 to getnetbyname().
96
97 To access this functionality without the core overrides,
98 pass the C<use> an empty import list, and then access
99 function functions with their full qualified names.
100 On the other hand, the built-ins are still available
101 via the C<CORE::> pseudo-package.
102
103 =head1 EXAMPLES
104
105 The getnet() functions do this in the Perl core:
106
107     sv_setiv(sv, (I32)nent->n_net);
108
109 The gethost() functions do this in the Perl core:
110
111     sv_setpvn(sv, hent->h_addr, len);
112
113 That means that the address comes back in binary for the
114 host functions, and as a regular perl integer for the net ones.
115 This seems a bug, but here's how to deal with it:
116
117  use strict;
118  use Socket;
119  use Net::netent;
120  
121  @ARGV = ('loopback') unless @ARGV;
122  
123  my($n, $net);
124  
125  for $net ( @ARGV ) {
126  
127      unless ($n = getnetbyname($net)) {
128         warn "$0: no such net: $net\n";
129         next;
130      }
131  
132      printf "\n%s is %s%s\n", 
133             $net, 
134             lc($n->name) eq lc($net) ? "" : "*really* ",
135             $n->name;
136  
137      print "\taliases are ", join(", ", @{$n->aliases}), "\n"
138                 if @{$n->aliases};     
139  
140      # this is stupid; first, why is this not in binary?
141      # second, why am i going through these convolutions
142      # to make it looks right
143      {
144         my @a = unpack("C4", pack("N", $n->net));
145         shift @a while @a && $a[0] == 0;
146         printf "\taddr is %s [%d.%d.%d.%d]\n", $n->net, @a;
147      }
148  
149      if ($n = getnetbyaddr($n->net)) {
150         if (lc($n->name) ne lc($net)) {
151             printf "\tThat addr reverses to net %s!\n", $n->name;
152             $net = $n->name;
153             redo;
154         } 
155      }
156  }
157
158 =head1 NOTE
159
160 While this class is currently implemented using the Class::Template
161 module to build a struct-like class, you shouldn't rely upon this.
162
163 =head1 AUTHOR
164
165 Tom Christiansen