Skip to content

Commit b863674

Browse files
committed
Asynchronously read ssh configuration
1 parent 9b02a59 commit b863674

2 files changed

Lines changed: 57 additions & 32 deletions

File tree

kittens/ssh/main.go

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"archive/tar"
77
"bytes"
88
"compress/gzip"
9+
"context"
910
"encoding/base64"
1011
"encoding/json"
1112
"errors"
@@ -620,7 +621,7 @@ func change_colors(color_scheme string) (ans string, err error) {
620621
return
621622
}
622623

623-
func run_ssh(ssh_args, server_args, found_extra_args []string, ssh_config *SSHConfig) (rc int, err error) {
624+
func run_ssh(ssh_args, server_args, found_extra_args []string, ssh_config_channel <-chan *SSHConfig) (rc int, err error) {
624625
go shell_integration.Data()
625626
go RelevantKittyOpts()
626627
defer func() {
@@ -630,14 +631,11 @@ func run_ssh(ssh_args, server_args, found_extra_args []string, ssh_config *SSHCo
630631
}
631632
}()
632633
cmd := append([]string{SSHExe()}, ssh_args...)
633-
cd := connection_data{remote_args: server_args[1:], ssh_config: ssh_config}
634+
cd := connection_data{remote_args: server_args[1:]}
634635
hostname := server_args[0]
635636
if len(cd.remote_args) == 0 {
636637
cmd = append(cmd, "-t")
637638
}
638-
if cd.ssh_config != nil && cd.ssh_config.RemoteCommand != "" {
639-
cmd = append(cmd, "-o", "RemoteCommand=none")
640-
}
641639
insertion_point := len(cmd)
642640
cmd = append(cmd, "--", hostname)
643641
uname, hostname_for_match := get_destination(hostname)
@@ -780,6 +778,12 @@ func run_ssh(ssh_args, server_args, found_extra_args []string, ssh_config *SSHCo
780778
}
781779
}
782780
defer cleanup()
781+
// Receive ssh config
782+
ssh_config := <-ssh_config_channel
783+
if ssh_config != nil && ssh_config.RemoteCommand != "" {
784+
cmd = slices.Insert(cmd, insertion_point, "-o", "RemoteCommand=none")
785+
}
786+
cd.ssh_config = ssh_config
783787
err = get_remote_command(&cd)
784788
if err != nil {
785789
return 1, err
@@ -856,17 +860,18 @@ func main(cmd *cli.Command, o *Options, args []string) (rc int, err error) {
856860
if passthrough {
857861
return 1, unix.Exec(SSHExe(), utils.Concat([]string{"ssh"}, ssh_args, server_args), os.Environ())
858862
}
859-
ssh_config, err := LoadSSHConfig(server_args[0])
860-
if err != nil {
861-
return 1, err
862-
}
863+
864+
ctx, cancel := context.WithCancel(context.Background())
865+
defer cancel()
866+
ssh_config_channel := ReadSSHConfig(ctx, server_args[0])
867+
863868
if os.Getenv("KITTY_WINDOW_ID") == "" || os.Getenv("KITTY_PID") == "" {
864869
return 1, fmt.Errorf("The SSH kitten is meant to run inside a kitty window")
865870
}
866871
if !tty.IsTerminal(os.Stdin.Fd()) {
867872
return 1, fmt.Errorf("The SSH kitten is meant for interactive use only, STDIN must be a terminal")
868873
}
869-
return run_ssh(ssh_args, server_args, found_extra_args, ssh_config)
874+
return run_ssh(ssh_args, server_args, found_extra_args, ssh_config_channel)
870875
}
871876

872877
func EntryPoint(parent *cli.Command) {

kittens/ssh/utils.go

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package ssh
55
import (
66
"bufio"
77
"bytes"
8+
"context"
89
"fmt"
910
"os/exec"
1011
"regexp"
@@ -199,34 +200,53 @@ type SSHConfig struct {
199200
RemoteCommand string
200201
}
201202

202-
func LoadSSHConfig(hostname string) (config *SSHConfig, err error) {
203-
cmd_args := []string{SSHExe(), hostname, "-G"}
204-
cmd := exec.Command(cmd_args[0], cmd_args[1:]...)
205-
var stdout, stderr bytes.Buffer
206-
cmd.Stdout = &stdout
207-
cmd.Stderr = &stderr
208-
_ = cmd.Run()
203+
// ReadSSHConfig Asynchronously read ssh configuration
204+
func ReadSSHConfig(ctx context.Context, hostname string) <-chan *SSHConfig {
205+
ch := make(chan *SSHConfig, 1)
209206

210-
text := stdout.String()
211-
scanner := bufio.NewScanner(strings.NewReader(text))
207+
go func() {
208+
defer close(ch)
212209

213-
config = &SSHConfig{}
214-
for scanner.Scan() {
215-
line := scanner.Text()
216-
i := strings.IndexByte(line, ' ')
217-
if i <= 0 {
218-
continue
210+
cmd_args := []string{SSHExe(), hostname, "-G"}
211+
cmd := exec.CommandContext(ctx, cmd_args[0], cmd_args[1:]...)
212+
var stdout, stderr bytes.Buffer
213+
cmd.Stdout = &stdout
214+
cmd.Stderr = &stderr
215+
if err := cmd.Run(); err != nil {
216+
return
219217
}
220218

221-
key, val := line[:i], line[i+1:]
222-
switch key {
223-
case "remotecommand":
224-
if val != "none" {
225-
config.RemoteCommand = val
219+
text := stdout.String()
220+
scanner := bufio.NewScanner(strings.NewReader(text))
221+
222+
config := &SSHConfig{}
223+
for scanner.Scan() {
224+
select {
225+
case <-ctx.Done():
226+
return
227+
default:
228+
}
229+
line := scanner.Text()
230+
i := strings.IndexByte(line, ' ')
231+
if i <= 0 {
232+
continue
233+
}
234+
235+
key, val := line[:i], line[i+1:]
236+
switch key {
237+
case "remotecommand":
238+
if val != "none" {
239+
config.RemoteCommand = val
240+
}
226241
}
227242
}
228-
}
229-
return config, nil
243+
select {
244+
case <-ctx.Done():
245+
return
246+
case ch <- config:
247+
}
248+
}()
249+
return ch
230250
}
231251

232252
type SSHVersion struct{ Major, Minor int }

0 commit comments

Comments
 (0)