/
shell.go
80 lines (75 loc) · 2.26 KB
/
shell.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package handlers
import (
"log"
"os/exec"
"strings"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/terminal"
"github.com/grt1st/sshjumper/conf"
"github.com/grt1st/sshjumper/utils"
)
// HandlePty 处理 shell 类型的请求,处理为交互式命令行
func HandlePty(channel ssh.Channel, serverConn *ssh.ServerConn) {
_, _ = channel.Write([]byte(utils.WordsWelcome))
_, _ = channel.Write(utils.LogSprintf(utils.WordsInfo, serverConn.User(), "我们经常在正确的事情和容易的事情之间做选择.").Bytes())
term := terminal.NewTerminal(channel, "> ")
defer channel.Close()
for {
// get user input
line, err := term.ReadLine()
if err != nil {
break
}
// parse input
line = strings.TrimSpace(line)
if line == "" {
continue
}
command := utils.NewCommand(line)
switch command.Name {
case "ssh":
var defaultChoice bool
var host string
if len(command.Peaces) == 0 {
defaultChoice = true
} else {
host = command.Peaces[0]
}
host, sshConfig, err := conf.GetRemoteSSH(host, defaultChoice)
if err != nil {
_, _ = term.Write(utils.LogSprintf(utils.WordsSSHNotAvailable, err).Bytes())
continue
}
_, _ = term.Write(utils.LogSprintf(utils.WordsSSHInfo, host).Bytes())
_, _ = term.Write(utils.LogSprintf(utils.WordsSSHLoading).Bytes())
wrapper := utils.NewTermWrapper(channel)
session, err := utils.CreateSSHSession(wrapper, host, sshConfig)
if err != nil {
log.Printf("connect to server failed: %v", err)
_, _ = term.Write(utils.LogSprintf(utils.WordsCommandError, err.Error()).Bytes())
continue
}
_, _ = term.Write([]byte(utils.ClearPreviousLine))
err = session.Wait()
_ = session.Close()
_ = wrapper.Close()
case "exec":
cmd, err := exec.Command("bash", "-c", strings.TrimPrefix(line, "exec")).Output()
if err != nil {
_, _ = term.Write(utils.LogSprintf(utils.WordsExecWrong, err).Bytes())
}
_, _ = term.Write(cmd)
case "exit":
_, _ = term.Write([]byte(utils.WordsDone))
return
case "help":
_, _ = term.Write([]byte(utils.GetHelpDoc(map[string]string{
"ssh": "ssh to remote host.",
"exec": "execute command.",
"exit": "logout",
}, utils.CRLF)))
default:
_, _ = term.Write(utils.LogSprintf(utils.WordsNotFound, line).Bytes())
}
}
}