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) 17package terminal 18 19import ( 20 "os" 21 22 "golang.org/x/sys/windows" 23) 24 25type State struct { 26 mode uint32 27} 28 29// IsTerminal returns whether the given file descriptor is a terminal. 30func IsTerminal(fd int) bool { 31 var st uint32 32 err := windows.GetConsoleMode(windows.Handle(fd), &st) 33 return err == nil 34} 35 36// MakeRaw put the terminal connected to the given file descriptor into raw 37// mode and returns the previous state of the terminal so that it can be 38// restored. 39func MakeRaw(fd int) (*State, error) { 40 var st uint32 41 if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { 42 return nil, err 43 } 44 raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT) 45 if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil { 46 return nil, err 47 } 48 return &State{st}, nil 49} 50 51// GetState returns the current state of a terminal which may be useful to 52// restore the terminal after a signal. 53func GetState(fd int) (*State, error) { 54 var st uint32 55 if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { 56 return nil, err 57 } 58 return &State{st}, nil 59} 60 61// Restore restores the terminal connected to the given file descriptor to a 62// previous state. 63func Restore(fd int, state *State) error { 64 return windows.SetConsoleMode(windows.Handle(fd), state.mode) 65} 66 67// GetSize returns the visible dimensions of the given terminal. 68// 69// These dimensions don't include any scrollback buffer height. 70func GetSize(fd int) (width, height int, err error) { 71 var info windows.ConsoleScreenBufferInfo 72 if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil { 73 return 0, 0, err 74 } 75 return int(info.Window.Right - info.Window.Left + 1), int(info.Window.Bottom - info.Window.Top + 1), nil 76} 77 78// ReadPassword reads a line of input from a terminal without local echo. This 79// is commonly used for inputting passwords and other sensitive data. The slice 80// returned does not include the \n. 81func ReadPassword(fd int) ([]byte, error) { 82 var st uint32 83 if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { 84 return nil, err 85 } 86 old := st 87 88 st &^= (windows.ENABLE_ECHO_INPUT) 89 st |= (windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT) 90 if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil { 91 return nil, err 92 } 93 94 defer windows.SetConsoleMode(windows.Handle(fd), old) 95 96 var h windows.Handle 97 p, _ := windows.GetCurrentProcess() 98 if err := windows.DuplicateHandle(p, windows.Handle(fd), p, &h, 0, false, windows.DUPLICATE_SAME_ACCESS); err != nil { 99 return nil, err 100 } 101 102 f := os.NewFile(uintptr(h), "stdin") 103 defer f.Close() 104 return readPasswordLine(f) 105} 106