Initial commit
This commit is contained in:
179
sshoneypot/info/terminal.go
Normal file
179
sshoneypot/info/terminal.go
Normal file
@@ -0,0 +1,179 @@
|
||||
package info
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Terminal struct {
|
||||
// the chan
|
||||
channel ssh.Channel
|
||||
|
||||
// The current prompt string
|
||||
prompt string
|
||||
|
||||
width, height int
|
||||
|
||||
isListening bool
|
||||
buffer []byte
|
||||
|
||||
lock *sync.Mutex
|
||||
}
|
||||
|
||||
const (
|
||||
keyCtrlC = 3
|
||||
keyCtrlD = 4
|
||||
keyEnter = 13
|
||||
keyEscape = 27
|
||||
keyReturn = 127
|
||||
keyUnknown = 0xd800 /* UTF-16 surrogate area */ + iota
|
||||
keyUp
|
||||
keyDown
|
||||
keyLeft
|
||||
keyRight
|
||||
keyAltLeft
|
||||
keyAltRight
|
||||
keyHome
|
||||
keyEnd
|
||||
keyDeleteWord
|
||||
keyDeleteLine
|
||||
keyClearScreen
|
||||
keyPasteStart
|
||||
keyPasteEnd
|
||||
)
|
||||
|
||||
var (
|
||||
CtrlC = errors.New("CtrlC")
|
||||
CtrlD = errors.New("CtrlD")
|
||||
)
|
||||
|
||||
func (term *Terminal) GetSize() (width int, height int) {
|
||||
return term.width, term.height
|
||||
}
|
||||
|
||||
func (term *Terminal) SetSize(width int, height int) {
|
||||
term.width = width
|
||||
term.height = height
|
||||
}
|
||||
|
||||
func (term *Terminal) GetPrompt() string {
|
||||
return term.prompt
|
||||
}
|
||||
|
||||
func (term *Terminal) SetPrompt(prompt string) {
|
||||
term.prompt = prompt
|
||||
}
|
||||
|
||||
func (term *Terminal) ReadLine() (string, error) {
|
||||
var content []byte
|
||||
for {
|
||||
data, _ := term.listen()
|
||||
for _, b := range data {
|
||||
fmt.Println(b)
|
||||
switch []rune(data) {
|
||||
case keyCtrlD:
|
||||
if len(content) == 0 {
|
||||
return "", CtrlD
|
||||
}
|
||||
case keyEnter:
|
||||
term.channel.Write([]byte("\r\n" + term.prompt))
|
||||
return string(data), nil
|
||||
case keyReturn:
|
||||
if len(content) - 1 > len(term.prompt) {
|
||||
content = content[:len(content) - 1]
|
||||
term.MoveCursor(0, 0, 1, 0)
|
||||
term.channel.Write(content)
|
||||
}
|
||||
case keyRight:
|
||||
fmt.Println("aaa")
|
||||
default:
|
||||
content = append(content, b)
|
||||
term.channel.Write(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (term *Terminal) Write(data []byte) (n int, err error) {
|
||||
return term.channel.Write(data)
|
||||
}
|
||||
|
||||
func (term *Terminal) MoveCursor(up, down, left, right int) {
|
||||
var m []rune
|
||||
|
||||
// 1 unit up can be expressed as ^[[A or ^[A
|
||||
// 5 units up can be expressed as ^[[5A
|
||||
|
||||
if up == 1 {
|
||||
m = append(m, keyEscape, '[', 'A')
|
||||
} else if up > 1 {
|
||||
m = append(m, keyEscape, '[')
|
||||
m = append(m, []rune(strconv.Itoa(up))...)
|
||||
m = append(m, 'A')
|
||||
}
|
||||
|
||||
if down == 1 {
|
||||
m = append(m, keyEscape, '[', 'B')
|
||||
} else if down > 1 {
|
||||
m = append(m, keyEscape, '[')
|
||||
m = append(m, []rune(strconv.Itoa(down))...)
|
||||
m = append(m, 'B')
|
||||
}
|
||||
|
||||
if right == 1 {
|
||||
m = append(m, keyEscape, '[', 'C')
|
||||
} else if right > 1 {
|
||||
m = append(m, keyEscape, '[')
|
||||
m = append(m, []rune(strconv.Itoa(right))...)
|
||||
m = append(m, 'C')
|
||||
}
|
||||
|
||||
if left == 1 {
|
||||
m = append(m, keyEscape, '[', 'D')
|
||||
} else if left > 1 {
|
||||
m = append(m, keyEscape, '[')
|
||||
m = append(m, []rune(strconv.Itoa(left))...)
|
||||
m = append(m, 'D')
|
||||
}
|
||||
|
||||
term.Write([]byte(string(m)))
|
||||
}
|
||||
|
||||
func (term *Terminal) ListenCtrlC() chan bool {
|
||||
ctrlc := make(chan bool, 1)
|
||||
go func() {
|
||||
if term.isListening {
|
||||
return
|
||||
}
|
||||
for {
|
||||
data, err := term.listen()
|
||||
if err == CtrlC {
|
||||
ctrlc <- false
|
||||
return
|
||||
}
|
||||
if term.isListening {
|
||||
ctrlc <- false
|
||||
term.buffer = data
|
||||
}
|
||||
}
|
||||
}()
|
||||
return ctrlc
|
||||
}
|
||||
|
||||
func (term *Terminal) listen() ([]byte, error) {
|
||||
buffer := make([]byte, 512)
|
||||
n, err := term.channel.Read(buffer)
|
||||
return buffer[:n], err
|
||||
}
|
||||
|
||||
func NewTerminal(channel ssh.Channel) *Terminal {
|
||||
return &Terminal{
|
||||
channel: channel,
|
||||
|
||||
lock: &sync.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user