term_windows.go (2185B)
1 // Copyright 2019 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 package term 6 7 import ( 8 "os" 9 10 "golang.org/x/sys/windows" 11 ) 12 13 type state struct { 14 mode uint32 15 } 16 17 func isTerminal(fd int) bool { 18 var st uint32 19 err := windows.GetConsoleMode(windows.Handle(fd), &st) 20 return err == nil 21 } 22 23 func makeRaw(fd int) (*State, error) { 24 var st uint32 25 if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { 26 return nil, err 27 } 28 raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT) 29 raw |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT 30 if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil { 31 return nil, err 32 } 33 return &State{state{st}}, nil 34 } 35 36 func getState(fd int) (*State, error) { 37 var st uint32 38 if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { 39 return nil, err 40 } 41 return &State{state{st}}, nil 42 } 43 44 func restore(fd int, state *State) error { 45 return windows.SetConsoleMode(windows.Handle(fd), state.mode) 46 } 47 48 func getSize(fd int) (width, height int, err error) { 49 var info windows.ConsoleScreenBufferInfo 50 if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil { 51 return 0, 0, err 52 } 53 return int(info.Window.Right - info.Window.Left + 1), int(info.Window.Bottom - info.Window.Top + 1), nil 54 } 55 56 func readPassword(fd int) ([]byte, error) { 57 var st uint32 58 if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { 59 return nil, err 60 } 61 old := st 62 63 st &^= (windows.ENABLE_ECHO_INPUT | windows.ENABLE_LINE_INPUT) 64 st |= (windows.ENABLE_PROCESSED_OUTPUT | windows.ENABLE_PROCESSED_INPUT) 65 if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil { 66 return nil, err 67 } 68 69 defer windows.SetConsoleMode(windows.Handle(fd), old) 70 71 var h windows.Handle 72 p, _ := windows.GetCurrentProcess() 73 if err := windows.DuplicateHandle(p, windows.Handle(fd), p, &h, 0, false, windows.DUPLICATE_SAME_ACCESS); err != nil { 74 return nil, err 75 } 76 77 f := os.NewFile(uintptr(h), "stdin") 78 defer f.Close() 79 return readPasswordLine(f) 80 }