summaryrefslogtreecommitdiff
blob: cb3d4c9bbe6d19a98f9f670bb6e022aa282528fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/usr/bin/env perl 
eval 'echo "Called with something not perl"' && exit 1    # Non-Perl protection.
  if 0;

use strict;
use warnings;
use 5.12.1;

# FILENAME: ssh_multiplex.pl
# CREATED: 02/08/11 12:18:23 by Kent Fredric (kentnl) <kentfredric@gmail.com>
# ABSTRACT: Spawn Background SSH Masters for Gentoo Git Sources

use File::Which qw( which );
use Data::Dump qw( dump );

my $ssh_cmd  = which(qw( ssh ));
my %flag_map = (
  background         => ['-f'],
  no_execute_command => ['-N'],
  no_stdin           => ['-n'],
  control_master     => [ '-o', 'ControlMaster=auto' ],
);

my @pids;

spawn_cmd(
  {
    pids    => \@pids,
    params  => [qw( background no_execute_command no_stdin control_master )],
    connect => 'git@github.com',
    cleanup => sub {
      say "\e[31mConnected to git\@github.com\e[0m";
    },
  }
);

spawn_cmd(
  {
    pids    => \@pids,
    params  => [qw( background no_execute_command no_stdin control_master )],
    connect => 'git@git.overlays.gentoo.org',
    cleanup => sub {
      say "\e[32mConnected to git\@git.overlays.gentoo.org\e[0m";
    },
  }
);

for (@pids) {
  waitpid $_, 0;
}

say "Done.";

exit;

sub map_option {
  my ($option) = @_;
  if ( not exists $flag_map{$option} ) {
    require Carp;
    Carp::croak("Map for $option undefined");
  }
  return @{ $flag_map{$option} };
}

sub map_literal_array {
  my ($literal) = @_;
  return @{$literal};
}

sub map_param {
  my ($param) = @_;
  return map_option($param) if not ref $param;
  return map_literal_array($param) if ref $param eq 'ARRAY';
  require Carp;
  Carp::croak("Unhandled parameter $param");
}

sub spawn_child {
  my (@cmd) = @_;
  local $!;
  local $?;
  local $@;
  my $cleanup = pop @cmd;
  my $pid;
  if ( not defined( $pid = fork() ) ) {
    my (%error) = ( '$!', $!, '$?', $?, '$@', $@ );
    require Carp;
    Carp::croak( 'Forking Failed :( ' . dump \%error );
  }
  if ($pid) {
    return $pid;
  }
  local $!;
  local $?;
  local $@;
  system(@cmd) == 0 or do {
    my (%error) = ( '$!', $!, '$?', $?, '$@', $@ );
    require Carp;
    Carp::croak( 'Running command Failed :( ' . dump \%error );
  };
  $cleanup->();
  exit;
}

sub spawn_cmd {
  my ($args) = @_;
  my @outargs = map { map_param($_) } @{ $args->{'params'} };
  my (@cmd) = ( $ssh_cmd, @outargs, $args->{'connect'} );
  say "Spawning " . dump( \@cmd );
  $args->{cleanup} //= sub {
    say "\e[31mConnected to " . $args->{'connect'} . "\e[0m";
  };
  push @{ $args->{pids} }, grep { defined } spawn_child( @cmd, $args->{cleanup} );
}