diff options
Diffstat (limited to 'perl')
-rw-r--r-- | perl/Makefile.am | 2 | ||||
-rw-r--r-- | perl/lib/Nix/SSH.pm | 52 |
2 files changed, 53 insertions, 1 deletions
diff --git a/perl/Makefile.am b/perl/Makefile.am index d41340af03eb..e6a5f9b5e71c 100644 --- a/perl/Makefile.am +++ b/perl/Makefile.am @@ -2,7 +2,7 @@ perlversion := $(shell perl -e 'use Config; print $$Config{version};') perlarchname := $(shell perl -e 'use Config; print $$Config{archname};') perllibdir = $(libdir)/perl5/site_perl/$(perlversion)/$(perlarchname) -PERL_MODULES = lib/Nix/Store.pm lib/Nix/Manifest.pm lib/Nix/GeneratePatches.pm lib/Nix/Config.pm.in +PERL_MODULES = lib/Nix/Store.pm lib/Nix/Manifest.pm lib/Nix/GeneratePatches.pm lib/Nix/SSH.pm lib/Nix/Config.pm.in all: $(PERL_MODULES:.in=) diff --git a/perl/lib/Nix/SSH.pm b/perl/lib/Nix/SSH.pm new file mode 100644 index 000000000000..68f4a628b072 --- /dev/null +++ b/perl/lib/Nix/SSH.pm @@ -0,0 +1,52 @@ +use strict; +use File::Temp qw(tempdir); + +our @sshOpts = split ' ', ($ENV{"NIX_SSHOPTS"} or ""); + +push @sshOpts, "-x"; + +my $sshStarted = 0; +my $sshHost; + +# Open a master SSH connection to `host', unless there already is a +# running master connection (as determined by `-O check'). +sub openSSHConnection { + my ($host) = @_; + die if $sshStarted; + $sshHost = $host; + return 1 if system("ssh $sshHost @sshOpts -O check 2> /dev/null") == 0; + + my $tmpDir = tempdir("nix-ssh.XXXXXX", CLEANUP => 1, TMPDIR => 1) + or die "cannot create a temporary directory"; + + push @sshOpts, "-S", "$tmpDir/control"; + + # Start the master. We can't use the `-f' flag (fork into + # background after establishing the connection) because then the + # child continues to run if we are killed. So instead make SSH + # print "started" when it has established the connection, and wait + # until we see that. + open SSHPIPE, "ssh $sshHost @sshOpts -M -N -o LocalCommand='echo started' -o PermitLocalCommand=yes |" or die; + + while (<SSHPIPE>) { + chomp; + if ($_ eq "started") { + $sshStarted = 1; + return 1; + } + } + + return 0; +} + +# Tell the master SSH client to exit. +sub closeSSHConnection { + if ($sshStarted) { + system("ssh $sshHost @sshOpts -O exit 2> /dev/null") == 0 + or warn "unable to stop SSH master: $?"; + } +} + +END { my $saved = $?; closeSSHConnection; $? = $saved; } + +return 1; |