aboutsummaryrefslogtreecommitdiff
path: root/ssf
diff options
context:
space:
mode:
authorGuillermo Ramos2023-11-07 12:52:40 +0100
committerGuillermo Ramos2023-11-07 12:52:45 +0100
commitd67aa99ef627fd028da6059ad5610866e6332877 (patch)
treeef51ccc4604980bef6d3c8683fd03db84908c736 /ssf
parentd5d95d418f5959a70f7fe79210562f98c3fad5e9 (diff)
downloadcli-d67aa99ef627fd028da6059ad5610866e6332877.tar.gz
ssf: almost full rewrite with pass support
Diffstat (limited to 'ssf')
-rwxr-xr-xssf86
1 files changed, 46 insertions, 40 deletions
diff --git a/ssf b/ssf
index 2366b29..8915c9a 100755
--- a/ssf
+++ b/ssf
@@ -3,9 +3,11 @@
# Author: Guillermo Ramos <gramos@gramos.me>
# SPDX-License-Identifier: BSD-3-Clause
#
-# Minimalistic SSH connector which uses FZF, the SSH config and the known_hosts file
-# 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.
+# 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".
#
################################################################################
@@ -13,68 +15,72 @@ use strict;
use warnings;
my @hosts;
-my %aliases;
-my $remote_user = $ENV{SSF_REMOTE_USER} || $ENV{USER};
+my $remote_session_name = $ENV{SSF_REMOTE_USER} || $ENV{USER};
-open(my $ssh_config, '<', "$ENV{HOME}/.ssh/config") or die "nope";
-while (my $line = <$ssh_config>) {
- if ($line =~ /^Host ([^#\n]+)(?: # (.*))?$/) {
- push @hosts, split(/ /, $1);
- if (defined $2) {
- $aliases{$_} = $1 foreach split / /, $2;
+foreach my $cfgfile (glob "$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') {
+ @line_hosts = map { { _pat => $_ } } (split /\s/, $value);
+ push @hosts, @line_hosts;
+ } elsif ($key eq 'Match') {
+ @line_hosts = ();
+ } else {
+ $_->{$key} = $value foreach (@line_hosts);
}
}
}
-my $egrep_regex = join "|", grep { $_ =~ /\*/ } @hosts;
-$egrep_regex =~ s/\./\\./g;
-$egrep_regex =~ s/\*/.*/g;
+my @hosts_no_wild = grep { not $_ =~ /\*/ } (map { $_->{_pat} } @hosts);
+my $newlined_hosts = join "\n", sort @hosts_no_wild;
-my $known_hosts = `
- grep -E '$egrep_regex' ~/.ssh/known_hosts |
- cut -f1 -d" " |
- sort -u
-`;
-my $hosts_no_wild = join "\n", grep { not $_ =~ /\*/ } @hosts;
-my $aliases = join "\n", keys %aliases;
-my $prompt = @ARGV ? "@ARGV " : "";
+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 "${known_hosts}$aliases\n$hosts_no_wild" |
- fzf -1 --print-query -q "$prompt"
+ 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
-my $host = $aliases{$hostname} || $hostname; # Resolve alias
# Save the final command to the shell history...?
-#`print -s "ssh $host"`;
+#`print -s "ssh $hostname"`;
+
+`which sshpass && which passh`;
+my @cmd = ($? eq 0 ? 'passh' : 'ssh', $hostname, '-t', "sh -c \"tmux new -As $remote_session_name\"");
-# Special behavior for tmux
if (exists $ENV{TMUX}) {
- my $window_id = `tmux list-windows -F '#{window_index}' -f '#{==:#{window_name},$hostname}'`;
- $window_id =~ s/^\s+|\s+$//g; # Trim whitespace
- if ($window_id ne '') {
- # The window exists; select it instead
- `tmux select-window -t $window_id`;
- } else {
- # The window does not exist; make the connection in the current one
- # and it to the machine we're connecting to
- `tmux rename-window $hostname`;
- system 'ssh', '-t', $host, "sh -c \"tmux new -As $remote_user\"";
- `tmux rename-window '!$hostname'`;
- }
+ `tmux rename-window $hostname`;
+ system 'passh', $hostname, '-t', "sh -c \"tmux new -As $remote_session_name\"";
+ `tmux rename-window '[$hostname]'`;
} else {
- exec 'ssh', '-t', $host, "sh -c \"tmux new -As $remote_user\"";
+ exec 'passh', $hostname, '-t', "sh -c \"tmux new -As $remote_session_name\"";
}