You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

74 lines
1.7 KiB

  1. // Copyright 2015 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. // +build solaris
  5. package terminal // import "golang.org/x/crypto/ssh/terminal"
  6. import (
  7. "golang.org/x/sys/unix"
  8. "io"
  9. "syscall"
  10. )
  11. // State contains the state of a terminal.
  12. type State struct {
  13. termios syscall.Termios
  14. }
  15. // IsTerminal returns true if the given file descriptor is a terminal.
  16. func IsTerminal(fd int) bool {
  17. // see: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libbc/libc/gen/common/isatty.c
  18. var termio unix.Termio
  19. err := unix.IoctlSetTermio(fd, unix.TCGETA, &termio)
  20. return err == nil
  21. }
  22. // ReadPassword reads a line of input from a terminal without local echo. This
  23. // is commonly used for inputting passwords and other sensitive data. The slice
  24. // returned does not include the \n.
  25. func ReadPassword(fd int) ([]byte, error) {
  26. // see also: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c
  27. val, err := unix.IoctlGetTermios(fd, unix.TCGETS)
  28. if err != nil {
  29. return nil, err
  30. }
  31. oldState := *val
  32. newState := oldState
  33. newState.Lflag &^= syscall.ECHO
  34. newState.Lflag |= syscall.ICANON | syscall.ISIG
  35. newState.Iflag |= syscall.ICRNL
  36. err = unix.IoctlSetTermios(fd, unix.TCSETS, &newState)
  37. if err != nil {
  38. return nil, err
  39. }
  40. defer unix.IoctlSetTermios(fd, unix.TCSETS, &oldState)
  41. var buf [16]byte
  42. var ret []byte
  43. for {
  44. n, err := syscall.Read(fd, buf[:])
  45. if err != nil {
  46. return nil, err
  47. }
  48. if n == 0 {
  49. if len(ret) == 0 {
  50. return nil, io.EOF
  51. }
  52. break
  53. }
  54. if buf[n-1] == '\n' {
  55. n--
  56. }
  57. ret = append(ret, buf[:n]...)
  58. if n < len(buf) {
  59. break
  60. }
  61. }
  62. return ret, nil
  63. }