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 | if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil {
|
---|
30 | return nil, err
|
---|
31 | }
|
---|
32 | return &State{state{st}}, nil
|
---|
33 | }
|
---|
34 |
|
---|
35 | func getState(fd int) (*State, error) {
|
---|
36 | var st uint32
|
---|
37 | if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
|
---|
38 | return nil, err
|
---|
39 | }
|
---|
40 | return &State{state{st}}, nil
|
---|
41 | }
|
---|
42 |
|
---|
43 | func restore(fd int, state *State) error {
|
---|
44 | return windows.SetConsoleMode(windows.Handle(fd), state.mode)
|
---|
45 | }
|
---|
46 |
|
---|
47 | func getSize(fd int) (width, height int, err error) {
|
---|
48 | var info windows.ConsoleScreenBufferInfo
|
---|
49 | if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil {
|
---|
50 | return 0, 0, err
|
---|
51 | }
|
---|
52 | return int(info.Window.Right - info.Window.Left + 1), int(info.Window.Bottom - info.Window.Top + 1), nil
|
---|
53 | }
|
---|
54 |
|
---|
55 | func readPassword(fd int) ([]byte, error) {
|
---|
56 | var st uint32
|
---|
57 | if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
|
---|
58 | return nil, err
|
---|
59 | }
|
---|
60 | old := st
|
---|
61 |
|
---|
62 | st &^= (windows.ENABLE_ECHO_INPUT | windows.ENABLE_LINE_INPUT)
|
---|
63 | st |= (windows.ENABLE_PROCESSED_OUTPUT | windows.ENABLE_PROCESSED_INPUT)
|
---|
64 | if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil {
|
---|
65 | return nil, err
|
---|
66 | }
|
---|
67 |
|
---|
68 | defer windows.SetConsoleMode(windows.Handle(fd), old)
|
---|
69 |
|
---|
70 | var h windows.Handle
|
---|
71 | p, _ := windows.GetCurrentProcess()
|
---|
72 | if err := windows.DuplicateHandle(p, windows.Handle(fd), p, &h, 0, false, windows.DUPLICATE_SAME_ACCESS); err != nil {
|
---|
73 | return nil, err
|
---|
74 | }
|
---|
75 |
|
---|
76 | f := os.NewFile(uintptr(h), "stdin")
|
---|
77 | defer f.Close()
|
---|
78 | return readPasswordLine(f)
|
---|
79 | }
|
---|