Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  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. package term
  5. import (
  6. "io"
  7. "syscall"
  8. "golang.org/x/sys/unix"
  9. )
  10. // State contains the state of a terminal.
  11. type state struct {
  12. termios unix.Termios
  13. }
  14. func isTerminal(fd int) bool {
  15. _, err := unix.IoctlGetTermio(fd, unix.TCGETA)
  16. return err == nil
  17. }
  18. func readPassword(fd int) ([]byte, error) {
  19. // see also: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c
  20. val, err := unix.IoctlGetTermios(fd, unix.TCGETS)
  21. if err != nil {
  22. return nil, err
  23. }
  24. oldState := *val
  25. newState := oldState
  26. newState.Lflag &^= syscall.ECHO
  27. newState.Lflag |= syscall.ICANON | syscall.ISIG
  28. newState.Iflag |= syscall.ICRNL
  29. err = unix.IoctlSetTermios(fd, unix.TCSETS, &newState)
  30. if err != nil {
  31. return nil, err
  32. }
  33. defer unix.IoctlSetTermios(fd, unix.TCSETS, &oldState)
  34. var buf [16]byte
  35. var ret []byte
  36. for {
  37. n, err := syscall.Read(fd, buf[:])
  38. if err != nil {
  39. return nil, err
  40. }
  41. if n == 0 {
  42. if len(ret) == 0 {
  43. return nil, io.EOF
  44. }
  45. break
  46. }
  47. if buf[n-1] == '\n' {
  48. n--
  49. }
  50. ret = append(ret, buf[:n]...)
  51. if n < len(buf) {
  52. break
  53. }
  54. }
  55. return ret, nil
  56. }
  57. func makeRaw(fd int) (*State, error) {
  58. // see http://cr.illumos.org/~webrev/andy_js/1060/
  59. termios, err := unix.IoctlGetTermios(fd, unix.TCGETS)
  60. if err != nil {
  61. return nil, err
  62. }
  63. oldState := State{state{termios: *termios}}
  64. termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON
  65. termios.Oflag &^= unix.OPOST
  66. termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN
  67. termios.Cflag &^= unix.CSIZE | unix.PARENB
  68. termios.Cflag |= unix.CS8
  69. termios.Cc[unix.VMIN] = 1
  70. termios.Cc[unix.VTIME] = 0
  71. if err := unix.IoctlSetTermios(fd, unix.TCSETS, termios); err != nil {
  72. return nil, err
  73. }
  74. return &oldState, nil
  75. }
  76. func restore(fd int, oldState *State) error {
  77. return unix.IoctlSetTermios(fd, unix.TCSETS, &oldState.termios)
  78. }
  79. func getState(fd int) (*State, error) {
  80. termios, err := unix.IoctlGetTermios(fd, unix.TCGETS)
  81. if err != nil {
  82. return nil, err
  83. }
  84. return &State{state{termios: *termios}}, nil
  85. }
  86. func getSize(fd int) (width, height int, err error) {
  87. ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
  88. if err != nil {
  89. return 0, 0, err
  90. }
  91. return int(ws.Col), int(ws.Row), nil
  92. }