Gibheer
fa05045d31
This is the import from the separate monfront repository. The history could not be imported, but this should suffice.
112 lines
2.4 KiB
Go
112 lines
2.4 KiB
Go
// Copyright 2019 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package term
|
|
|
|
import (
|
|
"io"
|
|
"syscall"
|
|
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
// State contains the state of a terminal.
|
|
type state struct {
|
|
termios unix.Termios
|
|
}
|
|
|
|
func isTerminal(fd int) bool {
|
|
_, err := unix.IoctlGetTermio(fd, unix.TCGETA)
|
|
return err == nil
|
|
}
|
|
|
|
func readPassword(fd int) ([]byte, error) {
|
|
// see also: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c
|
|
val, err := unix.IoctlGetTermios(fd, unix.TCGETS)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
oldState := *val
|
|
|
|
newState := oldState
|
|
newState.Lflag &^= syscall.ECHO
|
|
newState.Lflag |= syscall.ICANON | syscall.ISIG
|
|
newState.Iflag |= syscall.ICRNL
|
|
err = unix.IoctlSetTermios(fd, unix.TCSETS, &newState)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
defer unix.IoctlSetTermios(fd, unix.TCSETS, &oldState)
|
|
|
|
var buf [16]byte
|
|
var ret []byte
|
|
for {
|
|
n, err := syscall.Read(fd, buf[:])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if n == 0 {
|
|
if len(ret) == 0 {
|
|
return nil, io.EOF
|
|
}
|
|
break
|
|
}
|
|
if buf[n-1] == '\n' {
|
|
n--
|
|
}
|
|
ret = append(ret, buf[:n]...)
|
|
if n < len(buf) {
|
|
break
|
|
}
|
|
}
|
|
|
|
return ret, nil
|
|
}
|
|
|
|
func makeRaw(fd int) (*State, error) {
|
|
// see http://cr.illumos.org/~webrev/andy_js/1060/
|
|
termios, err := unix.IoctlGetTermios(fd, unix.TCGETS)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
oldState := State{state{termios: *termios}}
|
|
|
|
termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON
|
|
termios.Oflag &^= unix.OPOST
|
|
termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN
|
|
termios.Cflag &^= unix.CSIZE | unix.PARENB
|
|
termios.Cflag |= unix.CS8
|
|
termios.Cc[unix.VMIN] = 1
|
|
termios.Cc[unix.VTIME] = 0
|
|
|
|
if err := unix.IoctlSetTermios(fd, unix.TCSETS, termios); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &oldState, nil
|
|
}
|
|
|
|
func restore(fd int, oldState *State) error {
|
|
return unix.IoctlSetTermios(fd, unix.TCSETS, &oldState.termios)
|
|
}
|
|
|
|
func getState(fd int) (*State, error) {
|
|
termios, err := unix.IoctlGetTermios(fd, unix.TCGETS)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &State{state{termios: *termios}}, nil
|
|
}
|
|
|
|
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
|
|
}
|