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  }