123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- // Copyright 2011 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.
- // +build windows
- // Package terminal provides support functions for dealing with terminals, as
- // commonly found on UNIX systems.
- //
- // Putting a terminal into raw mode is the most common requirement:
- //
- // oldState, err := terminal.MakeRaw(0)
- // if err != nil {
- // panic(err)
- // }
- // defer terminal.Restore(0, oldState)
- package terminal
- import (
- "os"
- "golang.org/x/sys/windows"
- )
- type State struct {
- mode uint32
- }
- // IsTerminal returns whether the given file descriptor is a terminal.
- func IsTerminal(fd int) bool {
- var st uint32
- err := windows.GetConsoleMode(windows.Handle(fd), &st)
- return err == nil
- }
- // MakeRaw put 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.
- func MakeRaw(fd int) (*State, error) {
- var st uint32
- if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
- return nil, err
- }
- raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
- if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil {
- return nil, err
- }
- return &State{st}, nil
- }
- // 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) {
- var st uint32
- if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
- return nil, err
- }
- return &State{st}, nil
- }
- // Restore restores the terminal connected to the given file descriptor to a
- // previous state.
- func Restore(fd int, state *State) error {
- return windows.SetConsoleMode(windows.Handle(fd), state.mode)
- }
- // GetSize returns the visible dimensions of the given terminal.
- //
- // These dimensions don't include any scrollback buffer height.
- func GetSize(fd int) (width, height int, err error) {
- var info windows.ConsoleScreenBufferInfo
- if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil {
- return 0, 0, err
- }
- return int(info.Window.Right - info.Window.Left + 1), int(info.Window.Bottom - info.Window.Top + 1), nil
- }
- // ReadPassword reads a line of input from a terminal without local echo. This
- // is commonly used for inputting passwords and other sensitive data. The slice
- // returned does not include the \n.
- func ReadPassword(fd int) ([]byte, error) {
- var st uint32
- if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
- return nil, err
- }
- old := st
- st &^= (windows.ENABLE_ECHO_INPUT)
- st |= (windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
- if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil {
- return nil, err
- }
- defer windows.SetConsoleMode(windows.Handle(fd), old)
- var h windows.Handle
- p, _ := windows.GetCurrentProcess()
- if err := windows.DuplicateHandle(p, windows.Handle(fd), p, &h, 0, false, windows.DUPLICATE_SAME_ACCESS); err != nil {
- return nil, err
- }
- f := os.NewFile(uintptr(h), "stdin")
- defer f.Close()
- return readPasswordLine(f)
- }
|