Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 1 | # |
| 2 | # This is not a runnable script, it is a Perl module, a collection of variables, subroutines, etc. |
| 3 | # To get help about exported variables and subroutines, execute the following command: |
| 4 | # |
| 5 | # perldoc Uname.pm |
| 6 | # |
| 7 | # or see POD (Plain Old Documentation) embedded to the source... |
| 8 | # |
| 9 | # |
| 10 | #//===----------------------------------------------------------------------===// |
| 11 | #// |
| 12 | #// The LLVM Compiler Infrastructure |
| 13 | #// |
| 14 | #// This file is dual licensed under the MIT and the University of Illinois Open |
| 15 | #// Source Licenses. See LICENSE.txt for details. |
| 16 | #// |
| 17 | #//===----------------------------------------------------------------------===// |
| 18 | # |
| 19 | |
| 20 | package Uname; |
| 21 | |
| 22 | use strict; |
| 23 | use warnings; |
| 24 | use warnings::register; |
| 25 | use Exporter; |
| 26 | |
| 27 | use POSIX; |
| 28 | use File::Glob ":glob"; |
| 29 | use Net::Domain qw{}; |
| 30 | |
| 31 | # Following code does not work with Perl 5.6 on Linux* OS and Windows* OS: |
| 32 | # |
| 33 | # use if $^O eq "darwin", tools => qw{}; |
| 34 | # |
| 35 | # The workaround for Perl 5.6: |
| 36 | # |
| 37 | BEGIN { |
| 38 | if ( $^O eq "darwin" or $^O eq "linux" ) { |
| 39 | require tools; |
| 40 | import tools; |
| 41 | }; # if |
| 42 | if ( $^O eq "MSWin32" ) { |
| 43 | require Win32; |
| 44 | }; # if |
| 45 | }; # BEGIN |
| 46 | |
| 47 | my $mswin = qr{\A(?:MSWin32|Windows_NT)\z}; |
| 48 | |
| 49 | my @posix = qw{ kernel_name fqdn kernel_release kernel_version machine }; |
| 50 | # Properties supported by POSIX::uname(). |
| 51 | my @linux = |
| 52 | qw{ processor hardware_platform operating_system }; |
| 53 | # Properties reported by uname in Linux* OS. |
| 54 | my @base = ( @posix, @linux ); |
| 55 | # Base properties. |
| 56 | my @aux = |
| 57 | ( |
| 58 | qw{ host_name domain_name }, |
| 59 | map( "operating_system_$_", qw{ name release codename description } ) |
| 60 | ); |
Alp Toker | 8f2d3f0 | 2014-02-24 10:40:15 +0000 | [diff] [blame] | 61 | # Auxiliary properties. |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 62 | my @all = ( @base, @aux ); |
| 63 | # All the properties. |
| 64 | my @meta = qw{ base_names all_names value }; |
| 65 | # Meta functions. |
| 66 | |
| 67 | our $VERSION = "0.07"; |
| 68 | our @ISA = qw{ Exporter }; |
| 69 | our @EXPORT = qw{}; |
| 70 | our @EXPORT_OK = ( @all, @meta ); |
| 71 | our %EXPORT_TAGS = |
| 72 | ( |
| 73 | base => [ @base ], |
| 74 | all => [ @all ], |
| 75 | meta => [ @meta ], |
| 76 | ); |
| 77 | |
| 78 | my %values; |
| 79 | # Hash of values. Some values are strings, some may be references to code which should be |
| 80 | # evaluated to get real value. This trick is implemented because call to Net::Domain::hostfqdn() |
| 81 | # is relatively slow. |
| 82 | |
| 83 | # Get values from POSIX::uname(). |
| 84 | @values{ @posix } = POSIX::uname(); |
| 85 | |
| 86 | # On some systems POSIX::uname() returns "short" node name (without domain name). To be consistent |
| 87 | # on all systems, we will get node name from alternative source. |
| 88 | if ( $^O =~ m/cygwin/i ) { |
| 89 | # Function from Net::Domain module works well, but on Cygwin it prints to |
| 90 | # stderr "domainname: not found". So we will use environment variables for now. |
| 91 | $values{ fqdn } = lc( $ENV{ COMPUTERNAME } . "." . $ENV{ USERDNSDOMAIN } ); |
| 92 | } else { |
| 93 | # On systems other than Cygwin, let us use Net::Domain::hostfqdn(), but do it only node name |
| 94 | # is really requested. |
| 95 | $values{ fqdn } = |
| 96 | sub { |
| 97 | my $fqdn = Net::Domain::hostfqdn(); # "fqdn" stands for "fully qualified doamain name". |
| 98 | # On some systems POSIX::uname() and Net::Domain::hostfqdn() reports different names. |
| 99 | # Let us issue a warning if they significantly different. Names are insignificantly |
| 100 | # different if POSIX::uname() matches the beginning of Net::Domain::hostfqdn(). |
| 101 | if ( |
| 102 | $fqdn eq substr( $fqdn, 0, length( $fqdn ) ) |
| 103 | && |
| 104 | ( |
| 105 | length( $fqdn ) == length( $fqdn ) |
| 106 | || |
| 107 | substr( $fqdn, length( $fqdn ), 1 ) eq "." |
| 108 | ) |
| 109 | ) { |
| 110 | # Ok. |
| 111 | } else { |
| 112 | warnings::warnif( |
| 113 | "POSIX::uname() and Net::Domain::hostfqdn() reported different names: " . |
| 114 | "\"$values{ fqdn }\" and \"$fqdn\" respectively\n" |
| 115 | ); |
| 116 | }; # if |
| 117 | return $fqdn; |
| 118 | }; # sub |
| 119 | }; # if |
| 120 | |
| 121 | if ( $^O =~ $mswin ) { |
| 122 | if ( |
| 123 | $values{ machine } =~ m{\A(?:x86|[56]86)\z} |
| 124 | and |
| 125 | exists( $ENV{ PROCESSOR_ARCHITECTURE } ) and $ENV{ PROCESSOR_ARCHITECTURE } eq "x86" |
| 126 | and |
| 127 | exists( $ENV{ PROCESSOR_ARCHITEW6432 } ) |
| 128 | ) { |
| 129 | if ( $ENV{ PROCESSOR_ARCHITEW6432 } eq "AMD64" ) { |
| 130 | $values{ machine } = "x86_64"; |
| 131 | }; # if |
| 132 | }; # if |
| 133 | }; # if |
| 134 | |
| 135 | # Some values are not returned by POSIX::uname(), let us compute them. |
| 136 | |
| 137 | # processor. |
| 138 | $values{ processor } = $values{ machine }; |
| 139 | |
| 140 | # hardware_platform. |
| 141 | if ( 0 ) { |
Alp Toker | 763b939 | 2014-02-28 09:42:41 +0000 | [diff] [blame] | 142 | } elsif ( $^O eq "linux" or $^O eq "freebsd" ) { |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 143 | if ( 0 ) { |
| 144 | } elsif ( $values{ machine } =~ m{\Ai[3456]86\z} ) { |
| 145 | $values{ hardware_platform } = "i386"; |
Alp Toker | 763b939 | 2014-02-28 09:42:41 +0000 | [diff] [blame] | 146 | } elsif ( $values{ machine } =~ m{\A(x86_64|amd64)\z} ) { |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 147 | $values{ hardware_platform } = "x86_64"; |
Jim Cownie | 181b4bb | 2013-12-23 17:28:57 +0000 | [diff] [blame] | 148 | } elsif ( $values{ machine } =~ m{\Aarmv7\D*\z} ) { |
| 149 | $values{ hardware_platform } = "arm"; |
Jim Cownie | 3051f97 | 2014-08-07 10:12:54 +0000 | [diff] [blame^] | 150 | } elsif ( $values{ machine } =~ m{\Appc64\z} ) { |
| 151 | $values{ hardware_platform } = "ppc64"; |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 152 | } else { |
| 153 | die "Unsupported machine (\"$values{ machine }\") returned by POSIX::uname(); stopped"; |
| 154 | }; # if |
| 155 | } elsif ( $^O eq "darwin" ) { |
| 156 | if ( 0 ) { |
| 157 | } elsif ( $values{ machine } eq "x86" or $values{ machine } eq "i386" ) { |
| 158 | $values{ hardware_platform } = |
| 159 | sub { |
| 160 | my $platform = "i386"; |
| 161 | # Some OSes on Intel(R) 64 still reports "i386" machine. Verify it by using |
| 162 | # the value returned by 'sysctl -n hw.optional.x86_64'. On Intel(R) 64-bit systems the |
| 163 | # value == 1; on 32-bit systems the 'hw.optional.x86_64' property either does not exist |
| 164 | # or the value == 0. The path variable does not contain a path to sysctl when |
| 165 | # started by crontab. |
| 166 | my $sysctl = ( which( "sysctl" ) or "/usr/sbin/sysctl" ); |
| 167 | my $output; |
| 168 | debug( "Executing $sysctl..." ); |
| 169 | execute( [ $sysctl, "-n", "hw.optional.x86_64" ], -stdout => \$output, -stderr => undef ); |
| 170 | chomp( $output ); |
| 171 | if ( 0 ) { |
| 172 | } elsif ( "$output" eq "" or "$output" eq "0" ) { |
| 173 | $platform = "i386"; |
| 174 | } elsif ( "$output" eq "1" ) { |
| 175 | $platform = "x86_64"; |
| 176 | } else { |
| 177 | die "Unsupported value (\"$output\") returned by \"$sysctl -n hw.optional.x86_64\"; stopped"; |
| 178 | }; # if |
| 179 | return $platform; |
| 180 | }; # sub { |
| 181 | } elsif ( $values{ machine } eq "x86_64" ) { |
| 182 | # Some OS X* versions report "x86_64". |
| 183 | $values{ hardware_platform } = "x86_64"; |
| 184 | } else { |
| 185 | die "Unsupported machine (\"$values{ machine }\") returned by POSIX::uname(); stopped"; |
| 186 | }; # if |
| 187 | } elsif ( $^O =~ $mswin ) { |
| 188 | if ( 0 ) { |
| 189 | } elsif ( $values{ machine } =~ m{\A(?:x86|[56]86)\z} ) { |
| 190 | $values{ hardware_platform } = "i386"; |
| 191 | } elsif ( $values{ machine } eq "x86_64" or $values{ machine } eq "amd64" ) { |
| 192 | # ActivePerl for IA-32 architecture returns "x86_64", while ActivePerl for Intel(R) 64 returns "amd64". |
| 193 | $values{ hardware_platform } = "x86_64"; |
| 194 | } else { |
| 195 | die "Unsupported machine (\"$values{ machine }\") returned by POSIX::uname(); stopped"; |
| 196 | }; # if |
| 197 | } elsif ( $^O eq "cygwin" ) { |
| 198 | if ( 0 ) { |
| 199 | } elsif ( $values{ machine } =~ m{\Ai[3456]86\z} ) { |
| 200 | $values{ hardware_platform } = "i386"; |
| 201 | } elsif ( $values{ machine } eq "x86_64" ) { |
| 202 | $values{ hardware_platform } = "x86_64"; |
| 203 | } else { |
| 204 | die "Unsupported machine (\"$values{ machine }\") returned by POSIX::uname(); stopped"; |
| 205 | }; # if |
| 206 | } else { |
| 207 | die "Unsupported OS (\"$^O\"); stopped"; |
| 208 | }; # if |
| 209 | |
| 210 | # operating_system. |
| 211 | if ( 0 ) { |
| 212 | } elsif ( $values{ kernel_name } eq "Linux" ) { |
| 213 | $values{ operating_system } = "GNU/Linux"; |
Alp Toker | 8f2d3f0 | 2014-02-24 10:40:15 +0000 | [diff] [blame] | 214 | my $release; # Name of chosen "*-release" file. |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 215 | my $bulk; # Content of release file. |
| 216 | # On Ubuntu, lsb-release is quite informative, e. g.: |
| 217 | # DISTRIB_ID=Ubuntu |
| 218 | # DISTRIB_RELEASE=9.04 |
| 219 | # DISTRIB_CODENAME=jaunty |
| 220 | # DISTRIB_DESCRIPTION="Ubuntu 9.04" |
| 221 | # Try lsb-release first. But on some older systems lsb-release is not informative. |
| 222 | # It may contain just one line: |
| 223 | # LSB_VERSION="1.3" |
| 224 | $release = "/etc/lsb-release"; |
| 225 | if ( -e $release ) { |
| 226 | $bulk = read_file( $release ); |
| 227 | } else { |
| 228 | $bulk = ""; |
| 229 | }; # if |
| 230 | if ( $bulk =~ m{^DISTRIB_} ) { |
| 231 | # Ok, this lsb-release is informative. |
| 232 | $bulk =~ m{^DISTRIB_ID\s*=\s*(.*?)\s*$}m |
| 233 | or runtime_error( "$release: There is no DISTRIB_ID:", $bulk, "(eof)" ); |
| 234 | $values{ operating_system_name } = $1; |
| 235 | $bulk =~ m{^DISTRIB_RELEASE\s*=\s*(.*?)\s*$}m |
| 236 | or runtime_error( "$release: There is no DISTRIB_RELEASE:", $bulk, "(eof)" ); |
| 237 | $values{ operating_system_release } = $1; |
| 238 | $bulk =~ m{^DISTRIB_CODENAME\s*=\s*(.*?)\s*$}m |
| 239 | or runtime_error( "$release: There is no DISTRIB_CODENAME:", $bulk, "(eof)" ); |
| 240 | $values{ operating_system_codename } = $1; |
| 241 | $bulk =~ m{^DISTRIB_DESCRIPTION\s*="?\s*(.*?)"?\s*$}m |
| 242 | or runtime_error( "$release: There is no DISTRIB_DESCRIPTION:", $bulk, "(eof)" ); |
| 243 | $values{ operating_system_description } = $1; |
| 244 | } else { |
| 245 | # Oops. lsb-release is missed or not informative. Try other *-release files. |
| 246 | $release = "/etc/system-release"; |
| 247 | if ( not -e $release ) { # Use /etc/system-release" if such file exists. |
| 248 | # Otherwise try other "/etc/*-release" files, but ignore "/etc/lsb-release". |
| 249 | my @releases = grep( $_ ne "/etc/lsb-release", bsd_glob( "/etc/*-release" ) ); |
| 250 | # On some Fedora systems there are two files: fedora-release and redhat-release |
| 251 | # with identical content. If fedora-release present, ignore redjat-release. |
| 252 | if ( grep( $_ eq "/etc/fedora-release", @releases ) ) { |
| 253 | @releases = grep( $_ ne "/etc/redhat-release", @releases ); |
| 254 | }; # if |
| 255 | if ( @releases == 1 ) { |
| 256 | $release = $releases[ 0 ]; |
| 257 | } else { |
| 258 | if ( @releases == 0 ) { |
| 259 | # No *-release files found, try debian_version. |
| 260 | $release = "/etc/debian_version"; |
| 261 | if ( not -e $release ) { |
| 262 | $release = undef; |
| 263 | warning( "No release files found in \"/etc/\" directory." ); |
| 264 | }; # if |
| 265 | } else { |
| 266 | $release = undef; |
| 267 | warning( "More than one release files found in \"/etc/\" directory:", @releases ); |
| 268 | }; # if |
| 269 | }; # if |
| 270 | }; # if |
| 271 | if ( defined( $release ) ) { |
| 272 | $bulk = read_file( $release ); |
| 273 | if ( $release =~ m{system|redhat|fedora} ) { |
| 274 | # Red Hat or Fedora. Parse the first line of file. |
| 275 | # Typical values of *-release (one of): |
| 276 | # Red Hat Enterprise Linux* OS Server release 5.2 (Tikanga) |
| 277 | # Red Hat Enterprise Linux* OS AS release 3 (Taroon Update 4) |
| 278 | # Fedora release 10 (Cambridge) |
| 279 | $bulk =~ m{\A(.*)$}m |
| 280 | or runtime_error( "$release: Cannot find the first line:", $bulk, "(eof)" ); |
| 281 | my $first_line = $1; |
| 282 | $values{ operating_system_description } = $first_line; |
Jim Cownie | 181b4bb | 2013-12-23 17:28:57 +0000 | [diff] [blame] | 283 | $first_line =~ m{\A(.*?)\s+release\s+(.*?)(?:\s+\((.*?)(?:\s+Update\s+(.*?))?\))?\s*$} |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 284 | or runtime_error( "$release:1: Cannot parse line:", $first_line ); |
| 285 | $values{ operating_system_name } = $1; |
| 286 | $values{ operating_system_release } = $2 . ( defined( $4 ) ? ".$4" : "" ); |
| 287 | $values{ operating_system_codename } = $3; |
| 288 | } elsif ( $release =~ m{SuSE} ) { |
| 289 | # Typical SuSE-release: |
| 290 | # SUSE Linux* OS Enterprise Server 10 (x86_64) |
| 291 | # VERSION = 10 |
| 292 | # PATCHLEVEL = 2 |
| 293 | $bulk =~ m{\A(.*)$}m |
| 294 | or runtime_error( "$release: Cannot find the first line:", $bulk, "(eof)" ); |
| 295 | my $first_line = $1; |
| 296 | $values{ operating_system_description } = $first_line; |
| 297 | $first_line =~ m{^(.*?)\s*(\d+)\s*\(.*?\)\s*$} |
| 298 | or runtime_error( "$release:1: Cannot parse line:", $first_line ); |
| 299 | $values{ operating_system_name } = $1; |
| 300 | $bulk =~ m{^VERSION\s*=\s*(.*)\s*$}m |
| 301 | or runtime_error( "$release: There is no VERSION:", $bulk, "(eof)" ); |
| 302 | $values{ operating_system_release } = $1; |
| 303 | if ( $bulk =~ m{^PATCHLEVEL\s*=\s*(.*)\s*$}m ) { |
| 304 | $values{ operating_system_release } .= ".$1"; |
| 305 | }; # if |
| 306 | } elsif ( $release =~ m{debian_version} ) { |
| 307 | # Debian. The file debian_version contains just version number, nothing more: |
| 308 | # 4.0 |
| 309 | my $name = "Debian"; |
| 310 | $bulk =~ m{\A(.*)$}m |
| 311 | or runtime_error( "$release: Cannot find the first line:", $bulk, "(eof)" ); |
| 312 | my $version = $1; |
| 313 | $values{ operating_system_name } = $name; |
| 314 | $values{ operating_system_release } = $version; |
| 315 | $values{ operating_system_codename } = "unknown"; |
| 316 | $values{ operating_system_description } = sprintf( "%s %s", $name, $version ); |
| 317 | }; # if |
| 318 | }; # if |
| 319 | }; # if |
| 320 | if ( not defined( $values{ operating_system_name } ) ) { |
| 321 | $values{ operating_system_name } = "GNU/Linux"; |
| 322 | }; # if |
| 323 | } elsif ( $values{ kernel_name } eq "Darwin" ) { |
| 324 | my %codenames = ( |
| 325 | 10.4 => "Tiger", |
| 326 | 10.5 => "Leopard", |
| 327 | 10.6 => "Snow Leopard", |
| 328 | ); |
| 329 | my $darwin; |
| 330 | my $get_os_info = |
| 331 | sub { |
| 332 | my ( $name ) = @_; |
| 333 | if ( not defined $darwin ) { |
| 334 | $darwin->{ operating_system } = "Darwin"; |
| 335 | # sw_vers prints OS X* version to stdout: |
| 336 | # ProductName: OS X* |
| 337 | # ProductVersion: 10.4.11 |
| 338 | # BuildVersion: 8S2167 |
| 339 | # It does not print codename, so we code OS X* codenames here. |
| 340 | my $sw_vers = which( "sw_vers" ) || "/usr/bin/sw_vers"; |
| 341 | my $output; |
| 342 | debug( "Executing $sw_vers..." ); |
| 343 | execute( [ $sw_vers ], -stdout => \$output, -stderr => undef ); |
| 344 | $output =~ m{^ProductName:\s*(.*)\s*$}m |
| 345 | or runtime_error( "There is no ProductName in sw_vers output:", $output, "(eof)" ); |
| 346 | my $name = $1; |
| 347 | $output =~ m{^ProductVersion:\s*(.*)\s*$}m |
| 348 | or runtime_error( "There is no ProductVersion in sw_vers output:", $output, "(eof)" ); |
| 349 | my $release = $1; |
| 350 | # Sometimes release reported as "10.4.11" (3 componentes), sometimes as "10.6". |
| 351 | # Handle both variants. |
| 352 | $release =~ m{^(\d+.\d+)(?:\.\d+)?(?=\s|$)} |
| 353 | or runtime_error( "Cannot parse OS X* version: $release" ); |
| 354 | my $version = $1; |
| 355 | my $codename = ( $codenames{ $version } or "unknown" ); |
| 356 | $darwin->{ operating_system_name } = $name; |
| 357 | $darwin->{ operating_system_release } = $release; |
| 358 | $darwin->{ operating_system_codename } = $codename; |
| 359 | $darwin->{ operating_system_description } = sprintf( "%s %s (%s)", $name, $release, $codename ); |
| 360 | }; # if |
| 361 | return $darwin->{ $name }; |
| 362 | }; # sub |
| 363 | $values{ operating_system } = sub { $get_os_info->( "operating_system" ); }; |
| 364 | $values{ operating_system_name } = sub { $get_os_info->( "operating_system_name" ); }; |
| 365 | $values{ operating_system_release } = sub { $get_os_info->( "operating_system_release" ); }; |
| 366 | $values{ operating_system_codename } = sub { $get_os_info->( "operating_system_codename" ); }; |
| 367 | $values{ operating_system_description } = sub { $get_os_info->( "operating_system_description" ); }; |
| 368 | } elsif ( $values{ kernel_name } =~ m{\AWindows[ _]NT\z} ) { |
| 369 | $values{ operating_system } = "MS Windows"; |
| 370 | # my @os_name = Win32::GetOSName(); |
| 371 | # $values{ operating_system_release } = $os_name[ 0 ]; |
| 372 | # $values{ operating_system_update } = $os_name[ 1 ]; |
| 373 | } elsif ( $values{ kernel_name } =~ m{\ACYGWIN_NT-} ) { |
| 374 | $values{ operating_system } = "MS Windows"; |
Alp Toker | 763b939 | 2014-02-28 09:42:41 +0000 | [diff] [blame] | 375 | } elsif ( $values{ kernel_name } =~ m{\AFreeBSD} ) { |
| 376 | $values{ operating_system } = "FreeBSD"; |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 377 | } else { |
Alp Toker | 763b939 | 2014-02-28 09:42:41 +0000 | [diff] [blame] | 378 | die "Unsupported kernel_name (\"$values{ kernel_name }\") returned by POSIX::uname(); stopped"; |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 379 | }; # if |
| 380 | |
| 381 | # host_name and domain_name |
| 382 | $values{ host_name } = |
| 383 | sub { |
| 384 | my $fqdn = value( "fqdn" ); |
| 385 | $fqdn =~ m{\A([^.]*)(?:\.(.*))?\z}; |
| 386 | my $host_name = $1; |
| 387 | if ( not defined( $host_name ) or $host_name eq "" ) { |
| 388 | die "Unexpected error: undefined or empty host name; stopped"; |
| 389 | }; # if |
| 390 | return $host_name; |
| 391 | }; |
| 392 | $values{ domain_name } = |
| 393 | sub { |
| 394 | my $fqdn = value( "fqdn" ); |
| 395 | $fqdn =~ m{\A([^.]*)(?:\.(.*))?\z}; |
| 396 | my $domain_name = $2; |
| 397 | if ( not defined( $domain_name ) or $domain_name eq "" ) { |
| 398 | die "Unexpected error: undefined or empty domain name; stopped"; |
| 399 | }; # if |
| 400 | return $domain_name; |
| 401 | }; |
| 402 | |
| 403 | # Replace undefined values with "unknown". |
| 404 | foreach my $name ( @all ) { |
| 405 | if ( not defined( $values{ $name } ) ) { |
| 406 | $values{ $name } = "unknown"; |
| 407 | }; # if |
| 408 | }; # foreach $name |
| 409 | |
| 410 | # Export functions reporting properties. |
| 411 | foreach my $name ( @all ) { |
| 412 | no strict "refs"; |
| 413 | *$name = sub { return value( $name ); }; |
| 414 | }; # foreach $name |
| 415 | |
| 416 | # This function returns base names. |
| 417 | sub base_names { |
| 418 | return @base; |
| 419 | }; # sub base_names |
| 420 | |
| 421 | # This function returns all the names. |
| 422 | sub all_names { |
| 423 | return @all; |
| 424 | }; # sub all_names |
| 425 | |
| 426 | # This function returns value by the specified name. |
| 427 | sub value($) { |
| 428 | my $name = shift( @_ ); |
| 429 | if ( ref( $values{ $name } ) ) { |
| 430 | my $value = $values{ $name }->(); |
| 431 | $values{ $name } = $value; |
| 432 | }; # if |
| 433 | return $values{ $name }; |
| 434 | }; # sub value |
| 435 | |
| 436 | return 1; |
| 437 | |
| 438 | __END__ |
| 439 | |
| 440 | =pod |
| 441 | |
| 442 | =head1 NAME |
| 443 | |
| 444 | B<Uname.pm> -- A few subroutines to get system information usually provided by |
| 445 | C</bin/uname> and C<POSIX::uname()>. |
| 446 | |
| 447 | =head1 SYNOPSIS |
| 448 | |
| 449 | use Uname; |
| 450 | |
| 451 | # Base property functions. |
| 452 | $kernel_name = Uname::kernel_name(); |
| 453 | $fqdn = Uname::fqdn(); |
| 454 | $kernel_release = Uname::kernel_release(); |
| 455 | $kernel_version = Uname::kernel_version(); |
| 456 | $machine = Uname::machine(); |
| 457 | $processor = Uname::processor(); |
| 458 | $hardware_platform = Uname::hardware_platform(); |
| 459 | $operating_system = Uname::operating_system(); |
| 460 | |
Alp Toker | 8f2d3f0 | 2014-02-24 10:40:15 +0000 | [diff] [blame] | 461 | # Auxiliary property functions. |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 462 | $host_name = Uname::host_name(); |
| 463 | $domain_name = Uname::domain_name(); |
| 464 | $os_name = Uname::operating_system_name(); |
| 465 | $os_release = Uname::operating_system_release(); |
| 466 | $os_codename = Uname::operating_system_codename(); |
| 467 | $os_description = Uname::operating_system_description(); |
| 468 | |
| 469 | # Meta functions. |
| 470 | @base_names = Uname::base_names(); |
| 471 | @all_names = Uname::all_names(); |
| 472 | $kernel_name = Uname::value( "kernel_name" ); |
| 473 | |
| 474 | =head1 DESCRIPTION |
| 475 | |
| 476 | B<Uname.pm> resembles functionality found in C<POSIX::uname()> function or in C<uname> program. |
| 477 | However, both C<POSIX::uname()> and C</bin/uname> have some disadvantages: |
| 478 | |
| 479 | =over |
| 480 | |
| 481 | =item * |
| 482 | |
| 483 | C<uname> may be not available in some environments, for example, in Windows* OS |
| 484 | (C<uname> may be found in some third-party software packages, like MKS Toolkit or Cygwin, but it is |
| 485 | not a part of OS). |
| 486 | |
| 487 | =item * |
| 488 | |
| 489 | There are many different versions of C<uname>. For example, C<uname> on OS X* does not |
| 490 | recognize options C<-i>, C<-o>, and any long options. |
| 491 | |
| 492 | =item * |
| 493 | |
| 494 | Different versions of C<uname> may report the same property differently. For example, |
| 495 | C<uname> on Linux* OS reports machine as C<i686>, while C<uname> on OS X* reports the same machine as |
| 496 | C<x86>. |
| 497 | |
| 498 | =item * |
| 499 | |
| 500 | C<POSIX::uname()> returns list of values. I cannot recall what is the fourth element of the list. |
| 501 | |
| 502 | =back |
| 503 | |
| 504 | =head2 Base Functions |
| 505 | |
| 506 | Base property functions provide the information as C<uname> program. |
| 507 | |
| 508 | =over |
| 509 | |
| 510 | =item B<kernel_name()> |
| 511 | |
| 512 | Returns the kernel name, as reported by C<POSIX::uname()>. |
| 513 | |
| 514 | =item B<fqdn()> |
| 515 | |
| 516 | Returns the FQDN, fully qualified domain name. On some systems C<POSIX::uname()> reports short node |
| 517 | name (with no domain name), on others C<POSIX::uname()> reports full node name. This |
| 518 | function strive to return FQDN always (by refining C<POSIX::uname()> with |
| 519 | C<Net::Domain::hostfqdn()>). |
| 520 | |
| 521 | =item B<kernel_release()> |
| 522 | |
| 523 | Returns the kernel release string, as reported by C<POSIX::uname()>. Usually the string consists of |
| 524 | several numbers, separated by dots and dashes, but may also include some non-numeric substrings like |
| 525 | "smp". |
| 526 | |
| 527 | =item B<kernel_version()> |
| 528 | |
| 529 | Returns the kernel version string, as reported by C<POSIX::uname()>. It is B<not> several |
| 530 | dot-separated numbers but much longer string describing the kernel. |
| 531 | For example, on Linux* OS it includes build date. |
| 532 | If you look for something identifying the kernel, look at L<kernel_release>. |
| 533 | |
| 534 | =item B<machine()> |
| 535 | |
| 536 | Returns the machine hardware name, as reported by POSIX::uname(). Not reliable. Different OSes may |
| 537 | report the same machine hardware name differently. For example, Linux* OS reports C<i686>, while OS X* |
| 538 | reports C<x86> on the same machine. |
| 539 | |
| 540 | =item B<processor()> |
| 541 | |
| 542 | Returns the processor type. Not reliable. Usually the same as C<machine>. |
| 543 | |
| 544 | =item B<hardware_platform()> |
| 545 | |
| 546 | One of: C<i386> or C<x86_64>. |
| 547 | |
| 548 | =item B<operating_system()> |
| 549 | |
| 550 | One of: C<GNU/Linux>, C<OS X*>, or C<MS Windows>. |
| 551 | |
| 552 | =back |
| 553 | |
Alp Toker | 8f2d3f0 | 2014-02-24 10:40:15 +0000 | [diff] [blame] | 554 | =head2 Auxiliary Functions |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 555 | |
Alp Toker | 8f2d3f0 | 2014-02-24 10:40:15 +0000 | [diff] [blame] | 556 | Auxiliary functions extends base functions with information not reported by C<uname> program. |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 557 | |
Alp Toker | 8f2d3f0 | 2014-02-24 10:40:15 +0000 | [diff] [blame] | 558 | Auxiliary functions collect information from different sources. For example, on OS X*, they may |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 559 | call C<sw_vers> program to find out OS release; on Linux* OS they may parse C</etc/redhat-release> file, |
| 560 | etc. |
| 561 | |
| 562 | =over |
| 563 | |
| 564 | =item B<host_name()> |
| 565 | |
| 566 | Returns host name (FQDN with dropped domain part). |
| 567 | |
| 568 | =item B<domain_name()> |
| 569 | |
| 570 | Returns domain name (FQDN with dropped host part). |
| 571 | |
| 572 | =item B<operating_system_name> |
| 573 | |
| 574 | Name of operating system or name of Linux* OS distribution, like "Fedora" or |
| 575 | "Red Hat Enterprise Linux* OS Server". |
| 576 | |
| 577 | =item B<operating_system_release> |
| 578 | |
| 579 | Release (version) of operating system or Linux* OS distribution. Usually it is a series of |
| 580 | dot-separated numbers. |
| 581 | |
| 582 | =item B<operating_system_codename> |
| 583 | |
| 584 | Codename of operating system release or Linux* OS distribution. For example, Fedora 10 is "Cambridge" |
| 585 | while OS X* 10.4 is "Tiger". |
| 586 | |
| 587 | =item B<operating_system_description> |
| 588 | |
| 589 | Longer string. Usually it includes all the operating system properting mentioned above -- name, |
| 590 | release, codename in parentheses. |
| 591 | |
| 592 | =back |
| 593 | |
| 594 | =head2 Meta Functions |
| 595 | |
| 596 | =over |
| 597 | |
| 598 | =item B<base_names()> |
| 599 | |
| 600 | This function returns the list of base property names. |
| 601 | |
| 602 | =item B<all_names()> |
| 603 | |
| 604 | This function returns the list of all property names. |
| 605 | |
| 606 | =item B<value(> I<name> B<)> |
| 607 | |
| 608 | This function returns the value of the property specified by I<name>. |
| 609 | |
| 610 | =back |
| 611 | |
| 612 | =head1 EXAMPLES |
| 613 | |
| 614 | use Uname; |
| 615 | |
| 616 | print( Uname::string(), "\n" ); |
| 617 | |
| 618 | foreach my $name ( Uname::all_names() ) { |
| 619 | print( "$name=\"" . Uname::value( $name ) . "\"\n" ); |
| 620 | }; # foreach $name |
| 621 | |
| 622 | =head1 SEE ALSO |
| 623 | |
| 624 | L<POSIX::uname>, L<uname>. |
| 625 | |
| 626 | =cut |
| 627 | |
| 628 | # end of file # |
| 629 | |