aminal/platform/unixpty.go

102 lines
2.1 KiB
Go

//+build !windows
package platform
import (
"errors"
"os"
"os/exec"
"syscall"
"unsafe"
"github.com/kr/pty"
)
type unixPty struct {
pty *os.File
tty *os.File
platformDependentSettings PlatformDependentSettings
}
type winsize struct {
Height uint16
Width uint16
x uint16 // ignored, but necessary for ioctl calls
y uint16 // ignored, but necessary for ioctl calls
}
func (p *unixPty) Read(b []byte) (int, error) {
if p == nil || p.pty == nil {
return 0, errors.New("Attempted to read from a deallocated pty")
}
return p.pty.Read(b)
}
func (p *unixPty) Write(b []byte) (int, error) {
if p == nil || p.pty == nil {
return 0, errors.New("Attempted to write to a deallocated pty")
}
return p.pty.Write(b)
}
func (p *unixPty) Close() error {
if p == nil || p.pty == nil {
return nil
}
ret := p.pty.Close()
p.pty = nil
p.tty = nil
return ret
}
func (p *unixPty) Resize(x, y int) error {
size := winsize{
Height: uint16(y),
Width: uint16(x),
x: 0,
y: 0,
}
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(p.pty.Fd()),
uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(&size)))
if errno != 0 {
return errors.New(errno.Error())
}
return nil
}
func (p *unixPty) CreateGuestProcess(imagePath string) (Process, error) {
if p == nil || p.tty == nil {
return nil, errors.New("Attempted to create a process on a deallocated pty")
}
shell := newCmdProc(exec.Command(imagePath))
shell.cmd.Stdout = p.tty
shell.cmd.Stdin = p.tty
shell.cmd.Stderr = p.tty
shell.cmd.SysProcAttr = &syscall.SysProcAttr{Setctty: true, Setsid: true}
if err := shell.cmd.Start(); err != nil {
return nil, err
}
return shell, nil
}
func (pty *unixPty) GetPlatformDependentSettings() PlatformDependentSettings {
return pty.platformDependentSettings
}
func NewPty(x, y int) (Pty, error) {
innerPty, innerTty, err := pty.Open()
if err != nil {
return nil, err
}
return &unixPty{
pty: innerPty,
tty: innerTty,
platformDependentSettings: PlatformDependentSettings{
OSCTerminators: map[rune]struct{}{0x07: {}, 0x5c: {}},
},
}, nil
}