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