use strict; package Probe::Perl; { $Probe::Perl::VERSION = '0.03'; } # TODO: cache values derived from launching an external perl process # TODO: docs refer to Config.pm and $self->{config} use Config; use File::Spec; sub new { my $class = shift; my $data = shift || {}; return bless( $data, $class ); } sub config { my ($self, $key) = (shift, shift); if (@_) { unless (ref $self) { die "Can't set config values via $self->config(). Use $self->new() to create a local view"; } $self->{$key} = shift; } return ref($self) && exists $self->{$key} ? $self->{$key} : $Config{$key}; } sub config_revert { my $self = shift; die "Can't use config_revert() as a class method" unless ref($self); delete $self->{$_} foreach @_; } sub perl_version { my $self = shift; # Check the current perl interpreter # It's much more convenient to use $] here than $^V, but 'man # perlvar' says I'm not supposed to. Bloody tyrant. return $^V ? $self->perl_version_to_float(sprintf( "%vd", $^V )) : $]; } sub perl_version_to_float { my ($self, $version) = @_; $version =~ s/\./../; # Double up the first dot so the output has one dot remaining $version =~ s/\.(\d+)/sprintf( '%03d', $1 )/eg; return $version; } sub _backticks { my $perl = shift; return unless -e $perl; my $fh; eval {open $fh, '-|', $perl, @_ or die $!}; if (!$@) { return <$fh> if wantarray; my $tmp = do {local $/=undef; <$fh>}; return $tmp; } # Quoting only happens on the path to perl - I control the rest of # the args and they don't need quoting. if ($^O eq 'MSWin32') { $perl = qq{"$perl"} if $perl =~ m{^[\w\\]+$}; } else { $perl =~ s{([^\w\\])}{\\$1}g; } return `$perl @_`; } sub perl_is_same { my ($self, $perl) = @_; return _backticks($perl, qw(-MConfig=myconfig -e print -e myconfig)) eq Config->myconfig; } sub find_perl_interpreter { my $self = shift; return $^X if File::Spec->file_name_is_absolute($^X); my $exe = $self->config('exe_ext'); my $thisperl = $^X; if ($self->os_type eq 'VMS') { # VMS might have a file version at the end $thisperl .= $exe unless $thisperl =~ m/$exe(;\d+)?$/i; } elsif (defined $exe) { $thisperl .= $exe unless $thisperl =~ m/$exe$/i; } foreach my $perl ( $self->config('perlpath'), map( File::Spec->catfile($_, $thisperl), File::Spec->path() ) ) { return $perl if -f $perl and $self->perl_is_same($perl); } return; } # Determine the default @INC for this Perl sub perl_inc { my $self = shift; local $ENV{PERL5LIB}; # this is not considered part of the default. my $perl = $self->find_perl_interpreter(); my @inc = _backticks($perl, qw(-l -e print -e for -e @INC)); chomp @inc; return @inc; } { my %OSTYPES = qw( aix Unix bsdos Unix dgux Unix dynixptx Unix freebsd Unix linux Unix hpux Unix irix Unix darwin Unix machten Unix next Unix openbsd Unix netbsd Unix dec_osf Unix svr4 Unix svr5 Unix sco_sv Unix unicos Unix unicosmk Unix solaris Unix sunos Unix cygwin Unix os2 Unix dos Windows MSWin32 Windows os390 EBCDIC os400 EBCDIC posix-bc EBCDIC vmesa EBCDIC MacOS MacOS VMS VMS VOS VOS riscos RiscOS amigaos Amiga mpeix MPEiX ); sub os_type { my $class = shift; return $OSTYPES{shift || $^O}; } } 1; __END__ =head1 NAME Probe::Perl - Information about the currently running perl =head1 VERSION version 0.03 =head1 SYNOPSIS use Probe::Perl; $p = Probe::Perl->new(); # Version of this perl as a floating point number $ver = $p->perl_version(); $ver = Probe::Perl->perl_version(); # Convert a multi-dotted string to a floating point number $ver = $p->perl_version_to_float($ver); $ver = Probe::Perl->perl_version_to_float($ver); # Check if the given perl is the same as the one currently running $bool = $p->perl_is_same($perl_path); $bool = Probe::Perl->perl_is_same($perl_path); # Find a path to the currently-running perl $path = $p->find_perl_interpreter(); $path = Probe::Perl->find_perl_interpreter(); # Get @INC before run-time additions @paths = $p->perl_inc(); @paths = Probe::Perl->perl_inc(); # Get the general type of operating system $type = $p->os_type(); $type = Probe::Perl->os_type(); # Access Config.pm values $val = $p->config('foo'); $val = Probe::Perl->config('foo'); $p->config('foo' => 'bar'); # Set locally $p->config_revert('foo'); # Revert =head1 DESCRIPTION This module provides methods for obtaining information about the currently running perl interpreter. It originally began life as code in the C project, but has been externalized here for general use. =head1 METHODS =over 4 =item new() Creates a new Probe::Perl object and returns it. Most methods in the Probe::Perl packages are available as class methods, so you don't always need to create a new object. But if you want to create a mutable view of the C data, it's necessary to create an object to store the values in. =item config( $key [, $value] ) Returns the C value associated with C<$key>. If C<$value> is also specified, then the value is set to C<$value> for this view of the data. In this case, C must be called as an object method, not a class method. =item config_revert( $key ) Removes any user-assigned value in this view of the C data. =item find_perl_interpreter( ) Returns the absolute path of this perl interpreter. This is actually sort of a tricky thing to discover sometimes - in these cases we use C to verify. =item perl_version( ) Returns the version of this perl interpreter as a perl-styled version number using C. Uses C<$^V> if your perl is recent enough, otherwise uses C<$]>. =item perl_version_to_float( $version ) Formats C<$version> as a perl-styled version number like C<5.008001>. =item perl_is_same( $perl ) Given the name of a perl interpreter, this method determines if it has the same configuration as the one represented by the current perl instance. Usually this means it's exactly the same =item perl_inc( ) Returns a list of directories in this perl's C<@INC> path, I any entries from C, C<$ENV{PERL5LIB}>, or C<-I> switches are added. =item os_type( [$osname] ) Returns a generic OS type (e.g. "Unix", "Windows", "MacOS") for the given OS name. If no OS name is given it uses the value in $^O, which is the same as $Config{osname}. =back =head1 AUTHOR Randy W. Sims Based partly on code from the Module::Build project, by Ken Williams and others. =head1 COPYRIGHT Copyright 2005 Ken Williams and Randy Sims. All rights reserved. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut