Changed update-system to be less verbose
[clearscm.git] / bin / tunnel.pl
1 #!/usr/bin/perl
2
3 =pod
4
5 =head1 NAME $RCSfile: tunnel.pl,v $
6
7 Set up a tunnel for emailing
8
9 =head1 VERSION
10
11 =over
12
13 =item Author
14
15 Andrew DeFaria <Andrew@ClearSCM.com>
16
17 =item Revision:
18
19 $Revision: 1.0 $
20
21 =item Created:
22
23 Wed 19 Aug 2020 09:09:09 AM MST
24
25 =item Modified:
26
27 $Date: $
28
29 =back
30
31 =head1 SYNOPSIS
32
33   Usage: tunnel.pl [-u|sage] [-h|elp] [-ve|rbose] [-d|ebug]
34
35   Where:
36     -u|sage:      Displays this usage
37     -h|elp:       Display full help
38     -ve|rbose:    Be verbose
39     -d|ebug:      Output debug messages
40     -host1:       First host for tunnel (Default: localhost)
41     -port1:       Port for host1
42     -host2:       Second host for tunnel (Default: defaria.com)
43     -port2:       Port for host2
44     -a|nnounce:   Whether to announce startup (Default false)
45     -ap|pend      Append to logfile (Default: Noappend)
46     -maxtretries: Maximum number of retry attempt to reestablish tunnel
47                   (Default 3)
48     -nodaemon:    Whether to go into daemon mode (Default: Daemon mode)
49
50 =head1 DESCRIPTION
51
52 This script sets up an SSH tunnel for the purposes of emailing.
53
54 =cut
55
56 use strict;
57 use warnings;
58
59 use File::Temp qw(tempfile);
60 use FindBin;
61 use Getopt::Long;
62 use Net::OpenSSH;
63 use POSIX ':sys_wait_h';
64
65 use lib "$FindBin::Bin/../lib";
66
67 use Pod::Usage;
68
69 use Display;
70 use Logger;
71 use Speak;
72 use Utils;
73
74 my $VERSION  = '$Revision: 1.0 $';
75   ($VERSION) = ($VERSION =~ /\$Revision: (.*) /);
76
77 my %opts = (
78   usage      => sub { pod2usage },
79   help       => sub { pod2usage (-verbose => 2)},
80   verbose    => sub { set_verbose },
81   debug      => sub { set_debug },
82   host1      => 'localhost',
83   port1      => 1025,
84   host2      => 'defaria.com',
85   port2      => 25,
86   remotehost => 'defaria.com',
87   maxretries => 3,
88 );
89
90 # Perlcritic complains if $DB::OUT is used only once.
91 no warnings;
92 $opts{daemon} = 1 unless defined $DB::OUT;
93 use warnings;
94
95 my ($log, $ssh);
96
97 sub Report ($;$) {
98   my ($msg, $err) = @_;
99
100   speak $msg, $log;
101
102   if ($err) {
103     $log->err($msg, $err);
104   } else {
105     $log->err($msg);
106   } # if
107
108   return;
109 } # Report
110
111 sub interrupt {
112    Report "Tunnel killed unexpectedly", 1;
113
114    kill 'INT', $ssh->get_master_pid;
115
116    return;
117 } # interrupt
118
119 sub tunnel() {
120   my $tunnelStr = "-NL$opts{host1}:$opts{port1}:$opts{host2}:$opts{port2}";
121
122   my $retryattempts = 0;
123
124 RETRY:
125   my ($fh, $filename) = tempfile;
126
127   $ssh = Net::OpenSSH->new(
128     $opts{remotehost},
129     master_opts         => $tunnelStr,
130     default_stderr_file => $filename
131   );
132
133   Report("Unable to establish ssh tunnel " . $ssh->error, 1) if $ssh->error;
134
135   # Check to see if address is already in use
136   my @lines = <$fh>;
137
138   close $fh;
139
140   unlink $filename;
141
142   if (grep { /address already in use/i } @lines) {
143     Report 'Unable to start tunnel - Address already in use', 1;
144   } else {
145     my $msg  = 'Ssh tunnel ';
146        $msg .= $retryattempts ? 'reestablished' : 'established';
147
148     speak $msg, $log if $opts{announce};
149
150     $log->msg($msg);
151
152     # Reset retry attempts since we reestablished the tunnel
153     $retryattempts = 0 if $retryattempts;
154
155     # Wait for master to exit
156     waitpid($ssh->get_master_pid, WUNTRACED);
157
158     Report("Ssh tunnel terminated unexpectedly - Maximum retry count hit ($opts{maxretries}) - giving up", 1)
159       if $retryattempts++ >= $opts{maxretries};
160
161     undef $ssh;
162
163     goto RETRY;
164   } # if
165
166   return;
167 } # tunnel
168
169 ## Main
170 GetOptions (
171   \%opts,
172   'usage',
173   'help',
174   'verbose',
175   'debug',
176   'host1',
177   'host2',
178   'port1',
179   'port2',
180   'announce!',
181   'maxretries=i',
182   'daemon!',
183   'append',
184 ) || Usage;
185
186 $log = Logger->new(
187   path        => '/var/local/log',
188   name        => "$Logger::me",
189   timestamped => 'yes',
190   append      => $opts{append},
191 );
192
193 $log->msg("$FindBin::Script v$VERSION");
194
195 $SIG{INT} = $SIG{TERM} = \&interrupt;
196
197 EnterDaemonMode unless $opts{daemon} and get_debug;
198
199 tunnel;