term.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. package term
  2. import (
  3. "syscall"
  4. "unsafe"
  5. )
  6. type Termios struct {
  7. Iflag uintptr
  8. Oflag uintptr
  9. Cflag uintptr
  10. Lflag uintptr
  11. Cc [20]byte
  12. Ispeed uintptr
  13. Ospeed uintptr
  14. }
  15. const (
  16. // Input flags
  17. inpck = 0x010
  18. istrip = 0x020
  19. icrnl = 0x100
  20. ixon = 0x200
  21. // Output flags
  22. opost = 0x1
  23. // Control flags
  24. cs8 = 0x300
  25. // Local flags
  26. icanon = 0x100
  27. iexten = 0x400
  28. )
  29. const (
  30. HUPCL = 0x4000
  31. ICANON = 0x100
  32. ICRNL = 0x100
  33. IEXTEN = 0x400
  34. BRKINT = 0x2
  35. CFLUSH = 0xf
  36. CLOCAL = 0x8000
  37. CREAD = 0x800
  38. CS5 = 0x0
  39. CS6 = 0x100
  40. CS7 = 0x200
  41. CS8 = 0x300
  42. CSIZE = 0x300
  43. CSTART = 0x11
  44. CSTATUS = 0x14
  45. CSTOP = 0x13
  46. CSTOPB = 0x400
  47. CSUSP = 0x1a
  48. IGNBRK = 0x1
  49. IGNCR = 0x80
  50. IGNPAR = 0x4
  51. IMAXBEL = 0x2000
  52. INLCR = 0x40
  53. INPCK = 0x10
  54. ISIG = 0x80
  55. ISTRIP = 0x20
  56. IUTF8 = 0x4000
  57. IXANY = 0x800
  58. IXOFF = 0x400
  59. IXON = 0x200
  60. NOFLSH = 0x80000000
  61. OCRNL = 0x10
  62. OFDEL = 0x20000
  63. OFILL = 0x80
  64. ONLCR = 0x2
  65. ONLRET = 0x40
  66. ONOCR = 0x20
  67. ONOEOT = 0x8
  68. OPOST = 0x1
  69. RENB = 0x1000
  70. PARMRK = 0x8
  71. PARODD = 0x2000
  72. TOSTOP = 0x400000
  73. VDISCARD = 0xf
  74. VDSUSP = 0xb
  75. VEOF = 0x0
  76. VEOL = 0x1
  77. VEOL2 = 0x2
  78. VERASE = 0x3
  79. VINTR = 0x8
  80. VKILL = 0x5
  81. VLNEXT = 0xe
  82. VMIN = 0x10
  83. VQUIT = 0x9
  84. VREPRINT = 0x6
  85. VSTART = 0xc
  86. VSTATUS = 0x12
  87. VSTOP = 0xd
  88. VSUSP = 0xa
  89. VT0 = 0x0
  90. VT1 = 0x10000
  91. VTDLY = 0x10000
  92. VTIME = 0x11
  93. ECHO = 0x00000008
  94. PENDIN = 0x20000000
  95. )
  96. type State struct {
  97. termios Termios
  98. }
  99. // IsTerminal returns true if the given file descriptor is a terminal.
  100. func IsTerminal(fd int) bool {
  101. var termios Termios
  102. _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(getTermios), uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
  103. return err == 0
  104. }
  105. // MakeRaw put the terminal connected to the given file descriptor into raw
  106. // mode and returns the previous state of the terminal so that it can be
  107. // restored.
  108. func MakeRaw(fd int) (*State, error) {
  109. var oldState State
  110. if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(getTermios), uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 {
  111. return nil, err
  112. }
  113. newState := oldState.termios
  114. newState.Iflag &^= ISTRIP | INLCR | IGNCR | IXON | IXOFF
  115. newState.Iflag |= ICRNL
  116. newState.Oflag |= ONLCR
  117. newState.Lflag &^= ECHO | ICANON | ISIG
  118. if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(setTermios), uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 {
  119. return nil, err
  120. }
  121. return &oldState, nil
  122. }
  123. // Restore restores the terminal connected to the given file descriptor to a
  124. // previous state.
  125. func Restore(fd int, state *State) error {
  126. _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(setTermios), uintptr(unsafe.Pointer(&state.termios)), 0, 0, 0)
  127. return err
  128. }