123456789101112131415161718192021222324252627282930313233343536373839 | package pty
import (
"fmt"
"os"
"syscall"
"unsafe"
)
// getTermios and setTermios are the ioctls that get and set a
// terminal's settings (see KeyMode).
const getTermios, setTermios = syscall.TCGETS, syscall.TCSETS
// Open opens a new pseudo-terminal: the master, which the opener reads and
// writes, and the slave, the terminal a command gets.
func Open() (master, slave *os.File, err error) {
m, err := os.OpenFile("/dev/ptmx", os.O_RDWR|syscall.O_NOCTTY|syscall.O_CLOEXEC, 0)
if err != nil {
return nil, nil, err
}
defer func() {
if err != nil {
m.Close()
}
}()
var unlock int32
if err := ioctl(m, syscall.TIOCSPTLCK, unsafe.Pointer(&unlock)); err != nil {
return nil, nil, fmt.Errorf("unlocking the pty: %w", err)
}
var n uint32
if err := ioctl(m, syscall.TIOCGPTN, unsafe.Pointer(&n)); err != nil {
return nil, nil, fmt.Errorf("numbering the pty: %w", err)
}
s, err := os.OpenFile(fmt.Sprintf("/dev/pts/%d", n), os.O_RDWR|syscall.O_NOCTTY|syscall.O_CLOEXEC, 0)
if err != nil {
return nil, nil, err
}
return m, s, nil
}
|