mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
111 lines
1.7 KiB
Go
111 lines
1.7 KiB
Go
//go:build !windows
|
|
// +build !windows
|
|
|
|
package pty
|
|
|
|
import (
|
|
"os"
|
|
"os/exec"
|
|
"runtime"
|
|
"sync"
|
|
|
|
"github.com/creack/pty"
|
|
"golang.org/x/xerrors"
|
|
)
|
|
|
|
func newPty() (PTY, error) {
|
|
ptyFile, ttyFile, err := pty.Open()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &otherPty{
|
|
pty: ptyFile,
|
|
tty: ttyFile,
|
|
}, nil
|
|
}
|
|
|
|
type otherPty struct {
|
|
mutex sync.Mutex
|
|
closed bool
|
|
err error
|
|
pty, tty *os.File
|
|
}
|
|
|
|
type otherProcess struct {
|
|
pty *os.File
|
|
cmd *exec.Cmd
|
|
|
|
// cmdDone protects access to cmdErr: anything reading cmdErr should read from cmdDone first.
|
|
cmdDone chan any
|
|
cmdErr error
|
|
}
|
|
|
|
func (p *otherPty) Input() ReadWriter {
|
|
return ReadWriter{
|
|
Reader: p.tty,
|
|
Writer: p.pty,
|
|
}
|
|
}
|
|
|
|
func (p *otherPty) Output() ReadWriter {
|
|
return ReadWriter{
|
|
Reader: p.pty,
|
|
Writer: p.tty,
|
|
}
|
|
}
|
|
|
|
func (p *otherPty) Resize(height uint16, width uint16) error {
|
|
p.mutex.Lock()
|
|
defer p.mutex.Unlock()
|
|
if p.closed {
|
|
return p.err
|
|
}
|
|
return pty.Setsize(p.pty, &pty.Winsize{
|
|
Rows: height,
|
|
Cols: width,
|
|
})
|
|
}
|
|
|
|
func (p *otherPty) Close() error {
|
|
p.mutex.Lock()
|
|
defer p.mutex.Unlock()
|
|
|
|
if p.closed {
|
|
return p.err
|
|
}
|
|
p.closed = true
|
|
|
|
err := p.pty.Close()
|
|
err2 := p.tty.Close()
|
|
if err != nil {
|
|
err = err2
|
|
}
|
|
|
|
if err != nil {
|
|
p.err = err
|
|
} else {
|
|
p.err = xerrors.New("pty: closed")
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
func (p *otherProcess) Wait() error {
|
|
<-p.cmdDone
|
|
return p.cmdErr
|
|
}
|
|
|
|
func (p *otherProcess) Kill() error {
|
|
return p.cmd.Process.Kill()
|
|
}
|
|
|
|
func (p *otherProcess) waitInternal() {
|
|
// The GC can garbage collect the TTY FD before the command
|
|
// has finished running. See:
|
|
// https://github.com/creack/pty/issues/127#issuecomment-932764012
|
|
p.cmdErr = p.cmd.Wait()
|
|
runtime.KeepAlive(p.pty)
|
|
close(p.cmdDone)
|
|
}
|