You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
151 lines
2.8 KiB
Go
151 lines
2.8 KiB
Go
package commands
|
|
|
|
import (
|
|
"errors"
|
|
"log"
|
|
"strconv"
|
|
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
func Control(c rune) rune {
|
|
return c & 0x1f
|
|
}
|
|
|
|
func sttyCharFromDesc(c string) (rune, error) {
|
|
if len(c) > 2 || len(c) < 1 {
|
|
return 'i', errors.New(
|
|
"stty char description has unsupported length: " +
|
|
strconv.Itoa(len(c)),
|
|
)
|
|
}
|
|
|
|
if rune(c[0]) == '^' {
|
|
return Control(rune(c[1])), nil
|
|
}
|
|
|
|
return rune(c[0]), nil
|
|
}
|
|
|
|
const fakeUname = "Linux 5.16.19-76051619-generic"
|
|
|
|
type CommandExecutor interface {
|
|
Execute(shell *Shell, args []string) error
|
|
}
|
|
|
|
type SttyCommand struct{}
|
|
|
|
func (c *SttyCommand) Execute(shell *Shell, args []string) error {
|
|
// Tramp uses:
|
|
// -inlcr: don't translate newline to carriage return
|
|
// -onlcr: don't translate newline to carriage return-newline
|
|
// -echo: echo input characters
|
|
// kill CHAR: CHAR will erase the current line
|
|
// erase CHAR: CHAR will erase the last character typed
|
|
// icanon: enable special charactersq
|
|
|
|
fd := int(shell.GetPty().Fd())
|
|
const ioctlReadTermios = unix.TCGETS // Linux
|
|
const ioctlWriteTermios = unix.TCSETS // Linux
|
|
|
|
termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
newState := *termios
|
|
|
|
var skipNext bool
|
|
for i, arg := range args {
|
|
if skipNext {
|
|
skipNext = false
|
|
continue
|
|
}
|
|
|
|
var disable bool
|
|
if arg[0] == '-' {
|
|
disable = true
|
|
arg = arg[1:]
|
|
}
|
|
|
|
switch arg {
|
|
case "onlcr":
|
|
if disable {
|
|
newState.Iflag &^= unix.ONLCR
|
|
continue
|
|
}
|
|
|
|
newState.Iflag |= unix.ONLCR
|
|
case "inlcr":
|
|
if disable {
|
|
newState.Iflag &^= unix.INLCR
|
|
continue
|
|
}
|
|
|
|
newState.Iflag |= unix.INLCR
|
|
case "echo":
|
|
if disable {
|
|
newState.Lflag &^= unix.ECHO
|
|
continue
|
|
}
|
|
|
|
newState.Lflag |= unix.ECHO
|
|
case "kill":
|
|
skipNext = true
|
|
|
|
char, err := sttyCharFromDesc(args[i+1])
|
|
if err != nil {
|
|
log.Printf(
|
|
"Warning: Not applying unsupported character description for stty kill: %s",
|
|
args[i+1],
|
|
)
|
|
continue
|
|
}
|
|
|
|
newState.Cc[unix.VKILL] = uint8(char)
|
|
case "erase":
|
|
skipNext = true
|
|
|
|
char, err := sttyCharFromDesc(args[i+1])
|
|
if err != nil {
|
|
log.Printf(
|
|
"Warning: Not applying unsupported character description for stty erase: %s",
|
|
args[i+1],
|
|
)
|
|
continue
|
|
}
|
|
|
|
newState.Cc[unix.VERASE] = uint8(char)
|
|
case "icanon":
|
|
if disable {
|
|
newState.Lflag &^= unix.ICANON
|
|
continue
|
|
}
|
|
|
|
newState.Lflag |= unix.ICANON
|
|
|
|
case "tab0":
|
|
newState.Oflag = (newState.Oflag & ^uint32(unix.TABDLY)) | unix.TAB0
|
|
case "iutf8":
|
|
if disable {
|
|
newState.Iflag &^= unix.IUTF8
|
|
continue
|
|
}
|
|
|
|
newState.Iflag |= unix.IUTF8
|
|
|
|
default:
|
|
log.Printf(
|
|
"Warning, tramp requested unexpected stty option %s",
|
|
arg,
|
|
)
|
|
}
|
|
}
|
|
|
|
if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, &newState); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|