/
mosh
executable file
·73 lines (60 loc) · 1.5 KB
/
mosh
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
#!/usr/bin/env perl
use warnings;
use strict;
use Socket;
use IO::Pty;
$|=1;
if ( scalar @ARGV != 3 ) {
die "Usage: $0 [user@]host mosh-client-command mosh-server-command\n";
}
my ( $userhost, $client, $server ) = @ARGV;
my ( $user, $host );
# Get username
if ( $userhost =~ m'(.*?@)(.*)' ) {
( $user, $host ) = ( $1, $2 );
} else {
$user = "";
$host = $userhost;
}
# Resolve hostname
my $packed_ip = gethostbyname $host;
if ( not defined $packed_ip ) {
die "$0: Could not resolve hostname $host\n";
}
my $ip = inet_ntoa $packed_ip;
# Run SSH and read password
my $pty = new IO::Pty;
my $pty_slave = $pty->slave;
$pty_slave->clone_winsize_from( \*STDIN );
my $pid = fork;
die "$0: fork: $!\n" unless ( defined $pid );
if ( $pid == 0 ) { # child
close $pty;
open STDOUT, ">&", $pty_slave->fileno() or die;
open STDERR, ">&", $pty_slave->fileno() or die;
close $pty_slave;
exec {'ssh'} ('ssh', '-t', $user . $ip, $server, $ip);
die "Cannot exec ssh: $!\n";
} else { # server
my ( $port, $key );
$pty->close_slave();
LINE: while ( <$pty> ) {
chomp;
if ( m{^MOSH CONNECT} ) {
if ( ( $port, $key ) = m{^MOSH CONNECT (\d+?) ([A-Za-z0-9/+]{22})\s*$} ) {
last LINE;
} else {
die "Bad MOSH CONNECT string: $_\n";
}
} else {
print "$_\n";
}
}
waitpid $pid, 0;
if ( not defined $port ) {
die "$0: Did not find mosh server startup message.\n";
}
# Now start real mosh client
$ENV{ 'MOSH_KEY' } = $key;
exec {$client} ($client, $ip, $port);
}