Path: blob/main/vendor/github.com/chzyer/readline/term.go
2875 views
// Copyright 2011 The Go Authors. All rights reserved.1// Use of this source code is governed by a BSD-style2// license that can be found in the LICENSE file.34// +build aix darwin dragonfly freebsd linux,!appengine netbsd openbsd os400 solaris56// Package terminal provides support functions for dealing with terminals, as7// commonly found on UNIX systems.8//9// Putting a terminal into raw mode is the most common requirement:10//11// oldState, err := terminal.MakeRaw(0)12// if err != nil {13// panic(err)14// }15// defer terminal.Restore(0, oldState)16package readline1718import (19"io"20"syscall"21)2223// State contains the state of a terminal.24type State struct {25termios Termios26}2728// IsTerminal returns true if the given file descriptor is a terminal.29func IsTerminal(fd int) bool {30_, err := getTermios(fd)31return err == nil32}3334// MakeRaw put the terminal connected to the given file descriptor into raw35// mode and returns the previous state of the terminal so that it can be36// restored.37func MakeRaw(fd int) (*State, error) {38var oldState State3940if termios, err := getTermios(fd); err != nil {41return nil, err42} else {43oldState.termios = *termios44}4546newState := oldState.termios47// This attempts to replicate the behaviour documented for cfmakeraw in48// the termios(3) manpage.49newState.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON50// newState.Oflag &^= syscall.OPOST51newState.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN52newState.Cflag &^= syscall.CSIZE | syscall.PARENB53newState.Cflag |= syscall.CS85455newState.Cc[syscall.VMIN] = 156newState.Cc[syscall.VTIME] = 05758return &oldState, setTermios(fd, &newState)59}6061// GetState returns the current state of a terminal which may be useful to62// restore the terminal after a signal.63func GetState(fd int) (*State, error) {64termios, err := getTermios(fd)65if err != nil {66return nil, err67}6869return &State{termios: *termios}, nil70}7172// Restore restores the terminal connected to the given file descriptor to a73// previous state.74func restoreTerm(fd int, state *State) error {75return setTermios(fd, &state.termios)76}7778// ReadPassword reads a line of input from a terminal without local echo. This79// is commonly used for inputting passwords and other sensitive data. The slice80// returned does not include the \n.81func ReadPassword(fd int) ([]byte, error) {82oldState, err := getTermios(fd)83if err != nil {84return nil, err85}8687newState := oldState88newState.Lflag &^= syscall.ECHO89newState.Lflag |= syscall.ICANON | syscall.ISIG90newState.Iflag |= syscall.ICRNL91if err := setTermios(fd, newState); err != nil {92return nil, err93}9495defer func() {96setTermios(fd, oldState)97}()9899var buf [16]byte100var ret []byte101for {102n, err := syscall.Read(fd, buf[:])103if err != nil {104return nil, err105}106if n == 0 {107if len(ret) == 0 {108return nil, io.EOF109}110break111}112if buf[n-1] == '\n' {113n--114}115ret = append(ret, buf[:n]...)116if n < len(buf) {117break118}119}120121return ret, nil122}123124125