# 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