github.com/glycerine/xcryptossh@v7.0.4+incompatible/terminal/util_windows.go (about) 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 windows 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 18 19 import ( 20 "golang.org/x/sys/windows" 21 ) 22 23 type State struct { 24 mode uint32 25 } 26 27 // IsTerminal returns true if the given file descriptor is a terminal. 28 func IsTerminal(fd int) bool { 29 var st uint32 30 err := windows.GetConsoleMode(windows.Handle(fd), &st) 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 var st uint32 39 if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { 40 return nil, err 41 } 42 raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT) 43 if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil { 44 return nil, err 45 } 46 return &State{st}, nil 47 } 48 49 // GetState returns the current state of a terminal which may be useful to 50 // restore the terminal after a signal. 51 func GetState(fd int) (*State, error) { 52 var st uint32 53 if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { 54 return nil, err 55 } 56 return &State{st}, nil 57 } 58 59 // Restore restores the terminal connected to the given file descriptor to a 60 // previous state. 61 func Restore(fd int, state *State) error { 62 return windows.SetConsoleMode(windows.Handle(fd), state.mode) 63 } 64 65 // GetSize returns the dimensions of the given terminal. 66 func GetSize(fd int) (width, height int, err error) { 67 var info windows.ConsoleScreenBufferInfo 68 if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil { 69 return 0, 0, err 70 } 71 return int(info.Size.X), int(info.Size.Y), nil 72 } 73 74 // passwordReader is an io.Reader that reads from a specific Windows HANDLE. 75 type passwordReader int 76 77 func (r passwordReader) Read(buf []byte) (int, error) { 78 return windows.Read(windows.Handle(r), buf) 79 } 80 81 // ReadPassword reads a line of input from a terminal without local echo. This 82 // is commonly used for inputting passwords and other sensitive data. The slice 83 // returned does not include the \n. 84 func ReadPassword(fd int) ([]byte, error) { 85 var st uint32 86 if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { 87 return nil, err 88 } 89 old := st 90 91 st &^= (windows.ENABLE_ECHO_INPUT) 92 st |= (windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT) 93 if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil { 94 return nil, err 95 } 96 97 defer func() { 98 windows.SetConsoleMode(windows.Handle(fd), old) 99 }() 100 101 return readPasswordLine(passwordReader(fd)) 102 }