about summary refs log tree commit diff
path: root/perl
diff options
context:
space:
mode:
Diffstat (limited to 'perl')
-rw-r--r--perl/Makefile.am2
-rw-r--r--perl/lib/Nix/SSH.pm52
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;