-
Download Cygwin.
-
Run
setup.ex
e and install the following packages in addition to the default ones:- make
- boost
- libncurses-devel
- pkg-config
- perl
-
Download and compile Protocol Buffers (make sure there are no spaces in the working directory when compiling Protocol Buffers,
make
will fail if there are):$ tar zxvf protobuf-2.4.1.tar.gz $ cd protobuf-2.4.1 $ ./configure $ make $ make install
-
Download and compile Mosh:
$ tar zxvf mosh-1.1.3.tar.gz $ cd mosh-1.1.3 $ ./configure CPPFLAGS="-I/usr/include/ncurses" PKG_CONFIG_PATH=/usr/local/lib/pkgconfig/ $ make $ make install
-
Install the
IO::Pty
Perl module:$ perl -MCPAN -e shell cpan> install IO::Pty
-
Rock’n’roll.
-
-
Save ryantenney/3468305 to your computer and use it in GitHub Desktop.
Compiling Mosh (http://mosh.mit.edu/) under Cygwin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
# Mosh: the mobile shell | |
# Copyright 2012 Keith Winstein | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, either version 3 of the License, or | |
# (at your option) any later version. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
my $MOSH_VERSION = '1.1.94'; | |
use warnings; | |
use strict; | |
use Socket; | |
use Getopt::Long; | |
use Errno qw(EINTR); | |
use IO::Socket::INET; | |
use POSIX qw(_exit tmpnam); | |
$| = 1; | |
my $client = 'mosh-client'; | |
my $server = 'mosh-server'; | |
my $predict = undef; | |
my $port_request = undef; | |
my $ssh = 'ssh'; | |
my $help = undef; | |
my $version = undef; | |
my @cmdline = @ARGV; | |
my $usage = | |
qq{Usage: $0 [options] [--] [user@]host [command...] | |
--client=PATH mosh client on local machine | |
(default: "mosh-client") | |
--server=COMMAND mosh server on remote machine | |
(default: "mosh-server") | |
--predict=adaptive local echo for slower links [default] | |
-a --predict=always use local echo even on fast links | |
-n --predict=never never use local echo | |
-p NUM --port=NUM server-side UDP port | |
--ssh=COMMAND ssh command to run when setting up session | |
(example: "ssh -p 2222") | |
(default: "ssh") | |
--help this message | |
--version version and copyright information | |
Please report bugs to mosh-devel\@mit.edu. | |
Mosh home page: http://mosh.mit.edu\n}; | |
my $version_message = qq{mosh $MOSH_VERSION | |
Copyright 2012 Keith Winstein <mosh-devel\@mit.edu> | |
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>. | |
This is free software: you are free to change and redistribute it. | |
There is NO WARRANTY, to the extent permitted by law.\n}; | |
GetOptions( 'client=s' => \$client, | |
'server=s' => \$server, | |
'predict=s' => \$predict, | |
'port=i' => \$port_request, | |
'a' => sub { $predict = 'always' }, | |
'n' => sub { $predict = 'never' }, | |
'p=i' => \$port_request, | |
'ssh=s' => \$ssh, | |
'help' => \$help, | |
'version' => \$version, | |
'fake-proxy!' => \my $fake_proxy ) or die $usage; | |
die $usage if ( defined $help ); | |
die $version_message if ( defined $version ); | |
if ( defined $predict ) { | |
predict_check( $predict, 0 ); | |
} elsif ( defined $ENV{ 'MOSH_PREDICTION_DISPLAY' } ) { | |
$predict = $ENV{ 'MOSH_PREDICTION_DISPLAY' }; | |
predict_check( $predict, 1 ); | |
} else { | |
$predict = 'adaptive'; | |
predict_check( $predict, 0 ); | |
} | |
if ( defined $port_request ) { | |
if ( $port_request =~ m{^[0-9]+$} | |
and $port_request >= 0 | |
and $port_request <= 65535 ) { | |
# good port | |
} else { | |
die "$0: Server-side port ($port_request) must be within valid range [0..65535].\n"; | |
} | |
} | |
delete $ENV{ 'MOSH_PREDICTION_DISPLAY' }; | |
# Fake-proxy mode is needed to determine a real host address by its alias. | |
# One could use his own ssh_config options to make an alias for host, | |
# e.g. "ssh abcd" may mean "ssh example.com". To find this "example.com" | |
# name, we use a little hack: call ssh with ProxyCommand equals to | |
# "ourself --proxy-command %h" option and receive the real hostname (it is | |
# passed instead of %h placeholder replaced by ssh client). We also dump | |
# all the auxillary traffic through ourself (e.g. responses from mosh-server | |
# like "MOSH CONNECT XXX YYY") to make it available from the client. | |
if ( defined $fake_proxy ) { | |
my ( $host, $port ) = @ARGV; | |
# 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; | |
# Pass IP address info via STDERR. It could be catched from the | |
# client and processed. | |
print STDERR "MOSH IP $ip\n"; | |
# Act like netcat | |
my $sock = IO::Socket::INET->new( PeerAddr => $ip, | |
PeerPort => $port, | |
Proto => "tcp" ) | |
or die "$0: connect to host $ip port $port: $!\n"; | |
defined( my $pid = fork ) or die "$0: fork: $!\n"; | |
if ( $pid == 0 ) { | |
cat($sock, \*STDOUT); | |
$sock->shutdown( 0 ); | |
_exit 0; | |
} | |
$SIG{ 'HUP' } = 'IGNORE'; | |
cat(\*STDIN, $sock); | |
$sock->shutdown( 1 ); | |
waitpid $pid, 0; | |
exit; | |
} | |
if ( scalar @ARGV < 1 ) { | |
die $usage; | |
} | |
my $userhost = shift; | |
my @command = @ARGV; | |
# Count colors | |
open COLORCOUNT, '-|', $client, ('-c') or die "Can't count colors: $!\n"; | |
my $colors = ""; | |
{ | |
local $/ = undef; | |
$colors = <COLORCOUNT>; | |
} | |
close COLORCOUNT or die; | |
chomp $colors; | |
if ( (not defined $colors) | |
or $colors !~ m{^[0-9]+$} | |
or $colors < 0 ) { | |
$colors = 0; | |
} | |
# Run SSH, read password (if asked) and receive mosh server IP, port, key. | |
my @server = ( 'new', '-s' ); | |
push @server, ( '-c', $colors ); | |
if ( defined $port_request ) { | |
push @server, ( '-p', $port_request ); | |
} | |
for ( locale_vars() ) { | |
push @server, ( '-l', $_ ); | |
} | |
if ( @command ) { | |
push @server, '--', @command; | |
} | |
my ( $ip, $port, $key ); | |
my $quoted_self = shell_quote( $0 ); | |
my $tmp = tmpnam(); | |
my $quoted_tmp = shell_quote( $tmp ); | |
# Receive MOSH CONNECT string from mosh-server. Also put IP address | |
# to $tmp file (thanks to --fake-proxy). | |
open P, '-|', $ssh, '-S', 'none', '-o', "ProxyCommand=$quoted_self --fake-proxy -- %h %p 2>$quoted_tmp", '-t', $userhost, '--', $server, @server | |
or die "Cannot exec ssh: $!\n"; | |
while ( <P> ) { | |
chomp; | |
if ( m{^MOSH CONNECT } ) { | |
if ( ( $port, $key ) = m{^MOSH CONNECT (\d+?) ([A-Za-z0-9/+]{22})\s*$} ) { | |
last; | |
} else { | |
die "Bad MOSH CONNECT string: $_\n"; | |
} | |
} else { | |
print "$_\n"; | |
} | |
} | |
close(P); | |
# Now read server's IP address. | |
open P, $tmp or die "Cannot open temporary file $tmp: $!\n"; | |
while ( <P> ) { | |
chomp; | |
if ( m{^MOSH IP } ) { | |
( $ip ) = m{^MOSH IP (\S+)\s*$} or die "Bad MOSH IP string: $_\n"; | |
} | |
} | |
close(P); | |
unlink($tmp); | |
if ( not defined $ip ) { | |
die "$0: Did not find remote IP address (is SSH ProxyCommand disabled?).\n"; | |
} | |
if ( not defined $key or not defined $port ) { | |
die "$0: Did not find mosh server startup message.\n"; | |
} | |
# Now start real mosh client. | |
$ENV{ 'MOSH_KEY' } = $key; | |
$ENV{ 'MOSH_PREDICTION_DISPLAY' } = $predict; | |
# Execute the process $client passing "$client @cmdline |" as a displayable | |
# name (e.g. for "ps" or "top" commands). | |
exec {$client} "$client @cmdline |", $ip, $port; | |
sub predict_check { | |
my ( $predict, $env_set ) = @_; | |
if ( not exists { adaptive => 0, always => 0, never => 0 }->{ $predict } ) { | |
my $explanation = $env_set ? " (MOSH_PREDICTION_DISPLAY in environment)" : ""; | |
print STDERR qq{$0: Unknown mode \"$predict\"$explanation.\n\n}; | |
die $usage; | |
} | |
} | |
sub shell_quote { | |
return join ' ', map { (my $a = $_) =~ s/'/'\\''/g; "'$a'" } @_; | |
} | |
sub locale_vars { | |
my @names = qw[LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION LC_ALL]; | |
my @assignments; | |
for ( @names ) { | |
if ( defined $ENV{ $_ } ) { | |
push @assignments, $_ . q{=} . $ENV{ $_ }; | |
} | |
} | |
return @assignments; | |
} | |
sub cat { | |
my ( $from, $to ) = @_; | |
while ( my $n = $from->sysread( my $buf, 4096 ) ) { | |
next if ( $n == -1 && $! == EINTR ); | |
$n >= 0 or last; | |
$to->write( $buf ) or last; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment