github.com/timstclair/heapster@v0.20.0-alpha1/Godeps/_workspace/src/golang.org/x/crypto/ssh/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 "io" 21 "syscall" 22 "unsafe" 23 ) 24 25 const ( 26 enableLineInput = 2 27 enableEchoInput = 4 28 enableProcessedInput = 1 29 enableWindowInput = 8 30 enableMouseInput = 16 31 enableInsertMode = 32 32 enableQuickEditMode = 64 33 enableExtendedFlags = 128 34 enableAutoPosition = 256 35 enableProcessedOutput = 1 36 enableWrapAtEolOutput = 2 37 ) 38 39 var kernel32 = syscall.NewLazyDLL("kernel32.dll") 40 41 var ( 42 procGetConsoleMode = kernel32.NewProc("GetConsoleMode") 43 procSetConsoleMode = kernel32.NewProc("SetConsoleMode") 44 procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo") 45 ) 46 47 type ( 48 short int16 49 word uint16 50 51 coord struct { 52 x short 53 y short 54 } 55 smallRect struct { 56 left short 57 top short 58 right short 59 bottom short 60 } 61 consoleScreenBufferInfo struct { 62 size coord 63 cursorPosition coord 64 attributes word 65 window smallRect 66 maximumWindowSize coord 67 } 68 ) 69 70 type State struct { 71 mode uint32 72 } 73 74 // IsTerminal returns true if the given file descriptor is a terminal. 75 func IsTerminal(fd int) bool { 76 var st uint32 77 r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) 78 return r != 0 && e == 0 79 } 80 81 // MakeRaw put the terminal connected to the given file descriptor into raw 82 // mode and returns the previous state of the terminal so that it can be 83 // restored. 84 func MakeRaw(fd int) (*State, error) { 85 var st uint32 86 _, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) 87 if e != 0 { 88 return nil, error(e) 89 } 90 st &^= (enableEchoInput | enableProcessedInput | enableLineInput | enableProcessedOutput) 91 _, _, e = syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(st), 0) 92 if e != 0 { 93 return nil, error(e) 94 } 95 return &State{st}, nil 96 } 97 98 // GetState returns the current state of a terminal which may be useful to 99 // restore the terminal after a signal. 100 func GetState(fd int) (*State, error) { 101 var st uint32 102 _, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) 103 if e != 0 { 104 return nil, error(e) 105 } 106 return &State{st}, nil 107 } 108 109 // Restore restores the terminal connected to the given file descriptor to a 110 // previous state. 111 func Restore(fd int, state *State) error { 112 _, _, err := syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(state.mode), 0) 113 return err 114 } 115 116 // GetSize returns the dimensions of the given terminal. 117 func GetSize(fd int) (width, height int, err error) { 118 var info consoleScreenBufferInfo 119 _, _, e := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&info)), 0) 120 if e != 0 { 121 return 0, 0, error(e) 122 } 123 return int(info.size.x), int(info.size.y), nil 124 } 125 126 // ReadPassword reads a line of input from a terminal without local echo. This 127 // is commonly used for inputting passwords and other sensitive data. The slice 128 // returned does not include the \n. 129 func ReadPassword(fd int) ([]byte, error) { 130 var st uint32 131 _, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) 132 if e != 0 { 133 return nil, error(e) 134 } 135 old := st 136 137 st &^= (enableEchoInput) 138 st |= (enableProcessedInput | enableLineInput | enableProcessedOutput) 139 _, _, e = syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(st), 0) 140 if e != 0 { 141 return nil, error(e) 142 } 143 144 defer func() { 145 syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(old), 0) 146 }() 147 148 var buf [16]byte 149 var ret []byte 150 for { 151 n, err := syscall.Read(syscall.Handle(fd), buf[:]) 152 if err != nil { 153 return nil, err 154 } 155 if n == 0 { 156 if len(ret) == 0 { 157 return nil, io.EOF 158 } 159 break 160 } 161 if buf[n-1] == '\n' { 162 n-- 163 } 164 if n > 0 && buf[n-1] == '\r' { 165 n-- 166 } 167 ret = append(ret, buf[:n]...) 168 if n < len(buf) { 169 break 170 } 171 } 172 173 return ret, nil 174 }