1b8851fccSafresh1# Net::Domain.pm 2b8851fccSafresh1# 35759b3d2Safresh1# Copyright (C) 1995-1998 Graham Barr. All rights reserved. 4eac174f2Safresh1# Copyright (C) 2013-2014, 2020 Steve Hay. All rights reserved. 5b8851fccSafresh1# This module is free software; you can redistribute it and/or modify it under 6b8851fccSafresh1# the same terms as Perl itself, i.e. under the terms of either the GNU General 7b8851fccSafresh1# Public License or the Artistic License, as specified in the F<LICENCE> file. 8b8851fccSafresh1 9b8851fccSafresh1package Net::Domain; 10b8851fccSafresh1 11b8851fccSafresh1use 5.008001; 12b8851fccSafresh1 13b8851fccSafresh1use strict; 14b8851fccSafresh1use warnings; 15b8851fccSafresh1 16b8851fccSafresh1use Carp; 17b8851fccSafresh1use Exporter; 18b8851fccSafresh1use Net::Config; 19b8851fccSafresh1 20b8851fccSafresh1our @ISA = qw(Exporter); 21b8851fccSafresh1our @EXPORT_OK = qw(hostname hostdomain hostfqdn domainname); 22*e0680481Safresh1our $VERSION = "3.15"; 23b8851fccSafresh1 24b8851fccSafresh1my ($host, $domain, $fqdn) = (undef, undef, undef); 25b8851fccSafresh1 26b8851fccSafresh1# Try every conceivable way to get hostname. 27b8851fccSafresh1 28b8851fccSafresh1 29b8851fccSafresh1sub _hostname { 30b8851fccSafresh1 31b8851fccSafresh1 # we already know it 32b8851fccSafresh1 return $host 33b8851fccSafresh1 if (defined $host); 34b8851fccSafresh1 35b8851fccSafresh1 if ($^O eq 'MSWin32') { 36b8851fccSafresh1 require Socket; 37b8851fccSafresh1 my ($name, $alias, $type, $len, @addr) = gethostbyname($ENV{'COMPUTERNAME'} || 'localhost'); 38b8851fccSafresh1 while (@addr) { 39b8851fccSafresh1 my $a = shift(@addr); 40b8851fccSafresh1 $host = gethostbyaddr($a, Socket::AF_INET()); 41b8851fccSafresh1 last if defined $host; 42b8851fccSafresh1 } 43b8851fccSafresh1 if (defined($host) && index($host, '.') > 0) { 44b8851fccSafresh1 $fqdn = $host; 45b8851fccSafresh1 ($host, $domain) = $fqdn =~ /^([^.]+)\.(.*)$/; 46b8851fccSafresh1 } 47b8851fccSafresh1 return $host; 48b8851fccSafresh1 } 49b8851fccSafresh1 elsif ($^O eq 'MacOS') { 50b8851fccSafresh1 chomp($host = `hostname`); 51b8851fccSafresh1 } 52b8851fccSafresh1 elsif ($^O eq 'VMS') { ## multiple varieties of net s/w makes this hard 53b8851fccSafresh1 $host = $ENV{'UCX$INET_HOST'} if defined($ENV{'UCX$INET_HOST'}); 54b8851fccSafresh1 $host = $ENV{'MULTINET_HOST_NAME'} if defined($ENV{'MULTINET_HOST_NAME'}); 55b8851fccSafresh1 if (index($host, '.') > 0) { 56b8851fccSafresh1 $fqdn = $host; 57b8851fccSafresh1 ($host, $domain) = $fqdn =~ /^([^.]+)\.(.*)$/; 58b8851fccSafresh1 } 59b8851fccSafresh1 return $host; 60b8851fccSafresh1 } 61b8851fccSafresh1 else { 62b8851fccSafresh1 local $SIG{'__DIE__'}; 63b8851fccSafresh1 64b8851fccSafresh1 # syscall is preferred since it avoids tainting problems 65b8851fccSafresh1 eval { 66b8851fccSafresh1 my $tmp = "\0" x 256; ## preload scalar 67b8851fccSafresh1 eval { 68b8851fccSafresh1 package main; 69b8851fccSafresh1 require "syscall.ph"; ## no critic (Modules::RequireBarewordIncludes) 70b8851fccSafresh1 defined(&main::SYS_gethostname); 71b8851fccSafresh1 } 72b8851fccSafresh1 || eval { 73b8851fccSafresh1 package main; 74b8851fccSafresh1 require "sys/syscall.ph"; ## no critic (Modules::RequireBarewordIncludes) 75b8851fccSafresh1 defined(&main::SYS_gethostname); 76b8851fccSafresh1 } 77b8851fccSafresh1 and $host = 78b8851fccSafresh1 (syscall(&main::SYS_gethostname, $tmp, 256) == 0) 79b8851fccSafresh1 ? $tmp 80b8851fccSafresh1 : undef; 81b8851fccSafresh1 } 82b8851fccSafresh1 83b8851fccSafresh1 # POSIX 84b8851fccSafresh1 || eval { 85b8851fccSafresh1 require POSIX; 86b8851fccSafresh1 $host = (POSIX::uname())[1]; 87b8851fccSafresh1 } 88b8851fccSafresh1 89b8851fccSafresh1 # trusty old hostname command 90b8851fccSafresh1 || eval { 91b8851fccSafresh1 chop($host = `(hostname) 2>/dev/null`); # BSD'ish 92b8851fccSafresh1 } 93b8851fccSafresh1 94b8851fccSafresh1 # sysV/POSIX uname command (may truncate) 95b8851fccSafresh1 || eval { 96b8851fccSafresh1 chop($host = `uname -n 2>/dev/null`); ## SYSV'ish && POSIX'ish 97b8851fccSafresh1 } 98b8851fccSafresh1 99b8851fccSafresh1 # Apollo pre-SR10 100b8851fccSafresh1 || eval { $host = (split(/[:. ]/, `/com/host`, 6))[0]; } 101b8851fccSafresh1 102b8851fccSafresh1 || eval { $host = ""; }; 103b8851fccSafresh1 } 104b8851fccSafresh1 105b8851fccSafresh1 # remove garbage 106b8851fccSafresh1 $host =~ s/[\0\r\n]+//go; 107b8851fccSafresh1 $host =~ s/(\A\.+|\.+\Z)//go; 108b8851fccSafresh1 $host =~ s/\.\.+/\./go; 109b8851fccSafresh1 110b8851fccSafresh1 $host; 111b8851fccSafresh1} 112b8851fccSafresh1 113b8851fccSafresh1 114b8851fccSafresh1sub _hostdomain { 115b8851fccSafresh1 116b8851fccSafresh1 # we already know it 117b8851fccSafresh1 return $domain 118b8851fccSafresh1 if (defined $domain); 119b8851fccSafresh1 120b8851fccSafresh1 local $SIG{'__DIE__'}; 121b8851fccSafresh1 122b8851fccSafresh1 return $domain = $NetConfig{'inet_domain'} 123b8851fccSafresh1 if defined $NetConfig{'inet_domain'}; 124b8851fccSafresh1 125b8851fccSafresh1 # try looking in /etc/resolv.conf 126b8851fccSafresh1 # putting this here and assuming that it is correct, eliminates 127b8851fccSafresh1 # calls to gethostbyname, and therefore DNS lookups. This helps 128b8851fccSafresh1 # those on dialup systems. 129b8851fccSafresh1 130b8851fccSafresh1 local ($_); 131b8851fccSafresh1 132b8851fccSafresh1 if (open(my $res, '<', "/etc/resolv.conf")) { 133b8851fccSafresh1 while (<$res>) { 134b8851fccSafresh1 $domain = $1 135b8851fccSafresh1 if (/\A\s*(?:domain|search)\s+(\S+)/); 136b8851fccSafresh1 } 137b8851fccSafresh1 close($res); 138b8851fccSafresh1 139b8851fccSafresh1 return $domain 140b8851fccSafresh1 if (defined $domain); 141b8851fccSafresh1 } 142b8851fccSafresh1 143b8851fccSafresh1 # just try hostname and system calls 144b8851fccSafresh1 145b8851fccSafresh1 my $host = _hostname(); 146b8851fccSafresh1 my (@hosts); 147b8851fccSafresh1 148b8851fccSafresh1 @hosts = ($host, "localhost"); 149b8851fccSafresh1 150b8851fccSafresh1 unless (defined($host) && $host =~ /\./) { 151b8851fccSafresh1 my $dom = undef; 152b8851fccSafresh1 eval { 153b8851fccSafresh1 my $tmp = "\0" x 256; ## preload scalar 154b8851fccSafresh1 eval { 155b8851fccSafresh1 package main; 156b8851fccSafresh1 require "syscall.ph"; ## no critic (Modules::RequireBarewordIncludes) 157b8851fccSafresh1 } 158b8851fccSafresh1 || eval { 159b8851fccSafresh1 package main; 160b8851fccSafresh1 require "sys/syscall.ph"; ## no critic (Modules::RequireBarewordIncludes) 161b8851fccSafresh1 } 162b8851fccSafresh1 and $dom = 163b8851fccSafresh1 (syscall(&main::SYS_getdomainname, $tmp, 256) == 0) 164b8851fccSafresh1 ? $tmp 165b8851fccSafresh1 : undef; 166b8851fccSafresh1 }; 167b8851fccSafresh1 168b8851fccSafresh1 if ($^O eq 'VMS') { 169b8851fccSafresh1 $dom ||= $ENV{'TCPIP$INET_DOMAIN'} 170b8851fccSafresh1 || $ENV{'UCX$INET_DOMAIN'}; 171b8851fccSafresh1 } 172b8851fccSafresh1 173b8851fccSafresh1 chop($dom = `domainname 2>/dev/null`) 174b8851fccSafresh1 unless (defined $dom || $^O =~ /^(?:cygwin|MSWin32|android)/); 175b8851fccSafresh1 176b8851fccSafresh1 if (defined $dom) { 177b8851fccSafresh1 my @h = (); 178b8851fccSafresh1 $dom =~ s/^\.+//; 179b8851fccSafresh1 while (length($dom)) { 180b8851fccSafresh1 push(@h, "$host.$dom"); 181b8851fccSafresh1 $dom =~ s/^[^.]+.+// or last; 182b8851fccSafresh1 } 183b8851fccSafresh1 unshift(@hosts, @h); 184b8851fccSafresh1 } 185b8851fccSafresh1 } 186b8851fccSafresh1 187b8851fccSafresh1 # Attempt to locate FQDN 188b8851fccSafresh1 189b8851fccSafresh1 foreach (grep { defined $_ } @hosts) { 190b8851fccSafresh1 my @info = gethostbyname($_); 191b8851fccSafresh1 192b8851fccSafresh1 next unless @info; 193b8851fccSafresh1 194b8851fccSafresh1 # look at real name & aliases 195b8851fccSafresh1 foreach my $site ($info[0], split(/ /, $info[1])) { 196b8851fccSafresh1 if (rindex($site, ".") > 0) { 197b8851fccSafresh1 198b8851fccSafresh1 # Extract domain from FQDN 199b8851fccSafresh1 200b8851fccSafresh1 ($domain = $site) =~ s/\A[^.]+\.//; 201b8851fccSafresh1 return $domain; 202b8851fccSafresh1 } 203b8851fccSafresh1 } 204b8851fccSafresh1 } 205b8851fccSafresh1 206b8851fccSafresh1 # Look for environment variable 207b8851fccSafresh1 208b8851fccSafresh1 $domain ||= $ENV{LOCALDOMAIN} || $ENV{DOMAIN}; 209b8851fccSafresh1 210b8851fccSafresh1 if (defined $domain) { 211b8851fccSafresh1 $domain =~ s/[\r\n\0]+//g; 212b8851fccSafresh1 $domain =~ s/(\A\.+|\.+\Z)//g; 213b8851fccSafresh1 $domain =~ s/\.\.+/\./g; 214b8851fccSafresh1 } 215b8851fccSafresh1 216b8851fccSafresh1 $domain; 217b8851fccSafresh1} 218b8851fccSafresh1 219b8851fccSafresh1 220b8851fccSafresh1sub domainname { 221b8851fccSafresh1 222b8851fccSafresh1 return $fqdn 223b8851fccSafresh1 if (defined $fqdn); 224b8851fccSafresh1 225b8851fccSafresh1 _hostname(); 226b8851fccSafresh1 227b8851fccSafresh1 # *.local names are special on darwin. If we call gethostbyname below, it 228b8851fccSafresh1 # may hang while waiting for another, non-existent computer to respond. 229b8851fccSafresh1 if($^O eq 'darwin' && $host =~ /\.local$/) { 230b8851fccSafresh1 return $host; 231b8851fccSafresh1 } 232b8851fccSafresh1 233b8851fccSafresh1 _hostdomain(); 234b8851fccSafresh1 235b8851fccSafresh1 # Assumption: If the host name does not contain a period 236b8851fccSafresh1 # and the domain name does, then assume that they are correct 237b8851fccSafresh1 # this helps to eliminate calls to gethostbyname, and therefore 238b8851fccSafresh1 # eliminate DNS lookups 239b8851fccSafresh1 240b8851fccSafresh1 return $fqdn = $host . "." . $domain 241b8851fccSafresh1 if (defined $host 242b8851fccSafresh1 and defined $domain 243b8851fccSafresh1 and $host !~ /\./ 244b8851fccSafresh1 and $domain =~ /\./); 245b8851fccSafresh1 246b8851fccSafresh1 # For hosts that have no name, just an IP address 247b8851fccSafresh1 return $fqdn = $host if defined $host and $host =~ /^\d+(\.\d+){3}$/; 248b8851fccSafresh1 249b8851fccSafresh1 my @host = defined $host ? split(/\./, $host) : ('localhost'); 250b8851fccSafresh1 my @domain = defined $domain ? split(/\./, $domain) : (); 251b8851fccSafresh1 my @fqdn = (); 252b8851fccSafresh1 253b8851fccSafresh1 # Determine from @host & @domain the FQDN 254b8851fccSafresh1 255b8851fccSafresh1 my @d = @domain; 256b8851fccSafresh1 257b8851fccSafresh1LOOP: 258b8851fccSafresh1 while (1) { 259b8851fccSafresh1 my @h = @host; 260b8851fccSafresh1 while (@h) { 261b8851fccSafresh1 my $tmp = join(".", @h, @d); 262b8851fccSafresh1 if ((gethostbyname($tmp))[0]) { 263b8851fccSafresh1 @fqdn = (@h, @d); 264b8851fccSafresh1 $fqdn = $tmp; 265b8851fccSafresh1 last LOOP; 266b8851fccSafresh1 } 267b8851fccSafresh1 pop @h; 268b8851fccSafresh1 } 269b8851fccSafresh1 last unless shift @d; 270b8851fccSafresh1 } 271b8851fccSafresh1 272b8851fccSafresh1 if (@fqdn) { 273b8851fccSafresh1 $host = shift @fqdn; 274b8851fccSafresh1 until ((gethostbyname($host))[0]) { 275b8851fccSafresh1 $host .= "." . shift @fqdn; 276b8851fccSafresh1 } 277b8851fccSafresh1 $domain = join(".", @fqdn); 278b8851fccSafresh1 } 279b8851fccSafresh1 else { 280b8851fccSafresh1 undef $host; 281b8851fccSafresh1 undef $domain; 282b8851fccSafresh1 undef $fqdn; 283b8851fccSafresh1 } 284b8851fccSafresh1 285b8851fccSafresh1 $fqdn; 286b8851fccSafresh1} 287b8851fccSafresh1 288b8851fccSafresh1 289b8851fccSafresh1sub hostfqdn { domainname() } 290b8851fccSafresh1 291b8851fccSafresh1 292b8851fccSafresh1sub hostname { 293b8851fccSafresh1 domainname() 294b8851fccSafresh1 unless (defined $host); 295b8851fccSafresh1 return $host; 296b8851fccSafresh1} 297b8851fccSafresh1 298b8851fccSafresh1 299b8851fccSafresh1sub hostdomain { 300b8851fccSafresh1 domainname() 301b8851fccSafresh1 unless (defined $domain); 302b8851fccSafresh1 return $domain; 303b8851fccSafresh1} 304b8851fccSafresh1 305b8851fccSafresh11; # Keep require happy 306b8851fccSafresh1 307b8851fccSafresh1__END__ 308b8851fccSafresh1 309b8851fccSafresh1=head1 NAME 310b8851fccSafresh1 311b8851fccSafresh1Net::Domain - Attempt to evaluate the current host's internet name and domain 312b8851fccSafresh1 313b8851fccSafresh1=head1 SYNOPSIS 314b8851fccSafresh1 315b8851fccSafresh1 use Net::Domain qw(hostname hostfqdn hostdomain domainname); 316b8851fccSafresh1 317b8851fccSafresh1=head1 DESCRIPTION 318b8851fccSafresh1 319b8851fccSafresh1Using various methods B<attempt> to find the Fully Qualified Domain Name (FQDN) 320b8851fccSafresh1of the current host. From this determine the host-name and the host-domain. 321b8851fccSafresh1 322b8851fccSafresh1Each of the functions will return I<undef> if the FQDN cannot be determined. 323b8851fccSafresh1 324eac174f2Safresh1=head2 Functions 325eac174f2Safresh1 326b8851fccSafresh1=over 4 327b8851fccSafresh1 328eac174f2Safresh1=item C<hostfqdn()> 329b8851fccSafresh1 330b8851fccSafresh1Identify and return the FQDN of the current host. 331b8851fccSafresh1 332eac174f2Safresh1=item C<domainname()> 333b8851fccSafresh1 334b8851fccSafresh1An alias for hostfqdn(). 335b8851fccSafresh1 336eac174f2Safresh1=item C<hostname()> 337b8851fccSafresh1 338b8851fccSafresh1Returns the smallest part of the FQDN which can be used to identify the host. 339b8851fccSafresh1 340eac174f2Safresh1=item C<hostdomain()> 341b8851fccSafresh1 342b8851fccSafresh1Returns the remainder of the FQDN after the I<hostname> has been removed. 343b8851fccSafresh1 344b8851fccSafresh1=back 345b8851fccSafresh1 346eac174f2Safresh1=head1 EXPORTS 347eac174f2Safresh1 348eac174f2Safresh1The following symbols are, or can be, exported by this module: 349eac174f2Safresh1 350eac174f2Safresh1=over 4 351eac174f2Safresh1 352eac174f2Safresh1=item Default Exports 353eac174f2Safresh1 354eac174f2Safresh1I<None>. 355eac174f2Safresh1 356eac174f2Safresh1=item Optional Exports 357eac174f2Safresh1 358eac174f2Safresh1C<hostname>, 359eac174f2Safresh1C<hostdomain>, 360eac174f2Safresh1C<hostfqdn>, 361eac174f2Safresh1C<domainname>. 362eac174f2Safresh1 363eac174f2Safresh1=item Export Tags 364eac174f2Safresh1 365eac174f2Safresh1I<None>. 366eac174f2Safresh1 367eac174f2Safresh1=back 368eac174f2Safresh1 369eac174f2Safresh1 370eac174f2Safresh1=head1 KNOWN BUGS 371eac174f2Safresh1 372eac174f2Safresh1See L<https://rt.cpan.org/Dist/Display.html?Status=Active&Queue=libnet>. 373eac174f2Safresh1 374b8851fccSafresh1=head1 AUTHOR 375b8851fccSafresh1 376eac174f2Safresh1Graham Barr E<lt>L<gbarr@pobox.com|mailto:gbarr@pobox.com>E<gt>. 3775759b3d2Safresh1 378eac174f2Safresh1Adapted from Sys::Hostname by David Sundstrom 379eac174f2Safresh1E<lt>L<sunds@asictest.sc.ti.com|mailto:sunds@asictest.sc.ti.com>E<gt>. 380b8851fccSafresh1 381eac174f2Safresh1Steve Hay E<lt>L<shay@cpan.org|mailto:shay@cpan.org>E<gt> is now maintaining 382eac174f2Safresh1libnet as of version 1.22_02. 383b8851fccSafresh1 384b8851fccSafresh1=head1 COPYRIGHT 385b8851fccSafresh1 3865759b3d2Safresh1Copyright (C) 1995-1998 Graham Barr. All rights reserved. 3875759b3d2Safresh1 388eac174f2Safresh1Copyright (C) 2013-2014, 2020 Steve Hay. All rights reserved. 3895759b3d2Safresh1 3905759b3d2Safresh1=head1 LICENCE 391b8851fccSafresh1 392b8851fccSafresh1This module is free software; you can redistribute it and/or modify it under the 393b8851fccSafresh1same terms as Perl itself, i.e. under the terms of either the GNU General Public 394b8851fccSafresh1License or the Artistic License, as specified in the F<LICENCE> file. 395b8851fccSafresh1 396eac174f2Safresh1=head1 VERSION 397eac174f2Safresh1 398*e0680481Safresh1Version 3.15 399eac174f2Safresh1 400eac174f2Safresh1=head1 DATE 401eac174f2Safresh1 402*e0680481Safresh120 March 2023 403eac174f2Safresh1 404eac174f2Safresh1=head1 HISTORY 405eac174f2Safresh1 406eac174f2Safresh1See the F<Changes> file. 407eac174f2Safresh1 408b8851fccSafresh1=cut 409