Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

333 lines
7.3 KiB

  1. # Net::Domain.pm
  2. #
  3. # Copyright (c) 1995-1998 Graham Barr <[email protected]>. All rights reserved.
  4. # This program is free software; you can redistribute it and/or
  5. # modify it under the same terms as Perl itself.
  6. package Net::Domain;
  7. require Exporter;
  8. use Carp;
  9. use strict;
  10. use vars qw($VERSION @ISA @EXPORT_OK);
  11. use Net::Config;
  12. @ISA = qw(Exporter);
  13. @EXPORT_OK = qw(hostname hostdomain hostfqdn domainname);
  14. $VERSION = "2.13"; # $Id: //depot/libnet/Net/Domain.pm#10 $
  15. my($host,$domain,$fqdn) = (undef,undef,undef);
  16. # Try every conceivable way to get hostname.
  17. sub _hostname {
  18. # we already know it
  19. return $host
  20. if(defined $host);
  21. if ($^O eq 'MSWin32') {
  22. require Socket;
  23. my ($name,$alias,$type,$len,@addr) = gethostbyname($ENV{'COMPUTERNAME'}||'localhost');
  24. while (@addr)
  25. {
  26. my $a = shift(@addr);
  27. $host = gethostbyaddr($a,Socket::AF_INET());
  28. last if defined $host;
  29. }
  30. if (index($host,'.') > 0) {
  31. $fqdn = $host;
  32. ($host,$domain) = $fqdn =~ /^([^\.]+)\.(.*)$/;
  33. }
  34. return $host;
  35. }
  36. elsif ($^O eq 'MacOS') {
  37. chomp ($host = `hostname`);
  38. }
  39. elsif ($^O eq 'VMS') { ## multiple varieties of net s/w makes this hard
  40. $host = $ENV{'UCX$INET_HOST'} if defined($ENV{'UCX$INET_HOST'});
  41. $host = $ENV{'MULTINET_HOST_NAME'} if defined($ENV{'MULTINET_HOST_NAME'});
  42. if (index($host,'.') > 0) {
  43. $fqdn = $host;
  44. ($host,$domain) = $fqdn =~ /^([^\.]+)\.(.*)$/;
  45. }
  46. return $host;
  47. }
  48. else {
  49. local $SIG{'__DIE__'};
  50. # syscall is preferred since it avoids tainting problems
  51. eval {
  52. my $tmp = "\0" x 256; ## preload scalar
  53. eval {
  54. package main;
  55. require "syscall.ph";
  56. defined(&main::SYS_gethostname);
  57. }
  58. || eval {
  59. package main;
  60. require "sys/syscall.ph";
  61. defined(&main::SYS_gethostname);
  62. }
  63. and $host = (syscall(&main::SYS_gethostname, $tmp, 256) == 0)
  64. ? $tmp
  65. : undef;
  66. }
  67. # POSIX
  68. || eval {
  69. require POSIX;
  70. $host = (POSIX::uname())[1];
  71. }
  72. # trusty old hostname command
  73. || eval {
  74. chop($host = `(hostname) 2>/dev/null`); # BSD'ish
  75. }
  76. # sysV/POSIX uname command (may truncate)
  77. || eval {
  78. chop($host = `uname -n 2>/dev/null`); ## SYSV'ish && POSIX'ish
  79. }
  80. # Apollo pre-SR10
  81. || eval {
  82. $host = (split(/[:\. ]/,`/com/host`,6))[0];
  83. }
  84. || eval {
  85. $host = "";
  86. };
  87. }
  88. # remove garbage
  89. $host =~ s/[\0\r\n]+//go;
  90. $host =~ s/(\A\.+|\.+\Z)//go;
  91. $host =~ s/\.\.+/\./go;
  92. $host;
  93. }
  94. sub _hostdomain {
  95. # we already know it
  96. return $domain
  97. if(defined $domain);
  98. local $SIG{'__DIE__'};
  99. return $domain = $NetConfig{'inet_domain'}
  100. if defined $NetConfig{'inet_domain'};
  101. # try looking in /etc/resolv.conf
  102. # putting this here and assuming that it is correct, eliminates
  103. # calls to gethostbyname, and therefore DNS lookups. This helps
  104. # those on dialup systems.
  105. local *RES;
  106. if(open(RES,"/etc/resolv.conf")) {
  107. while(<RES>) {
  108. $domain = $1
  109. if(/\A\s*(?:domain|search)\s+(\S+)/);
  110. }
  111. close(RES);
  112. return $domain
  113. if(defined $domain);
  114. }
  115. # just try hostname and system calls
  116. my $host = _hostname();
  117. my(@hosts);
  118. local($_);
  119. @hosts = ($host,"localhost");
  120. unless($host =~ /\./) {
  121. my $dom = undef;
  122. eval {
  123. my $tmp = "\0" x 256; ## preload scalar
  124. eval {
  125. package main;
  126. require "syscall.ph";
  127. }
  128. || eval {
  129. package main;
  130. require "sys/syscall.ph";
  131. }
  132. and $dom = (syscall(&main::SYS_getdomainname, $tmp, 256) == 0)
  133. ? $tmp
  134. : undef;
  135. };
  136. if ($^O ne 'MSWin32') {
  137. chop($dom = `domainname 2>/dev/null`)
  138. unless(defined $dom);
  139. }
  140. if(defined $dom) {
  141. my @h = ();
  142. while(length($dom)) {
  143. push(@h, "$host.$dom");
  144. $dom =~ s/^[^.]+.//;
  145. }
  146. unshift(@hosts,@h);
  147. }
  148. }
  149. # Attempt to locate FQDN
  150. foreach (@hosts) {
  151. my @info = gethostbyname($_);
  152. next unless @info;
  153. # look at real name & aliases
  154. my $site;
  155. foreach $site ($info[0], split(/ /,$info[1])) {
  156. if(rindex($site,".") > 0) {
  157. # Extract domain from FQDN
  158. ($domain = $site) =~ s/\A[^\.]+\.//;
  159. return $domain;
  160. }
  161. }
  162. }
  163. # Look for environment variable
  164. $domain ||= $ENV{LOCALDOMAIN} ||= $ENV{DOMAIN} || undef;
  165. if(defined $domain) {
  166. $domain =~ s/[\r\n\0]+//g;
  167. $domain =~ s/(\A\.+|\.+\Z)//g;
  168. $domain =~ s/\.\.+/\./g;
  169. }
  170. $domain;
  171. }
  172. sub domainname {
  173. return $fqdn
  174. if(defined $fqdn);
  175. _hostname();
  176. _hostdomain();
  177. # Assumption: If the host name does not contain a period
  178. # and the domain name does, then assume that they are correct
  179. # this helps to eliminate calls to gethostbyname, and therefore
  180. # eleminate DNS lookups
  181. return $fqdn = $host . "." . $domain
  182. if($host !~ /\./ && $domain =~ /\./);
  183. # For hosts that have no name, just an IP address
  184. return $fqdn = $host if $host =~ /^\d+(\.\d+){3}$/;
  185. my @host = split(/\./, $host);
  186. my @domain = split(/\./, $domain);
  187. my @fqdn = ();
  188. # Determine from @host & @domain the FQDN
  189. my @d = @domain;
  190. LOOP:
  191. while(1) {
  192. my @h = @host;
  193. while(@h) {
  194. my $tmp = join(".",@h,@d);
  195. if((gethostbyname($tmp))[0]) {
  196. @fqdn = (@h,@d);
  197. $fqdn = $tmp;
  198. last LOOP;
  199. }
  200. pop @h;
  201. }
  202. last unless shift @d;
  203. }
  204. if(@fqdn) {
  205. $host = shift @fqdn;
  206. until((gethostbyname($host))[0]) {
  207. $host .= "." . shift @fqdn;
  208. }
  209. $domain = join(".", @fqdn);
  210. }
  211. else {
  212. undef $host;
  213. undef $domain;
  214. undef $fqdn;
  215. }
  216. $fqdn;
  217. }
  218. sub hostfqdn { domainname() }
  219. sub hostname {
  220. domainname()
  221. unless(defined $host);
  222. return $host;
  223. }
  224. sub hostdomain {
  225. domainname()
  226. unless(defined $domain);
  227. return $domain;
  228. }
  229. 1; # Keep require happy
  230. __END__
  231. =head1 NAME
  232. Net::Domain - Attempt to evaluate the current host's internet name and domain
  233. =head1 SYNOPSIS
  234. use Net::Domain qw(hostname hostfqdn hostdomain);
  235. =head1 DESCRIPTION
  236. Using various methods B<attempt> to find the Fully Qualified Domain Name (FQDN)
  237. of the current host. From this determine the host-name and the host-domain.
  238. Each of the functions will return I<undef> if the FQDN cannot be determined.
  239. =over 4
  240. =item hostfqdn ()
  241. Identify and return the FQDN of the current host.
  242. =item hostname ()
  243. Returns the smallest part of the FQDN which can be used to identify the host.
  244. =item hostdomain ()
  245. Returns the remainder of the FQDN after the I<hostname> has been removed.
  246. =back
  247. =head1 AUTHOR
  248. Graham Barr <[email protected]>.
  249. Adapted from Sys::Hostname by David Sundstrom <[email protected]>
  250. =head1 COPYRIGHT
  251. Copyright (c) 1995-1998 Graham Barr. All rights reserved.
  252. This program is free software; you can redistribute it and/or modify
  253. it under the same terms as Perl itself.
  254. =cut