|
|
@@ -14,14 +14,12 @@ import (
|
|
|
|
|
|
// State contains the state of a terminal.
|
|
|
type State struct {
|
|
|
- termios syscall.Termios
|
|
|
+ state *unix.Termios
|
|
|
}
|
|
|
|
|
|
// IsTerminal returns true if the given file descriptor is a terminal.
|
|
|
func IsTerminal(fd int) bool {
|
|
|
- // see: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libbc/libc/gen/common/isatty.c
|
|
|
- var termio unix.Termio
|
|
|
- err := unix.IoctlSetTermio(fd, unix.TCGETA, &termio)
|
|
|
+ _, err := unix.IoctlGetTermio(fd, unix.TCGETA)
|
|
|
return err == nil
|
|
|
}
|
|
|
|
|
|
@@ -71,3 +69,60 @@ func ReadPassword(fd int) ([]byte, error) {
|
|
|
|
|
|
return ret, nil
|
|
|
}
|
|
|
+
|
|
|
+// MakeRaw puts the terminal connected to the given file descriptor into raw
|
|
|
+// mode and returns the previous state of the terminal so that it can be
|
|
|
+// restored.
|
|
|
+// see http://cr.illumos.org/~webrev/andy_js/1060/
|
|
|
+func MakeRaw(fd int) (*State, error) {
|
|
|
+ oldTermiosPtr, err := unix.IoctlGetTermios(fd, unix.TCGETS)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ oldTermios := *oldTermiosPtr
|
|
|
+
|
|
|
+ newTermios := oldTermios
|
|
|
+ newTermios.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON
|
|
|
+ newTermios.Oflag &^= syscall.OPOST
|
|
|
+ newTermios.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN
|
|
|
+ newTermios.Cflag &^= syscall.CSIZE | syscall.PARENB
|
|
|
+ newTermios.Cflag |= syscall.CS8
|
|
|
+ newTermios.Cc[unix.VMIN] = 1
|
|
|
+ newTermios.Cc[unix.VTIME] = 0
|
|
|
+
|
|
|
+ if err := unix.IoctlSetTermios(fd, unix.TCSETS, &newTermios); err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ return &State{
|
|
|
+ state: oldTermiosPtr,
|
|
|
+ }, nil
|
|
|
+}
|
|
|
+
|
|
|
+// Restore restores the terminal connected to the given file descriptor to a
|
|
|
+// previous state.
|
|
|
+func Restore(fd int, oldState *State) error {
|
|
|
+ return unix.IoctlSetTermios(fd, unix.TCSETS, oldState.state)
|
|
|
+}
|
|
|
+
|
|
|
+// GetState returns the current state of a terminal which may be useful to
|
|
|
+// restore the terminal after a signal.
|
|
|
+func GetState(fd int) (*State, error) {
|
|
|
+ oldTermiosPtr, err := unix.IoctlGetTermios(fd, unix.TCGETS)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ return &State{
|
|
|
+ state: oldTermiosPtr,
|
|
|
+ }, nil
|
|
|
+}
|
|
|
+
|
|
|
+// GetSize returns the dimensions of the given terminal.
|
|
|
+func GetSize(fd int) (width, height int, err error) {
|
|
|
+ ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
|
|
|
+ if err != nil {
|
|
|
+ return 0, 0, err
|
|
|
+ }
|
|
|
+ return int(ws.Col), int(ws.Row), nil
|
|
|
+}
|