...

Source file src/pkg/cmd/vendor/golang.org/x/crypto/ssh/terminal/util.go

     1	// Copyright 2011 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	// +build aix darwin dragonfly freebsd linux,!appengine netbsd openbsd
     6	
     7	// Package terminal provides support functions for dealing with terminals, as
     8	// commonly found on UNIX systems.
     9	//
    10	// Putting a terminal into raw mode is the most common requirement:
    11	//
    12	// 	oldState, err := terminal.MakeRaw(0)
    13	// 	if err != nil {
    14	// 	        panic(err)
    15	// 	}
    16	// 	defer terminal.Restore(0, oldState)
    17	package terminal // import "golang.org/x/crypto/ssh/terminal"
    18	
    19	import (
    20		"golang.org/x/sys/unix"
    21	)
    22	
    23	// State contains the state of a terminal.
    24	type State struct {
    25		termios unix.Termios
    26	}
    27	
    28	// IsTerminal returns whether the given file descriptor is a terminal.
    29	func IsTerminal(fd int) bool {
    30		_, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
    31		return err == nil
    32	}
    33	
    34	// MakeRaw put the terminal connected to the given file descriptor into raw
    35	// mode and returns the previous state of the terminal so that it can be
    36	// restored.
    37	func MakeRaw(fd int) (*State, error) {
    38		termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
    39		if err != nil {
    40			return nil, err
    41		}
    42	
    43		oldState := State{termios: *termios}
    44	
    45		// This attempts to replicate the behaviour documented for cfmakeraw in
    46		// the termios(3) manpage.
    47		termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON
    48		termios.Oflag &^= unix.OPOST
    49		termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN
    50		termios.Cflag &^= unix.CSIZE | unix.PARENB
    51		termios.Cflag |= unix.CS8
    52		termios.Cc[unix.VMIN] = 1
    53		termios.Cc[unix.VTIME] = 0
    54		if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, termios); err != nil {
    55			return nil, err
    56		}
    57	
    58		return &oldState, nil
    59	}
    60	
    61	// GetState returns the current state of a terminal which may be useful to
    62	// restore the terminal after a signal.
    63	func GetState(fd int) (*State, error) {
    64		termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
    65		if err != nil {
    66			return nil, err
    67		}
    68	
    69		return &State{termios: *termios}, nil
    70	}
    71	
    72	// Restore restores the terminal connected to the given file descriptor to a
    73	// previous state.
    74	func Restore(fd int, state *State) error {
    75		return unix.IoctlSetTermios(fd, ioctlWriteTermios, &state.termios)
    76	}
    77	
    78	// GetSize returns the dimensions of the given terminal.
    79	func GetSize(fd int) (width, height int, err error) {
    80		ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
    81		if err != nil {
    82			return -1, -1, err
    83		}
    84		return int(ws.Col), int(ws.Row), nil
    85	}
    86	
    87	// passwordReader is an io.Reader that reads from a specific file descriptor.
    88	type passwordReader int
    89	
    90	func (r passwordReader) Read(buf []byte) (int, error) {
    91		return unix.Read(int(r), buf)
    92	}
    93	
    94	// ReadPassword reads a line of input from a terminal without local echo.  This
    95	// is commonly used for inputting passwords and other sensitive data. The slice
    96	// returned does not include the \n.
    97	func ReadPassword(fd int) ([]byte, error) {
    98		termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
    99		if err != nil {
   100			return nil, err
   101		}
   102	
   103		newState := *termios
   104		newState.Lflag &^= unix.ECHO
   105		newState.Lflag |= unix.ICANON | unix.ISIG
   106		newState.Iflag |= unix.ICRNL
   107		if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, &newState); err != nil {
   108			return nil, err
   109		}
   110	
   111		defer unix.IoctlSetTermios(fd, ioctlWriteTermios, termios)
   112	
   113		return readPasswordLine(passwordReader(fd))
   114	}
   115	

View as plain text