Skip to content

Commit be07468

Browse files
committed
add shell CLI option
1 parent 3751291 commit be07468

File tree

4 files changed

+59
-29
lines changed

4 files changed

+59
-29
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,13 @@ You can search hosts or hostname using repectively `F1` amd `F4` to jump directl
8888

8989
### CLI mode
9090

91-
It is also possible to use s1h as a CLI to copy files around:
91+
It is also possible to use `s1h` as a CLI to shell and copy files.
92+
This approach might be more convenient if you rely on shell history to pass things around.
93+
Mostly this approach helps with password managements.
9294
```
9395
s1h cp [hos1:]/path1 [hos2:]/path2
96+
s1h shell hos1
9497
```
95-
Which might be more convenient if you rely on shell history to pass things around.
9698

9799
### What about password?
98100

cmd/s1h/main.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ func main() {
6565
removeCmd := flag.NewFlagSet("remove", flag.ExitOnError)
6666
removeCmd.StringVar(&hostname, "hostname", "", "The hostname to remove")
6767
err := removeCmd.Parse(os.Args[2:])
68+
if err != nil {
69+
fmt.Println("Error remote:", err)
70+
os.Exit(1)
71+
}
6872
if hostname == "" {
6973
fmt.Println("Please provide the hostname to remove.")
7074
os.Exit(1)
@@ -92,6 +96,17 @@ func main() {
9296
fmt.Println("Error while copying: ", err.Error())
9397
os.Exit(1)
9498
}
99+
case "shell":
100+
if len(os.Args) != 3 {
101+
fmt.Println("Missing args: s1h shell host")
102+
os.Exit(1)
103+
}
104+
configs := loadConfigs()
105+
err := cli.Shell(configs, os.Args[2])
106+
if err != nil {
107+
fmt.Println("Error while copying: ", err.Error())
108+
os.Exit(1)
109+
}
95110
default:
96111
fmt.Println("Unknown command. Expected 'upsert' or 'remove'.")
97112
os.Exit(1)

internal/cli/cp.go

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -30,59 +30,72 @@ func extractPath(endpoint string) string {
3030
return endpoint[n+1:]
3131
}
3232

33-
func Copy(configs []ssh.SSHConfig, first, second string) error {
34-
firstHost := extractHost(first)
35-
secondHost := extractHost(second)
33+
func findConfig(configs []ssh.SSHConfig, host string) (ssh.SSHConfig, bool) {
34+
for i := range configs {
35+
if configs[i].Host == host {
36+
return configs[i], true
37+
}
38+
}
39+
return ssh.SSHConfig{}, false
40+
}
41+
42+
func Copy(configs []ssh.SSHConfig, left, right string) error {
43+
leftHost := extractHost(left)
44+
rightHost := extractHost(right)
3645

3746
var leftClient, rightClient *cssh.Client
3847
var leftConfig, rightConfig ssh.SSHConfig
3948
var err error
40-
if firstHost != "" { // remote -> local | remote
41-
for i := range configs {
42-
if configs[i].Host == firstHost {
43-
leftConfig = configs[i]
44-
break
45-
}
49+
if leftHost != "" { // remote -> local | remote
50+
var has bool
51+
leftConfig, has = findConfig(configs, leftHost)
52+
if !has {
53+
return fmt.Errorf("config %s not found", leftHost)
4654
}
4755
leftClient, err = ssh.SSHClient(leftConfig)
4856
if err != nil {
4957
return err
5058
}
5159

52-
if secondHost != "" { // remote -> remote
53-
for i := range configs {
54-
if configs[i].Host == secondHost {
55-
rightConfig = configs[i]
56-
break
57-
}
60+
if rightHost != "" { // remote -> remote
61+
rightConfig, has = findConfig(configs, rightHost)
62+
if !has {
63+
return fmt.Errorf("config %s not found", rightHost)
5864
}
5965
rightClient, err = ssh.SSHClient(rightConfig)
6066
if err != nil {
6167
return err
6268
}
6369
tempPath := filepath.Join(os.TempDir(),
64-
removeSlashes("s1h"+first+second))
65-
err = ssh.DownloadFile(leftClient, extractPath(firstHost), tempPath)
70+
removeSlashes("s1h"+left+right))
71+
err = ssh.DownloadFile(leftClient, extractPath(leftHost), tempPath)
6672
if err != nil {
6773
return err
6874
}
6975
defer os.Remove(tempPath)
70-
err = ssh.UploadFile(rightClient, tempPath, extractPath(secondHost))
76+
err = ssh.UploadFile(rightClient, tempPath, extractPath(rightHost))
7177
} else { // remote -> local
72-
err = ssh.DownloadFile(leftClient, extractPath(firstHost), second)
78+
err = ssh.DownloadFile(leftClient, extractPath(leftHost), right)
7379
}
7480
} else { // local -> remote
75-
for i := range configs {
76-
if configs[i].Host == secondHost {
77-
rightConfig = configs[i]
78-
break
79-
}
81+
var has bool
82+
rightConfig, has = findConfig(configs, rightHost)
83+
if !has {
84+
return fmt.Errorf("config %s not found", rightHost)
8085
}
8186
rightClient, err = ssh.SSHClient(rightConfig)
8287
if err != nil {
8388
return err
8489
}
85-
err = ssh.UploadFile(rightClient, extractPath(firstHost), second)
90+
err = ssh.UploadFile(rightClient, left, extractPath(right))
8691
}
8792
return err
8893
}
94+
95+
func Shell(configs []ssh.SSHConfig, host string) error {
96+
cfg, has := findConfig(configs, host)
97+
if !has {
98+
return fmt.Errorf("config %s not found", host)
99+
}
100+
return ssh.ExecuteSSHShell(cfg)
101+
}

internal/ssh/ssh.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,12 +283,12 @@ func UploadFile(client *ssh.Client, localFile, remotePath string) error {
283283
info, err := sftpClient.Stat(remotePath)
284284
if err == nil {
285285
if info.IsDir() {
286-
remotePath = filepath.Join(localFile, filepath.Base(remotePath))
286+
remotePath = filepath.Join(remotePath, filepath.Base(localFile))
287287
}
288288
}
289289
dstFile, err := sftpClient.Create(remotePath)
290290
if err != nil {
291-
return fmt.Errorf("failed to create remote file: %w", err)
291+
return fmt.Errorf("failed to create remote file %s: %w", remotePath, err)
292292
}
293293
defer dstFile.Close()
294294

0 commit comments

Comments
 (0)