1package term 2 3import ( 4 "errors" 5 "io" 6 "os" 7 "syscall" 8 9 "github.com/pkg/term/termios" 10) 11 12type Term struct { 13} 14 15var errNotSupported = errors.New("not supported") 16 17// Open opens an asynchronous communications port. 18func Open(name string, options ...func(*Term) error) (*Term, error) { 19 return nil, errNotSupported 20} 21 22// SetOption takes one or more option function and applies them in order to Term. 23func (t *Term) SetOption(options ...func(*Term) error) error { 24 for _, opt := range options { 25 if err := opt(t); err != nil { 26 return err 27 } 28 } 29 return nil 30} 31 32// Read reads up to len(b) bytes from the terminal. It returns the number of 33// bytes read and an error, if any. EOF is signaled by a zero count with 34// err set to io.EOF. 35func (t *Term) Read(b []byte) (int, error) { 36 n, e := syscall.Read(t.fd, b) 37 if n < 0 { 38 n = 0 39 } 40 if n == 0 && len(b) > 0 && e == nil { 41 return 0, io.EOF 42 } 43 if e != nil { 44 return n, &os.PathError{"read", t.name, e} 45 } 46 return n, nil 47} 48 49// Write writes len(b) bytes to the terminal. It returns the number of bytes 50// written and an error, if any. Write returns a non-nil error when n != 51// len(b). 52func (t *Term) Write(b []byte) (int, error) { 53 n, e := syscall.Write(t.fd, b) 54 if n < 0 { 55 n = 0 56 } 57 if n != len(b) { 58 return n, io.ErrShortWrite 59 } 60 if e != nil { 61 return n, &os.PathError{"write", t.name, e} 62 } 63 return n, nil 64} 65 66// Close closes the device and releases any associated resources. 67func (t *Term) Close() error { 68 err := syscall.Close(t.fd) 69 t.fd = -1 70 return err 71} 72 73// SetCbreak sets cbreak mode. 74func (t *Term) SetCbreak() error { 75 return t.SetOption(CBreakMode) 76} 77 78// CBreakMode places the terminal into cbreak mode. 79func CBreakMode(t *Term) error { 80 var a attr 81 if err := termios.Tcgetattr(uintptr(t.fd), (*syscall.Termios)(&a)); err != nil { 82 return err 83 } 84 termios.Cfmakecbreak((*syscall.Termios)(&a)) 85 return termios.Tcsetattr(uintptr(t.fd), termios.TCSANOW, (*syscall.Termios)(&a)) 86} 87 88// SetRaw sets raw mode. 89func (t *Term) SetRaw() error { 90 return t.SetOption(RawMode) 91} 92 93// RawMode places the terminal into raw mode. 94func RawMode(t *Term) error { 95 var a attr 96 if err := termios.Tcgetattr(uintptr(t.fd), (*syscall.Termios)(&a)); err != nil { 97 return err 98 } 99 termios.Cfmakeraw((*syscall.Termios)(&a)) 100 return termios.Tcsetattr(uintptr(t.fd), termios.TCSANOW, (*syscall.Termios)(&a)) 101} 102 103// Speed sets the baud rate option for the terminal. 104func Speed(baud int) func(*Term) error { 105 return func(t *Term) error { 106 return t.setSpeed(baud) 107 } 108} 109 110// SetSpeed sets the receive and transmit baud rates. 111func (t *Term) SetSpeed(baud int) error { 112 return t.SetOption(Speed(baud)) 113} 114 115func (t *Term) setSpeed(baud int) error { 116 var a attr 117 if err := termios.Tcgetattr(uintptr(t.fd), (*syscall.Termios)(&a)); err != nil { 118 return err 119 } 120 a.setSpeed(baud) 121 return termios.Tcsetattr(uintptr(t.fd), termios.TCSANOW, (*syscall.Termios)(&a)) 122} 123 124// Flush flushes both data received but not read, and data written but not transmitted. 125func (t *Term) Flush() error { 126 return termios.Tcflush(uintptr(t.fd), termios.TCIOFLUSH) 127} 128 129// SendBreak sends a break signal. 130func (t *Term) SendBreak() error { 131 return termios.Tcsendbreak(uintptr(t.fd), 0) 132} 133 134// SetDTR sets the DTR (data terminal ready) signal. 135func (t *Term) SetDTR(v bool) error { 136 bits := syscall.TIOCM_DTR 137 if v { 138 return termios.Tiocmbis(uintptr(t.fd), &bits) 139 } else { 140 return termios.Tiocmbic(uintptr(t.fd), &bits) 141 } 142} 143 144// DTR returns the state of the DTR (data terminal ready) signal. 145func (t *Term) DTR() (bool, error) { 146 var status int 147 err := termios.Tiocmget(uintptr(t.fd), &status) 148 return status&syscall.TIOCM_DTR == syscall.TIOCM_DTR, err 149} 150 151// SetRTS sets the RTS (data terminal ready) signal. 152func (t *Term) SetRTS(v bool) error { 153 bits := syscall.TIOCM_RTS 154 if v { 155 return termios.Tiocmbis(uintptr(t.fd), &bits) 156 } else { 157 return termios.Tiocmbic(uintptr(t.fd), &bits) 158 } 159} 160 161// RTS returns the state of the RTS (data terminal ready) signal. 162func (t *Term) RTS() (bool, error) { 163 var status int 164 err := termios.Tiocmget(uintptr(t.fd), &status) 165 return status&syscall.TIOCM_RTS == syscall.TIOCM_RTS, err 166} 167 168// Restore restores the state of the terminal captured at the point that 169// the terminal was originally opened. 170func (t *Term) Restore() error { 171 return termios.Tcsetattr(uintptr(t.fd), termios.TCIOFLUSH, &t.orig) 172} 173