# Copyright 1997-2001, Paul Johnson (pjcj@cpan.org)
# This software is free. It is licensed under the same terms as Perl itself.
# The latest version of this software should be available from my homepage:
# http://www.pjcj.net
use strict;
require 5.004;
package Shell::Source;
use vars qw($VERSION);
$VERSION = "0.01";
use Carp;
use FileHandle;
my $shells =
{
csh => "csh -f -c 'source [[file]]; env' |",
tcsh => "tcsh -f -c 'source [[file]]; env' |",
sh => "sh -c '. [[file]]; env' |",
ksh => "ksh -c '. [[file]]; env' |",
zsh => "zsh -c '. [[file]]; env' |",
bash => "bash -norc -noprofile -c '. [[file]]; env' |",
};
sub new
{
my $class = shift;
my $self = { @_ };
croak "Must specify type of shell" unless $self->{shell};
$self->{run} ||= $shells->{$self->{shell}};
croak "Must specify how to run unknown shell $self->{shell}"
unless $self->{run};
push @{$self->{ignore}}, qw( TIMEFMT PWD _ );
bless $self, $class;
$self->run if length $self->{file};
$self
}
sub run
{
my $self = shift;
my $file = shift || $self->{file};
croak "Must specify file to source" unless length $self->{file};
(my $run = $self->{run}) =~ s/\[\[file\]\]/$self->{file}/g;
my $fh = $self->{fh}
= FileHandle->new($run) or croak "Can't run $self->{shell}";
$self->_parse;
$fh->close or croak "Can't close $self->{shell}";
$self
}
sub _parse
{
my $self = shift;
my $fh = $self->{fh}; # FileHandle ready for reading
my $env = 0; # for control of multi-line variables
while (defined(my $line = <$fh>))
{
if ($line =~ /^(\w+)=(.*)$/)
{
$env = 1;
if ((!defined $ENV{$1} || $ENV{$1} ne $2) &&
!grep {$1 eq $_} @{$self->{ignore}})
{
$self->{env}{$1} = $2;
}
}
else
{
push (@{$self->{output}}, $line) unless $env;
}
}
$self
}
sub inherit
{
my $self = shift;
while (my ($key, $val) = each (%{$self->{env}}))
{
$ENV{$key} = $val;
}
}
sub shell
{
my $self = shift;
my $shell = "";
while (my ($key, $val) = each (%{$self->{env}}))
{
$shell .= qq($key="$val"; export $key\n);
}
$shell
}
sub output
{
my $self = shift;
join("\n", @{$self->{output}}) if defined $self->{output}
}
sub env
{
my $self = shift;
$self->{env}
}
1;
__END__
=head1 NAME
Shell::Source - run programs and inherit environment changes
=head1 SYNOPSIS
use Shell::Source;
my $csh = Shell::Source->new(shell => "csh", file => "stuff.csh");
$csh->inherit;
print STDERR $csh->output;
print $csh->shell;
=head1 DESCRIPTION
The Shell::Source allows arbitrary shell scripts, or other programs for
that matter, to be run and their environment to be inherited into a Perl
program.
Begin by creating a Shell::Source object, and specifying the shell it
will use.
If the shell is unknown to the module, you will also need to specify how
to run the shell in such a way that the output is a series of lines of
the form NAME=value. For example, to run a csh script:
my $csh = Shell::Source->new(shell => "csh",
file => "stuff.csh",
run => "csh -f -c 'source [[file]]; env' |");
However, for known shells this is not required. Note that [[file]] will
be replaced with the filename of the program you want to run.
Output from running the program is returned from $csh->output.
Changes made to the environment by running the program may be inherited
by calling $csh->inherit.
The environment changes are available as a hash from $csh->env, or in
Bourne shell syntax from $csh->shell.
=head1 BUGS
Huh?
=head1 VERSION
Version 0.01 - 2nd August 2001
=head1 HISTORY
Created - Wednesday 26th November 1997 09:29:31 pm
=head1 LICENCE
Copyright 1997-2001, Paul Johnson (pjcj@cpan.org)
This software is free. It is licensed under the same terms as Perl itself.
The latest version of this software should be available from my homepage:
http://www.pjcj.net
=cut
syntax highlighted by Code2HTML, v. 0.9.1