#!/usr/bin/env perl # # Author: Guillermo Ramos # SPDX-License-Identifier: BSD-3-Clause # # Minimalistic SSH connector which uses FZF and the SSH config to show a # reasonable list of machines to connect to. Then it starts or attaches to # a remote tmux session named as the current user. It also supports passwords # stored in `pass`, using the wrappers "passh" (provided in this repo" and # "sshpass". # ################################################################################ use strict; use warnings; my @hosts; my $remote_session_name = $ENV{SSF_REMOTE_USER} || $ENV{USER}; foreach my $cfgfile (glob("$ENV{HOME}/.ssh/config.d/*"), "$ENV{HOME}/.ssh/config") { open(my $ssh_config, '<', $cfgfile) or die "nope"; my @line_hosts; while (my $line = <$ssh_config>) { my ($key, $value); if ($line =~ /^\s*([A-Z][a-zA-Z]+)\s+([^#\n]+)/) { $key = $1; $value = $2; } next unless defined $key; if ($key eq 'Host') { if ($value =~ /"/) { @line_hosts = ({ _pat => $value }); } else { @line_hosts = map { { _pat => $_ } } (split /\s/, $value); } push @hosts, @line_hosts; } elsif ($key eq 'Match') { @line_hosts = (); } else { $_->{$key} = $value foreach (@line_hosts); } } } my @hosts_no_wild = grep { not $_ =~ /\*/ } (map { $_->{_pat} } @hosts); my %tmp = map { $_, 1 } @hosts_no_wild; my @hosts_no_rep = keys %tmp; my $newlined_hosts = join "\n", sort @hosts_no_rep; my $fzf_cmd = 'fzf'; if (exists $ENV{TMUX}) { if (`which fzf-tmux`) { $fzf_cmd = 'fzf-tmux'; } } my $prompt = @ARGV ? "$ARGV[0] " : ""; my $selection = ` echo -n "$newlined_hosts" | $fzf_cmd -1 --print-query -q "$prompt" `; my $retval = $? >> 8; my @lines = split "\n", $selection; my $hostname; if ($retval == 0) { # 0: normal exit; a host has been selected $hostname = $lines[1]; } elsif ($retval == 1) { # 1: no match; pick user input $hostname = $lines[0]; } else { # either 2 (error) or 130 (interrupted wth C-c or ESC) exit $retval; } $hostname =~ s/^\s+|\s+$//g; # Trim whitespace # Save the final command to the shell history...? #`print -s "ssh $hostname"`; `which sshpass && which passh`; my @cmd = ($? eq 0 ? 'passh' : 'ssh', $hostname, '-t', "sh -c \"tmux new -As $remote_session_name\""); if (exists $ENV{TMUX}) { `tmux rename-window $hostname`; system 'passh', $hostname, '-t', "sh -c \"tmux new -As $remote_session_name\""; `tmux rename-window '[$hostname]'`; } else { exec 'passh', $hostname; }