#!/usr/bin/env ruby require 'fileutils' include FileUtils::Verbose require 'tins/go' include Tins::GO require 'utils' SSH_CONFIG = <<SSH_CONFIG_END # ~/.ssh/config Host * ForwardX11 = yes ControlMaster auto ControlPath ~/.ssh/%r@%h:%p.sock SSH_CONFIG_END def usage puts <<EOT Usage: #{File.basename($0)} [OPTS] [user@]remote[:port]" OPTS is one of -N list all session names on the specified remote -n NAME name of the multiplexer session to attach to (defaults to $USER) -t [HOST[:PORT]] host:port to tunnel if different from LOCALPORT -m screen|tmux use sshscreen or tmux as a terminal multiplexer -l LOCALPORT the localport to forward to -C (ssh|rc)-default|rc output ssh or rc config file -h to display this help EOT exit 1 end config = Utils::Config::ConfigFile.new arguments = ARGV opts = go 'l:t:n:C:m:hN', arguments case opts['C'] when 'ssh-default' puts SSH_CONFIG; exit when 'rc-default' puts config.to_ruby; exit when 'rc' config.configure_from_paths puts config.to_ruby; exit end config.configure_from_paths usage if opts['h'] or arguments.size != 1 if multiplexer = opts['m'] config.ssh_tunnel.terminal_multiplexer = multiplexer end user_remote = arguments.shift user, remote, rport = case user_remote when /\A(?:([^@:]+)@)?([^@:]+)(?::(\d+))?\Z/ user = $1 || ENV['USER'] user.to_s.empty? and fail "user required to login" [ user, $2, $3 || '22' ] else usage end lport = opts['l'] tunnel, tport = nil, nil if tunnel_port = opts['t'] case tunnel_port when /\A([^:]+)(?::(\d+))?\Z/ tunnel, tport = $1, $2 || '22' lport ||= tport else usage end else tunnel, tport = 'localhost', lport end ssh_dir = File.expand_path('~/.ssh') mkdir_p ssh_dir sock_file = "#{ssh_dir}/#{user}@#{remote}:#{rport}.sock" if env_user = ENV['USER'] opts['n'] ||= env_user else opts['n'] ||= 'session' end if opts['N'] exec "ssh -p #{rport} -S #{sock_file} #{user}@#{remote} #{config.ssh_tunnel.multiplexer_list}" else env = [] File.exist? sock_file and rm_f sock_file r = config.ssh_tunnel.copy_paste.full? do |t| env << "COPY_REMOTE_HOST_PORT='#{t.bind_address}:#{t.port}'" " -R #{t}" end env *= ' ' if lport exec "ssh -p #{rport} -Mt -L localhost:#{lport}:#{tunnel}:#{tport}#{r} "\ "-S #{sock_file} #{user}@#{remote} "\ "'env #{env} #{config.ssh_tunnel.multiplexer_new(opts['n'])} || "\ "#{config.ssh_tunnel.multiplexer_attach(opts['n'])}'" else exec "ssh -p #{rport} -Mt -S #{sock_file} #{user}@#{remote}#{r} "\ "'env #{env} #{config.ssh_tunnel.multiplexer_new(opts['n'])} || "\ "#{config.ssh_tunnel.multiplexer_attach(opts['n'])}'" end end