1package Sys::Hostname; 2 3use strict; 4 5use Carp; 6 7use Exporter 'import'; 8 9our @EXPORT = qw/ hostname /; 10 11our $VERSION; 12 13use warnings (); 14 15our $host; 16 17BEGIN { 18 $VERSION = '1.25'; 19 { 20 local $SIG{__DIE__}; 21 eval { 22 require XSLoader; 23 XSLoader::load(); 24 }; 25 warn $@ if $@; 26 } 27} 28 29 30sub hostname { 31 @_ and croak("hostname() does not accepts arguments (it used to silently discard any provided)"); 32 33 # method 1 - we already know it 34 return $host if defined $host; 35 36 # method 1' - try to ask the system 37 $host = ghname() if defined &ghname; 38 return $host if defined $host; 39 40 if ($^O eq 'VMS') { 41 42 # method 2 - no sockets ==> return DECnet node name 43 eval { local $SIG{__DIE__}; $host = (gethostbyname('me'))[0] }; 44 if ($@) { return $host = $ENV{'SYS$NODE'}; } 45 46 # method 3 - has someone else done the job already? It's common for the 47 # TCP/IP stack to advertise the hostname via a logical name. (Are 48 # there any other logicals which TCP/IP stacks use for the host name?) 49 $host = $ENV{'ARPANET_HOST_NAME'} || $ENV{'INTERNET_HOST_NAME'} || 50 $ENV{'MULTINET_HOST_NAME'} || $ENV{'UCX$INET_HOST'} || 51 $ENV{'TCPWARE_DOMAINNAME'} || $ENV{'NEWS_ADDRESS'}; 52 return $host if $host; 53 54 # method 4 - does hostname happen to work? 55 my($rslt) = `hostname`; 56 if ($rslt !~ /IVVERB/) { ($host) = $rslt =~ /^(\S+)/; } 57 return $host if $host; 58 59 # rats! 60 $host = ''; 61 croak "Cannot get host name of local machine"; 62 63 } 64 elsif ($^O eq 'MSWin32') { 65 ($host) = gethostbyname('localhost'); 66 chomp($host = `hostname 2> NUL`) unless defined $host; 67 return $host; 68 } 69 else { # Unix 70 # is anyone going to make it here? 71 72 local $ENV{PATH} = '/usr/bin:/bin:/usr/sbin:/sbin'; # Paranoia. 73 74 # method 2 - syscall is preferred since it avoids tainting problems 75 # XXX: is it such a good idea to return hostname untainted? 76 eval { 77 local $SIG{__DIE__}; 78 require "syscall.ph"; 79 $host = "\0" x 65; ## preload scalar 80 syscall(&SYS_gethostname, $host, 65) == 0; 81 } 82 83 # method 2a - syscall using systeminfo instead of gethostname 84 # -- needed on systems like Solaris 85 || eval { 86 local $SIG{__DIE__}; 87 require "sys/syscall.ph"; 88 require "sys/systeminfo.ph"; 89 $host = "\0" x 65; ## preload scalar 90 syscall(&SYS_systeminfo, &SI_HOSTNAME, $host, 65) != -1; 91 } 92 93 # method 3 - trusty old hostname command 94 || eval { 95 local $SIG{__DIE__}; 96 local $SIG{CHLD}; 97 $host = `(hostname) 2>/dev/null`; # BSDish 98 } 99 100 # method 4 - use POSIX::uname(), which strictly can't be expected to be 101 # correct 102 || eval { 103 local $SIG{__DIE__}; 104 require POSIX; 105 $host = (POSIX::uname())[1]; 106 } 107 108 # method 5 - sysV uname command (may truncate) 109 || eval { 110 local $SIG{__DIE__}; 111 $host = `uname -n 2>/dev/null`; ## sysVish 112 } 113 114 # bummer 115 || croak "Cannot get host name of local machine"; 116 117 # remove garbage 118 $host =~ tr/\0\r\n//d; 119 $host; 120 } 121} 122 1231; 124 125__END__ 126 127=head1 NAME 128 129Sys::Hostname - Try every conceivable way to get hostname 130 131=head1 SYNOPSIS 132 133 use Sys::Hostname; 134 my $host = hostname; 135 136=head1 DESCRIPTION 137 138Attempts several methods of getting the system hostname and 139then caches the result. It tries the first available of the C 140library's gethostname(), C<`$Config{aphostname}`>, uname(2), 141C<syscall(SYS_gethostname)>, C<`hostname`>, C<`uname -n`>, 142and the file F</com/host>. If all that fails it C<croak>s. 143 144All NULs, returns, and newlines are removed from the result. 145 146=head1 AUTHOR 147 148David Sundstrom E<lt>F<sunds@asictest.sc.ti.com>E<gt> 149 150Texas Instruments 151 152XS code added by Greg Bacon E<lt>F<gbacon@cs.uah.edu>E<gt> 153 154=cut 155 156