pax_global_header00006660000000000000000000000064137275511010014514gustar00rootroot0000000000000052 comment=d02e49dd31404f3c3cf4b5469b28942194e0ca23 term-1.1.0/000077500000000000000000000000001372755110100124625ustar00rootroot00000000000000term-1.1.0/.github/000077500000000000000000000000001372755110100140225ustar00rootroot00000000000000term-1.1.0/.github/workflows/000077500000000000000000000000001372755110100160575ustar00rootroot00000000000000term-1.1.0/.github/workflows/test.yml000066400000000000000000000006461372755110100175670ustar00rootroot00000000000000on: [push, pull_request] name: Test jobs: test: strategy: matrix: go-version: [1.14.x, 1.15.x] platform: [ubuntu-latest, macos-latest] runs-on: ${{ matrix.platform }} steps: - name: Install Go uses: actions/setup-go@v2 with: go-version: ${{ matrix.go-version }} - name: Checkout code uses: actions/checkout@v2 - name: Test run: go test ./... term-1.1.0/.travis.yml000066400000000000000000000001611372755110100145710ustar00rootroot00000000000000language: go go_import_path: github.com/pkg/term go: - 1.13.x - 1.14.x - tip script: - go test -v ./... term-1.1.0/LICENSE000066400000000000000000000024131372755110100134670ustar00rootroot00000000000000Copyright (c) 2014, David Cheney All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. term-1.1.0/README.md000066400000000000000000000063621372755110100137500ustar00rootroot00000000000000 # term import "github.com/pkg/term" Package term manages POSIX terminals. As POSIX terminals are connected to, or emulate, a UART, this package also provides control over the various UART and serial line parameters. ## func CBreakMode ``` go func CBreakMode(t *Term) error ``` CBreakMode places the terminal into cbreak mode. ## func RawMode ``` go func RawMode(t *Term) error ``` RawMode places the terminal into raw mode. ## func Speed ``` go func Speed(baud int) func(*Term) error ``` Speed sets the baud rate option for the terminal. ## type Term ``` go type Term struct { // contains filtered or unexported fields } ``` Term represents an asynchronous communications port. ### func Open ``` go func Open(name string, options ...func(*Term) error) (*Term, error) ``` Open opens an asynchronous communications port. ### func (\*Term) Available ``` go func (t *Term) Available() (int, error) ``` Available returns how many bytes are unused in the buffer. ### func (\*Term) Buffered ``` go func (t *Term) Buffered() (int, error) ``` Buffered returns the number of bytes that have been written into the current buffer. ### func (\*Term) Close ``` go func (t *Term) Close() error ``` Close closes the device and releases any associated resources. ### func (\*Term) DTR ``` go func (t *Term) DTR() (bool, error) ``` DTR returns the state of the DTR (data terminal ready) signal. ### func (\*Term) Flush ``` go func (t *Term) Flush() error ``` Flush flushes both data received but not read, and data written but not transmitted. ### func (\*Term) RTS ``` go func (t *Term) RTS() (bool, error) ``` RTS returns the state of the RTS (data terminal ready) signal. ### func (\*Term) Read ``` go func (t *Term) Read(b []byte) (int, error) ``` Read reads up to len(b) bytes from the terminal. It returns the number of bytes read and an error, if any. EOF is signaled by a zero count with err set to io.EOF. ### func (\*Term) Restore ``` go func (t *Term) Restore() error ``` Restore restores the state of the terminal captured at the point that the terminal was originally opened. ### func (\*Term) SendBreak ``` go func (t *Term) SendBreak() error ``` SendBreak sends a break signal. ### func (\*Term) SetCbreak ``` go func (t *Term) SetCbreak() error ``` SetCbreak sets cbreak mode. ### func (\*Term) SetDTR ``` go func (t *Term) SetDTR(v bool) error ``` SetDTR sets the DTR (data terminal ready) signal. ### func (\*Term) SetOption ``` go func (t *Term) SetOption(options ...func(*Term) error) error ``` SetOption takes one or more option function and applies them in order to Term. ### func (\*Term) SetRTS ``` go func (t *Term) SetRTS(v bool) error ``` SetRTS sets the RTS (data terminal ready) signal. ### func (\*Term) SetRaw ``` go func (t *Term) SetRaw() error ``` SetRaw sets raw mode. ### func (\*Term) SetSpeed ``` go func (t *Term) SetSpeed(baud int) error ``` SetSpeed sets the receive and transmit baud rates. ### func (\*Term) Write ``` go func (t *Term) Write(b []byte) (int, error) ``` Write writes len(b) bytes to the terminal. It returns the number of bytes written and an error, if any. Write returns a non-nil error when n != len(b). - - - Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md)term-1.1.0/example_test.go000066400000000000000000000012771372755110100155120ustar00rootroot00000000000000// +build !windows package term import ( "log" "time" ) // Open a terminal in raw mode at 19200 baud. func ExampleOpen() { Open("/dev/ttyUSB0", Speed(19200), RawMode) } // Reset an Arduino by toggling the DTR signal. func ExampleTerm_SetDTR() { t, _ := Open("/dev/USB0") t.SetDTR(false) // toggle DTR low time.Sleep(250 * time.Millisecond) t.SetDTR(true) // raise DTR, resets Ardunio } // Send Break to the remote DTE. func ExampleTerm_SendBreak() { t, _ := Open("/dev/ttyUSB0") for { time.Sleep(3 * time.Second) log.Println("Break...") t.SendBreak() } } // Restore the terminal state func ExampleTerm_Restore() { t, _ := Open("/dev/tty") // mutate terminal state t.Restore() } term-1.1.0/go.mod000066400000000000000000000001411372755110100135640ustar00rootroot00000000000000module github.com/pkg/term go 1.14 require golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 term-1.1.0/go.sum000066400000000000000000000006361372755110100136220ustar00rootroot00000000000000golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 h1:W0lCpv29Hv0UaM1LXb9QlBHLNP8UFfcKjblhVCWftOM= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= term-1.1.0/term.go000066400000000000000000000035041372755110100137620ustar00rootroot00000000000000// +build !windows // Package term manages POSIX terminals. As POSIX terminals are connected to, // or emulate, a UART, this package also provides control over the various // UART and serial line parameters. package term import ( "errors" "io" "os" "github.com/pkg/term/termios" "golang.org/x/sys/unix" ) const ( NONE = iota // flow control off XONXOFF // software flow control HARDWARE // hardware flow control ) var errNotSupported = errors.New("not supported") // Read reads up to len(b) bytes from the terminal. It returns the number of // bytes read and an error, if any. EOF is signaled by a zero count with // err set to io.EOF. func (t *Term) Read(b []byte) (int, error) { n, e := unix.Read(t.fd, b) if n < 0 { n = 0 } if n == 0 && len(b) > 0 && e == nil { return 0, io.EOF } if e != nil { return n, &os.PathError{"read", t.name, e} } return n, nil } // SetOption takes one or more option function and applies them in order to Term. func (t *Term) SetOption(options ...func(*Term) error) error { for _, opt := range options { if err := opt(t); err != nil { return err } } return nil } // Write writes len(b) bytes to the terminal. It returns the number of bytes // written and an error, if any. Write returns a non-nil error when n != // len(b). func (t *Term) Write(b []byte) (int, error) { n, e := unix.Write(t.fd, b) if n < 0 { n = 0 } if n != len(b) { return n, io.ErrShortWrite } if e != nil { return n, &os.PathError{"write", t.name, e} } return n, nil } // Available returns how many bytes are unused in the buffer. func (t *Term) Available() (int, error) { return termios.Tiocinq(uintptr(t.fd)) } // Buffered returns the number of bytes that have been written into the current buffer. func (t *Term) Buffered() (int, error) { return termios.Tiocoutq(uintptr(t.fd)) } term-1.1.0/term_bsdi.go000066400000000000000000000035121372755110100147620ustar00rootroot00000000000000// +build netbsd openbsd package term import "golang.org/x/sys/unix" type attr unix.Termios func (a *attr) getSpeed() (int, error) { // We generally only care about ospeed, since that's what would // be used for padding characters, for example. switch a.Ospeed { case syscall.B50: return 50, nil case syscall.B75: return 75, nil case syscall.B110: return 110, nil case syscall.B134: return 134, nil case syscall.B150: return 150, nil case syscall.B200: return 200, nil case syscall.B300: return 300, nil case syscall.B600: return 600, nil case syscall.B1200: return 1200, nil case syscall.B1800: return 1800, nil case syscall.B2400: return 2400, nil case syscall.B4800: return 4800, nil case syscall.B9600: return 9600, nil case syscall.B19200: return 19200, nil case syscall.B38400: return 38400, nil case syscall.B57600: return 57600, nil case syscall.B115200: return 115200, nil case syscall.B230400: return 230400, nil default: return 0, syscall.EINVAL } } func (a *attr) setSpeed(baud int) error { var rate int32 switch baud { case 50: rate = unix.B50 case 75: rate = unix.B75 case 110: rate = unix.B110 case 134: rate = unix.B134 case 150: rate = unix.B150 case 200: rate = unix.B200 case 300: rate = unix.B300 case 600: rate = unix.B600 case 1200: rate = unix.B1200 case 1800: rate = unix.B1800 case 2400: rate = unix.B2400 case 4800: rate = unix.B4800 case 9600: rate = unix.B9600 case 19200: rate = unix.B19200 case 38400: rate = unix.B38400 case 57600: rate = unix.B57600 case 115200: rate = unix.B115200 case 230400: rate = unix.B230400 default: return unix.EINVAL } (*unix.Termios)(a).Cflag = unix.CS8 | unix.CREAD | unix.CLOCAL | uint32(rate) (*unix.Termios)(a).Ispeed = rate (*unix.Termios)(a).Ospeed = rate return nil } term-1.1.0/term_bsdu.go000066400000000000000000000035061372755110100150010ustar00rootroot00000000000000// +build dragonfly freebsd package term import "golang.org/x/sys/unix" type attr unix.Termios func (a *attr) getSpeed() (int, error) { // We generally only care about ospeed, since that's what would // be used for padding characters, for example. switch a.Ospeed { case syscall.B50: return 50, nil case syscall.B75: return 75, nil case syscall.B110: return 110, nil case syscall.B134: return 134, nil case syscall.B150: return 150, nil case syscall.B200: return 200, nil case syscall.B300: return 300, nil case syscall.B600: return 600, nil case syscall.B1200: return 1200, nil case syscall.B1800: return 1800, nil case syscall.B2400: return 2400, nil case syscall.B4800: return 4800, nil case syscall.B9600: return 9600, nil case syscall.B19200: return 19200, nil case syscall.B38400: return 38400, nil case syscall.B57600: return 57600, nil case syscall.B115200: return 115200, nil case syscall.B230400: return 230400, nil default: return 0, syscall.EINVAL } } func (a *attr) setSpeed(baud int) error { var rate uint32 switch baud { case 50: rate = unix.B50 case 75: rate = unix.B75 case 110: rate = unix.B110 case 134: rate = unix.B134 case 150: rate = unix.B150 case 200: rate = unix.B200 case 300: rate = unix.B300 case 600: rate = unix.B600 case 1200: rate = unix.B1200 case 1800: rate = unix.B1800 case 2400: rate = unix.B2400 case 4800: rate = unix.B4800 case 9600: rate = unix.B9600 case 19200: rate = unix.B19200 case 38400: rate = unix.B38400 case 57600: rate = unix.B57600 case 115200: rate = unix.B115200 case 230400: rate = unix.B230400 default: return unix.EINVAL } (*unix.Termios)(a).Cflag = unix.CS8 | unix.CREAD | unix.CLOCAL | rate (*unix.Termios)(a).Ispeed = rate (*unix.Termios)(a).Ospeed = rate return nil } term-1.1.0/term_darwin.go000066400000000000000000000033601372755110100153260ustar00rootroot00000000000000package term import "golang.org/x/sys/unix" type attr unix.Termios func (a *attr) getSpeed() (int, error) { // We generally only care about ospeed, since that's what would // be used for padding characters, for example. switch a.Ospeed { case unix.B50: return 50, nil case unix.B75: return 75, nil case unix.B110: return 110, nil case unix.B134: return 134, nil case unix.B150: return 150, nil case unix.B200: return 200, nil case unix.B300: return 300, nil case unix.B600: return 600, nil case unix.B1200: return 1200, nil case unix.B1800: return 1800, nil case unix.B2400: return 2400, nil case unix.B4800: return 4800, nil case unix.B9600: return 9600, nil case unix.B19200: return 19200, nil case unix.B38400: return 38400, nil case unix.B57600: return 57600, nil case unix.B115200: return 115200, nil case unix.B230400: return 230400, nil default: return 0, unix.EINVAL } } func (a *attr) setSpeed(baud int) error { var rate uint64 switch baud { case 50: rate = unix.B50 case 75: rate = unix.B75 case 110: rate = unix.B110 case 134: rate = unix.B134 case 150: rate = unix.B150 case 200: rate = unix.B200 case 300: rate = unix.B300 case 600: rate = unix.B600 case 1200: rate = unix.B1200 case 1800: rate = unix.B1800 case 2400: rate = unix.B2400 case 4800: rate = unix.B4800 case 9600: rate = unix.B9600 case 19200: rate = unix.B19200 case 38400: rate = unix.B38400 case 57600: rate = unix.B57600 case 115200: rate = unix.B115200 case 230400: rate = unix.B230400 default: return unix.EINVAL } (*unix.Termios)(a).Cflag = unix.CS8 | unix.CREAD | unix.CLOCAL | rate (*unix.Termios)(a).Ispeed = rate (*unix.Termios)(a).Ospeed = rate return nil } term-1.1.0/term_linux.go000066400000000000000000000065321372755110100152050ustar00rootroot00000000000000package term import "golang.org/x/sys/unix" type attr unix.Termios const ( // CBaudMask is the logical of CBAUD and CBAUDEX, except // that those values were not exposed via the syscall // package. Many of these values will be redundant, but // this long definition ensures we are portable if some // architecture defines different values for them (unlikely). CBaudMask = unix.B50 | unix.B75 | unix.B110 | unix.B134 | unix.B150 | unix.B200 | unix.B300 | unix.B600 | unix.B1200 | unix.B1800 | unix.B2400 | unix.B4800 | unix.B9600 | unix.B19200 | unix.B38400 | unix.B57600 | unix.B115200 | unix.B230400 | unix.B460800 | unix.B500000 | unix.B576000 | unix.B921600 | unix.B1000000 | unix.B1152000 | unix.B1500000 | unix.B2000000 | unix.B2500000 | unix.B3000000 | unix.B3500000 | unix.B4000000 ) func (a *attr) getSpeed() (int, error) { switch a.Cflag & CBaudMask { case unix.B50: return 50, nil case unix.B75: return 75, nil case unix.B110: return 110, nil case unix.B134: return 134, nil case unix.B150: return 150, nil case unix.B200: return 200, nil case unix.B300: return 300, nil case unix.B600: return 600, nil case unix.B1200: return 1200, nil case unix.B1800: return 1800, nil case unix.B2400: return 2400, nil case unix.B4800: return 4800, nil case unix.B9600: return 9600, nil case unix.B19200: return 19200, nil case unix.B38400: return 38400, nil case unix.B57600: return 57600, nil case unix.B115200: return 115200, nil case unix.B230400: return 230400, nil case unix.B460800: return 460800, nil case unix.B500000: return 500000, nil case unix.B576000: return 576000, nil case unix.B921600: return 921600, nil case unix.B1000000: return 1000000, nil case unix.B1152000: return 1152000, nil case unix.B1500000: return 1500000, nil case unix.B2000000: return 2000000, nil case unix.B2500000: return 2500000, nil case unix.B3000000: return 3000000, nil case unix.B3500000: return 3500000, nil case unix.B4000000: return 4000000, nil default: return 0, unix.EINVAL } } func (a *attr) setSpeed(baud int) error { var rate uint32 switch baud { case 50: rate = unix.B50 case 75: rate = unix.B75 case 110: rate = unix.B110 case 134: rate = unix.B134 case 150: rate = unix.B150 case 200: rate = unix.B200 case 300: rate = unix.B300 case 600: rate = unix.B600 case 1200: rate = unix.B1200 case 1800: rate = unix.B1800 case 2400: rate = unix.B2400 case 4800: rate = unix.B4800 case 9600: rate = unix.B9600 case 19200: rate = unix.B19200 case 38400: rate = unix.B38400 case 57600: rate = unix.B57600 case 115200: rate = unix.B115200 case 230400: rate = unix.B230400 case 460800: rate = unix.B460800 case 500000: rate = unix.B500000 case 576000: rate = unix.B576000 case 921600: rate = unix.B921600 case 1000000: rate = unix.B1000000 case 1152000: rate = unix.B1152000 case 1500000: rate = unix.B1500000 case 2000000: rate = unix.B2000000 case 2500000: rate = unix.B2500000 case 3000000: rate = unix.B3000000 case 3500000: rate = unix.B3500000 case 4000000: rate = unix.B4000000 default: return unix.EINVAL } (*unix.Termios)(a).Cflag = unix.CS8 | unix.CREAD | unix.CLOCAL | rate (*unix.Termios)(a).Ispeed = rate (*unix.Termios)(a).Ospeed = rate return nil } term-1.1.0/term_open_posix.go000066400000000000000000000015111372755110100162210ustar00rootroot00000000000000// +build !windows,!solaris package term import ( "os" "github.com/pkg/term/termios" "golang.org/x/sys/unix" ) // Open opens an asynchronous communications port. func Open(name string, options ...func(*Term) error) (*Term, error) { fd, e := unix.Open(name, unix.O_NOCTTY|unix.O_CLOEXEC|unix.O_NDELAY|unix.O_RDWR, 0666) if e != nil { return nil, &os.PathError{"open", name, e} } t := Term{name: name, fd: fd} if err := termios.Tcgetattr(uintptr(t.fd), &t.orig); err != nil { return nil, err } if err := t.SetOption(options...); err != nil { return nil, err } return &t, unix.SetNonblock(t.fd, false) } // Restore restores the state of the terminal captured at the point that // the terminal was originally opened. func (t *Term) Restore() error { return termios.Tcsetattr(uintptr(t.fd), termios.TCIOFLUSH, &t.orig) } term-1.1.0/term_posix.go000066400000000000000000000122151372755110100152030ustar00rootroot00000000000000// +build !windows package term import ( "time" "github.com/pkg/term/termios" "golang.org/x/sys/unix" ) // Term represents an asynchronous communications port. type Term struct { name string fd int orig unix.Termios // original state of the terminal, see Open and Restore } // SetCbreak sets cbreak mode. func (t *Term) SetCbreak() error { return t.SetOption(CBreakMode) } // CBreakMode places the terminal into cbreak mode. func CBreakMode(t *Term) error { var a attr if err := termios.Tcgetattr(uintptr(t.fd), (*unix.Termios)(&a)); err != nil { return err } termios.Cfmakecbreak((*unix.Termios)(&a)) return termios.Tcsetattr(uintptr(t.fd), termios.TCSANOW, (*unix.Termios)(&a)) } // SetRaw sets raw mode. func (t *Term) SetRaw() error { return t.SetOption(RawMode) } // RawMode places the terminal into raw mode. func RawMode(t *Term) error { var a attr if err := termios.Tcgetattr(uintptr(t.fd), (*unix.Termios)(&a)); err != nil { return err } termios.Cfmakeraw((*unix.Termios)(&a)) return termios.Tcsetattr(uintptr(t.fd), termios.TCSANOW, (*unix.Termios)(&a)) } // Speed sets the baud rate option for the terminal. func Speed(baud int) func(*Term) error { return func(t *Term) error { return t.setSpeed(baud) } } // SetSpeed sets the receive and transmit baud rates. func (t *Term) SetSpeed(baud int) error { return t.SetOption(Speed(baud)) } func (t *Term) setSpeed(baud int) error { var a attr if err := termios.Tcgetattr(uintptr(t.fd), (*unix.Termios)(&a)); err != nil { return err } a.setSpeed(baud) return termios.Tcsetattr(uintptr(t.fd), termios.TCSANOW, (*unix.Termios)(&a)) } // GetSpeed gets the current output baud rate. func (t *Term) GetSpeed() (int, error) { var a attr if err := termios.Tcgetattr(uintptr(t.fd), (*unix.Termios)(&a)); err != nil { return 0, err } return a.getSpeed() } func clamp(v, lo, hi int64) int64 { if v < lo { return lo } if v > hi { return hi } return v } // timeoutVals converts d into values suitable for termios VMIN and VTIME ctrl chars func timeoutVals(d time.Duration) (uint8, uint8) { if d > 0 { // VTIME is expressed in terms of deciseconds vtimeDeci := d.Nanoseconds() / 1e6 / 100 // ensure valid range vtime := uint8(clamp(vtimeDeci, 1, 0xff)) return 0, vtime } // block indefinitely until we receive at least 1 byte return 1, 0 } // ReadTimeout sets the read timeout option for the terminal. func ReadTimeout(d time.Duration) func(*Term) error { return func(t *Term) error { return t.setReadTimeout(d) } } // SetReadTimeout sets the read timeout. // A zero value for d means read operations will not time out. func (t *Term) SetReadTimeout(d time.Duration) error { return t.SetOption(ReadTimeout(d)) } func (t *Term) setReadTimeout(d time.Duration) error { var a attr if err := termios.Tcgetattr(uintptr(t.fd), (*unix.Termios)(&a)); err != nil { return err } a.Cc[unix.VMIN], a.Cc[unix.VTIME] = timeoutVals(d) return termios.Tcsetattr(uintptr(t.fd), termios.TCSANOW, (*unix.Termios)(&a)) } // FlowControl sets the flow control option for the terminal. func FlowControl(kind int) func(*Term) error { return func(t *Term) error { return t.setFlowControl(kind) } } // SetFlowControl sets whether hardware flow control is enabled. func (t *Term) SetFlowControl(kind int) error { return t.SetOption(FlowControl(kind)) } func (t *Term) setFlowControl(kind int) error { var a attr if err := termios.Tcgetattr(uintptr(t.fd), (*unix.Termios)(&a)); err != nil { return err } switch kind { case NONE: a.Iflag &^= termios.IXON | termios.IXOFF | termios.IXANY a.Cflag &^= termios.CRTSCTS case XONXOFF: a.Cflag &^= termios.CRTSCTS a.Iflag |= termios.IXON | termios.IXOFF | termios.IXANY case HARDWARE: a.Iflag &^= termios.IXON | termios.IXOFF | termios.IXANY a.Cflag |= termios.CRTSCTS } return termios.Tcsetattr(uintptr(t.fd), termios.TCSANOW, (*unix.Termios)(&a)) } // Flush flushes both data received but not read, and data written but not transmitted. func (t *Term) Flush() error { return termios.Tcflush(uintptr(t.fd), termios.TCIOFLUSH) } // SendBreak sends a break signal. func (t *Term) SendBreak() error { return termios.Tcsendbreak(uintptr(t.fd), 0) } // SetDTR sets the DTR (data terminal ready) signal. func (t *Term) SetDTR(v bool) error { bits := unix.TIOCM_DTR if v { return termios.Tiocmbis(uintptr(t.fd), bits) } else { return termios.Tiocmbic(uintptr(t.fd), bits) } } // DTR returns the state of the DTR (data terminal ready) signal. func (t *Term) DTR() (bool, error) { status, err := termios.Tiocmget(uintptr(t.fd)) return status&unix.TIOCM_DTR == unix.TIOCM_DTR, err } // SetRTS sets the RTS (data terminal ready) signal. func (t *Term) SetRTS(v bool) error { bits := unix.TIOCM_RTS if v { return termios.Tiocmbis(uintptr(t.fd), bits) } else { return termios.Tiocmbic(uintptr(t.fd), bits) } } // RTS returns the state of the RTS (data terminal ready) signal. func (t *Term) RTS() (bool, error) { status, err := termios.Tiocmget(uintptr(t.fd)) return status&unix.TIOCM_RTS == unix.TIOCM_RTS, err } // Close closes the device and releases any associated resources. func (t *Term) Close() error { err := unix.Close(t.fd) t.fd = -1 return err } term-1.1.0/term_solaris.go000066400000000000000000000062761372755110100155270ustar00rootroot00000000000000package term // #include import "C" import ( "os" "syscall" "unsafe" "github.com/pkg/term/termios" "golang.org/x/sys/unix" ) type attr unix.Termios func (a *attr) getSpeed() (int, error) { // We generally only care about ospeed, since that's what would // be used for padding characters, for example. rate := termios.Cfgetospeed((*syscall.Termios)(a)) switch rate { case syscall.B50: return 50, nil case syscall.B75: return 75, nil case syscall.B110: return 110, nil case syscall.B134: return 134, nil case syscall.B150: return 150, nil case syscall.B200: return 200, nil case syscall.B300: return 300, nil case syscall.B600: return 600, nil case syscall.B1200: return 1200, nil case syscall.B1800: return 1800, nil case syscall.B2400: return 2400, nil case syscall.B4800: return 4800, nil case syscall.B9600: return 9600, nil case syscall.B19200: return 19200, nil case syscall.B38400: return 38400, nil case syscall.B57600: return 57600, nil case syscall.B115200: return 115200, nil case syscall.B230400: return 230400, nil case syscall.B460800: return 460800, nil case syscall.B500000: return 500000, nil case syscall.B576000: return 576000, nil case syscall.B921600: return 921600, nil default: return 0, syscall.EINVAL } } func (a *attr) setSpeed(baud int) error { var rate uint32 switch baud { case 50: rate = unix.B50 case 75: rate = unix.B75 case 110: rate = unix.B110 case 134: rate = unix.B134 case 150: rate = unix.B150 case 200: rate = unix.B200 case 300: rate = unix.B300 case 600: rate = unix.B600 case 1200: rate = unix.B1200 case 1800: rate = unix.B1800 case 2400: rate = unix.B2400 case 4800: rate = unix.B4800 case 9600: rate = unix.B9600 case 19200: rate = unix.B19200 case 38400: rate = unix.B38400 case 57600: rate = unix.B57600 case 115200: rate = unix.B115200 case 230400: rate = unix.B230400 case 460800: rate = unix.B460800 case 921600: rate = unix.B921600 default: return unix.EINVAL } err := termios.Cfsetispeed((*unix.Termios)(a), uintptr(rate)) if err != nil { return err } err = termios.Cfsetospeed((*unix.Termios)(a), uintptr(rate)) if err != nil { return err } return nil } // Open opens an asynchronous communications port. func Open(name string, options ...func(*Term) error) (*Term, error) { fd, e := unix.Open(name, unix.O_NOCTTY|unix.O_CLOEXEC|unix.O_NDELAY|unix.O_RDWR, 0666) if e != nil { return nil, &os.PathError{"open", name, e} } modules := [2]string{"ptem", "ldterm"} for _, mod := range modules { err := unix.IoctlSetInt(fd, C.I_PUSH, int(uintptr(unsafe.Pointer(unix.StringBytePtr(mod))))) if err != nil { return nil, err } } t := Term{name: name, fd: fd} termios.Tcgetattr(uintptr(t.fd), &t.orig) if err := termios.Tcgetattr(uintptr(t.fd), &t.orig); err != nil { return nil, err } if err := t.SetOption(options...); err != nil { return nil, err } return &t, unix.SetNonblock(t.fd, false) } // Restore restores the state of the terminal captured at the point that // the terminal was originally opened. func (t *Term) Restore() error { return termios.Tcsetattr(uintptr(t.fd), termios.TCSANOW, &t.orig) } term-1.1.0/term_test.go000066400000000000000000000035521372755110100150240ustar00rootroot00000000000000// +build !windows package term import ( "testing" "time" "github.com/pkg/term/termios" ) // assert that Term implements the same method set across // all supported platforms var _ interface { Available() (int, error) Buffered() (int, error) Close() error DTR() (bool, error) Flush() error RTS() (bool, error) Read(b []byte) (int, error) Restore() error SendBreak() error SetCbreak() error SetDTR(v bool) error SetOption(options ...func(*Term) error) error SetRTS(v bool) error SetRaw() error SetSpeed(baud int) error GetSpeed() (int, error) Write(b []byte) (int, error) } = new(Term) func TestTermSetCbreak(t *testing.T) { tt := opendev(t) defer tt.Close() if err := tt.SetCbreak(); err != nil { t.Fatal(err) } } func TestTermSetRaw(t *testing.T) { tt := opendev(t) defer tt.Close() if err := tt.SetRaw(); err != nil { t.Fatal(err) } } func TestTermSetSpeed(t *testing.T) { tt := opendev(t) defer tt.Close() if err := tt.SetSpeed(57600); err != nil { t.Fatal(err) } if spd, err := tt.GetSpeed(); err != nil { t.Fatal(err) } else if spd != 57600 { t.Errorf("speed mismatch %d != 57600", spd) } } func TestTermSetReadTimeout(t *testing.T) { tt := opendev(t) defer tt.Close() if err := tt.SetReadTimeout(1 * time.Second); err != nil { t.Fatal(err) } } func TestTermSetFlowControl(t *testing.T) { tt := opendev(t) defer tt.Close() kinds := []int{XONXOFF, NONE, HARDWARE, NONE, XONXOFF, HARDWARE, NONE} for _, kind := range kinds { if err := tt.SetFlowControl(kind); err != nil { t.Fatal(err) } } } func TestTermRestore(t *testing.T) { tt := opendev(t) defer tt.Close() if err := tt.Restore(); err != nil { t.Fatal(err) } } func opendev(t *testing.T) *Term { _, pts, err := termios.Pty() if err != nil { t.Fatal(err) } term, err := Open(pts.Name()) if err != nil { t.Fatal(err) } pts.Close() return term } term-1.1.0/term_windows.go000066400000000000000000000054421372755110100155370ustar00rootroot00000000000000package term import ( "errors" ) type Term struct { } var errNotSupported = errors.New("not supported") // Open opens an asynchronous communications port. func Open(name string, options ...func(*Term) error) (*Term, error) { return nil, errNotSupported } // SetOption takes one or more option function and applies them in order to Term. func (t *Term) SetOption(options ...func(*Term) error) error { return errNotSupported } // Read reads up to len(b) bytes from the terminal. It returns the number of // bytes read and an error, if any. EOF is signaled by a zero count with // err set to io.EOF. func (t *Term) Read(b []byte) (int, error) { return 0, errNotSupported } // Write writes len(b) bytes to the terminal. It returns the number of bytes // written and an error, if any. Write returns a non-nil error when n != // len(b). func (t *Term) Write(b []byte) (int, error) { return 0, errNotSupported } // Close closes the device and releases any associated resources. func (t *Term) Close() error { return errNotSupported } // SetCbreak sets cbreak mode. func (t *Term) SetCbreak() error { return errNotSupported } // CBreakMode places the terminal into cbreak mode. func CBreakMode(t *Term) error { return errNotSupported } // SetRaw sets raw mode. func (t *Term) SetRaw() error { return errNotSupported } // RawMode places the terminal into raw mode. func RawMode(t *Term) error { return errNotSupported } // Speed sets the baud rate option for the terminal. func Speed(baud int) func(*Term) error { return func(*Term) error { return errNotSupported } } // SetSpeed sets the receive and transmit baud rates. func (t *Term) SetSpeed(baud int) error { return errNotSupported } // GetSpeed gets the transmit baud rate. func (t *Term) GetSpeed() (int, error) { var a attr if err := termios.Tcgetattr(uintptr(t.fd), (*syscall.Termios)(&a)); err != nil { return 0, err } return a.getSpeed() } // Flush flushes both data received but not read, and data written but not transmitted. func (t *Term) Flush() error { return errNotSupported } // SendBreak sends a break signal. func (t *Term) SendBreak() error { return errNotSupported } // SetDTR sets the DTR (data terminal ready) signal. func (t *Term) SetDTR(v bool) error { return errNotSupported } // DTR returns the state of the DTR (data terminal ready) signal. func (t *Term) DTR() (bool, error) { return false, errNotSupported } // SetRTS sets the RTS (data terminal ready) signal. func (t *Term) SetRTS(v bool) error { return errNotSupported } // RTS returns the state of the RTS (data terminal ready) signal. func (t *Term) RTS() (bool, error) { return false, errNotSupported } // Restore restores the state of the terminal captured at the point that // the terminal was originally opened. func (t *Term) Restore() error { return errNotSupported } term-1.1.0/termios/000077500000000000000000000000001372755110100141445ustar00rootroot00000000000000term-1.1.0/termios/doc.go000066400000000000000000000002731372755110100152420ustar00rootroot00000000000000// Package termios implements the low level termios(3) terminal line discipline facilities. // // For a higher level interface please use the github.com/pkg/term package. package termios term-1.1.0/termios/ioctl.go000066400000000000000000000003771372755110100156140ustar00rootroot00000000000000// +build !windows,!solaris package termios import ( "syscall" "golang.org/x/sys/unix" ) func ioctl(fd, request, argp uintptr) error { if _, _, e := unix.Syscall6(syscall.SYS_IOCTL, fd, request, argp, 0, 0, 0); e != 0 { return e } return nil } term-1.1.0/termios/ioctl_darwin.go000066400000000000000000000002711372755110100171510ustar00rootroot00000000000000package termios const ( _IOC_PARAM_SHIFT = 13 _IOC_PARAM_MASK = (1 << _IOC_PARAM_SHIFT) - 1 ) func _IOC_PARM_LEN(ioctl uintptr) uintptr { return (ioctl >> 16) & _IOC_PARAM_MASK } term-1.1.0/termios/ioctl_solaris.go000066400000000000000000000002351372755110100173410ustar00rootroot00000000000000package termios import "golang.org/x/sys/unix" func ioctl(fd, request, argp uintptr) error { return unix.IoctlSetInt(int(fd), uint(request), int(argp)) } term-1.1.0/termios/pty.go000066400000000000000000000016151372755110100153120ustar00rootroot00000000000000// +build !windows package termios import ( "fmt" "os" "golang.org/x/sys/unix" ) func open_device(path string) (uintptr, error) { fd, err := unix.Open(path, unix.O_NOCTTY|unix.O_RDWR|unix.O_CLOEXEC, 0666) if err != nil { return 0, fmt.Errorf("unable to open %q: %v", path, err) } return uintptr(fd), nil } // Pty returns a UNIX 98 pseudoterminal device. // Pty returns a pair of fds representing the master and slave pair. func Pty() (*os.File, *os.File, error) { ptm, err := open_pty_master() if err != nil { return nil, nil, err } sname, err := Ptsname(ptm) if err != nil { return nil, nil, err } err = grantpt(ptm) if err != nil { return nil, nil, err } err = unlockpt(ptm) if err != nil { return nil, nil, err } pts, err := open_device(sname) if err != nil { return nil, nil, err } return os.NewFile(uintptr(ptm), "ptm"), os.NewFile(uintptr(pts), sname), nil } term-1.1.0/termios/pty_bsd.go000066400000000000000000000011641372755110100161410ustar00rootroot00000000000000// +build dragonfly openbsd package termios // #include import "C" import "syscall" func open_pty_master() (uintptr, error) { rc := C.posix_openpt(syscall.O_NOCTTY | syscall.O_RDWR) if rc < 0 { return 0, syscall.Errno(rc) } return uintptr(rc), nil } func Ptsname(fd uintptr) (string, error) { slavename := C.GoString(C.ptsname(C.int(fd))) return slavename, nil } func grantpt(fd uintptr) error { rc := C.grantpt(C.int(fd)) if rc == 0 { return nil } return syscall.Errno(rc) } func unlockpt(fd uintptr) error { rc := C.unlockpt(C.int(fd)) if rc == 0 { return nil } return syscall.Errno(rc) } term-1.1.0/termios/pty_darwin.go000066400000000000000000000012511372755110100166520ustar00rootroot00000000000000package termios import ( "errors" "unsafe" "golang.org/x/sys/unix" ) func open_pty_master() (uintptr, error) { return open_device("/dev/ptmx") } func Ptsname(fd uintptr) (string, error) { n := make([]byte, _IOC_PARM_LEN(unix.TIOCPTYGNAME)) err := ioctl(fd, unix.TIOCPTYGNAME, uintptr(unsafe.Pointer(&n[0]))) if err != nil { return "", err } for i, c := range n { if c == 0 { return string(n[:i]), nil } } return "", errors.New("TIOCPTYGNAME string not NUL-terminated") } func grantpt(fd uintptr) error { return unix.IoctlSetInt(int(fd), unix.TIOCPTYGRANT, 0) } func unlockpt(fd uintptr) error { return unix.IoctlSetInt(int(fd), unix.TIOCPTYUNLK, 0) } term-1.1.0/termios/pty_freebsd.go000066400000000000000000000013641372755110100170050ustar00rootroot00000000000000package termios import ( "fmt" "unsafe" ) func posix_openpt(oflag int) (fd uintptr, err error) { // Copied from debian-golang-pty/pty_freebsd.go. r0, _, e1 := unix.Syscall(unix.SYS_POSIX_OPENPT, uintptr(oflag), 0, 0) fd = uintptr(r0) if e1 != 0 { err = e1 } return } func open_pty_master() (uintptr, error) { return posix_openpt(unix.O_NOCTTY | unix.O_RDWR | unix.O_CLOEXEC) } func Ptsname(fd uintptr) (string, error) { var n uintptr err := ioctl(fd, unix.TIOCGPTN, uintptr(unsafe.Pointer(&n))) if err != nil { return "", err } return fmt.Sprintf("/dev/pts/%d", n), nil } func grantpt(fd uintptr) error { var n uintptr return ioctl(fd, unix.TIOCGPTN, uintptr(unsafe.Pointer(&n))) } func unlockpt(fd uintptr) error { return nil } term-1.1.0/termios/pty_linux.go000066400000000000000000000011051372755110100165230ustar00rootroot00000000000000package termios import ( "fmt" "unsafe" "golang.org/x/sys/unix" ) func open_pty_master() (uintptr, error) { return open_device("/dev/ptmx") } func Ptsname(fd uintptr) (string, error) { var n uintptr err := ioctl(fd, unix.TIOCGPTN, uintptr(unsafe.Pointer(&n))) if err != nil { return "", err } return fmt.Sprintf("/dev/pts/%d", n), nil } func grantpt(fd uintptr) error { var n uintptr return ioctl(fd, unix.TIOCGPTN, uintptr(unsafe.Pointer(&n))) } func unlockpt(fd uintptr) error { var n uintptr return ioctl(fd, unix.TIOCSPTLCK, uintptr(unsafe.Pointer(&n))) } term-1.1.0/termios/pty_netbsd.go000066400000000000000000000011041372755110100166420ustar00rootroot00000000000000package termios import ( "bytes" "golang.org/x/sys/unix" ) func open_pty_master() (uintptr, error) { fd, err := unix.Open("/dev/ptmx", unix.O_NOCTTY|unix.O_RDWR, 0666) if err != nil { return 0, err } return uintptr(fd), nil } func Ptsname(fd uintptr) (string, error) { ptm, err := unix.IoctlGetPtmget(int(fd), unix.TIOCPTSNAME) if err != nil { return "", err } return string(ptm.Sn[:bytes.IndexByte(ptm.Sn[:], 0)]), nil } func grantpt(fd uintptr) error { return unix.IoctlSetInt(int(fd), unix.TIOCGRANTPT, 0) } func unlockpt(fd uintptr) error { return nil } term-1.1.0/termios/pty_solaris.go000066400000000000000000000010161372755110100170410ustar00rootroot00000000000000package termios // #include import "C" import "syscall" func open_pty_master() (uintptr, error) { return open_device("/dev/ptmx") } func Ptsname(fd uintptr) (string, error) { slavename := C.GoString(C.ptsname(C.int(fd))) return slavename, nil } func grantpt(fd uintptr) error { rc := C.grantpt(C.int(fd)) if rc == 0 { return nil } else { return syscall.Errno(rc) } } func unlockpt(fd uintptr) error { rc := C.unlockpt(C.int(fd)) if rc == 0 { return nil } else { return syscall.Errno(rc) } } term-1.1.0/termios/termios.go000066400000000000000000000023141372755110100161550ustar00rootroot00000000000000// +build !windows package termios import ( "golang.org/x/sys/unix" ) // Tiocmget returns the state of the MODEM bits. func Tiocmget(fd uintptr) (int, error) { return unix.IoctlGetInt(int(fd), unix.TIOCMGET) } // Tiocmset sets the state of the MODEM bits. func Tiocmset(fd uintptr, status int) error { return unix.IoctlSetInt(int(fd), unix.TIOCMSET, status) } // Tiocmbis sets the indicated modem bits. func Tiocmbis(fd uintptr, status int) error { return unix.IoctlSetPointerInt(int(fd), unix.TIOCMBIS, status) } // Tiocmbic clears the indicated modem bits. func Tiocmbic(fd uintptr, status int) error { return unix.IoctlSetPointerInt(int(fd), unix.TIOCMBIC, status) } // Cfmakecbreak modifies attr for cbreak mode. func Cfmakecbreak(attr *unix.Termios) { attr.Lflag &^= unix.ECHO | unix.ICANON attr.Cc[unix.VMIN] = 1 attr.Cc[unix.VTIME] = 0 } // Cfmakeraw modifies attr for raw mode. func Cfmakeraw(attr *unix.Termios) { attr.Iflag &^= unix.BRKINT | unix.ICRNL | unix.INPCK | unix.ISTRIP | unix.IXON attr.Oflag &^= unix.OPOST attr.Cflag &^= unix.CSIZE | unix.PARENB attr.Cflag |= unix.CS8 attr.Lflag &^= unix.ECHO | unix.ICANON | unix.IEXTEN | unix.ISIG attr.Cc[unix.VMIN] = 1 attr.Cc[unix.VTIME] = 0 } term-1.1.0/termios/termios_bsd.go000066400000000000000000000046401372755110100170110ustar00rootroot00000000000000// +build darwin freebsd openbsd netbsd dragonfly package termios import ( "time" "golang.org/x/sys/unix" ) const ( FREAD = 0x0001 FWRITE = 0x0002 IXON = 0x00000200 IXOFF = 0x00000400 IXANY = 0x00000800 CCTS_OFLOW = 0x00010000 CRTS_IFLOW = 0x00020000 CRTSCTS = CCTS_OFLOW | CRTS_IFLOW ) // Tcgetattr gets the current serial port settings. func Tcgetattr(fd uintptr, argp *unix.Termios) error { return unix.IoctlSetTermios(int(fd), unix.TIOCGETA, argp) } // Tcsetattr sets the current serial port settings. func Tcsetattr(fd, opt uintptr, argp *unix.Termios) error { switch opt { case TCSANOW: opt = unix.TIOCSETA case TCSADRAIN: opt = unix.TIOCSETAW case TCSAFLUSH: opt = unix.TIOCSETAF default: return unix.EINVAL } return unix.IoctlSetTermios(int(fd), uint(opt), argp) } // Tcsendbreak function transmits a continuous stream of zero-valued bits for // four-tenths of a second to the terminal referenced by fildes. The duration // parameter is ignored in this implementation. func Tcsendbreak(fd, duration uintptr) error { if err := unix.IoctlSetInt(int(fd), unix.TIOCSBRK, 0); err != nil { return err } time.Sleep(4 / 10 * time.Second) return unix.IoctlSetInt(int(fd), unix.TIOCCBRK, 0) } // Tcdrain waits until all output written to the terminal referenced by fd has been transmitted to the terminal. func Tcdrain(fd uintptr) error { return unix.IoctlSetInt(int(fd), unix.TIOCDRAIN, 0) } // Tcflush discards data written to the object referred to by fd but not transmitted, or data received but not read, depending on the value of which. func Tcflush(fd, which uintptr) error { var com int switch which { case unix.TCIFLUSH: com = FREAD case unix.TCOFLUSH: com = FWRITE case unix.TCIOFLUSH: com = FREAD | FWRITE default: return unix.EINVAL } return unix.IoctlSetPointerInt(int(fd), unix.TIOCFLUSH, com) } // Cfgetispeed returns the input baud rate stored in the termios structure. func Cfgetispeed(attr *unix.Termios) uint32 { return uint32(attr.Ispeed) } // Cfgetospeed returns the output baud rate stored in the termios structure. func Cfgetospeed(attr *unix.Termios) uint32 { return uint32(attr.Ospeed) } // Tiocinq returns the number of bytes in the input buffer. func Tiocinq(fd uintptr) (int, error) { return 0, nil } // Tiocoutq return the number of bytes in the output buffer. func Tiocoutq(fd uintptr) (int, error) { return unix.IoctlGetInt(int(fd), unix.TIOCOUTQ) } term-1.1.0/termios/termios_bsd_test.go000066400000000000000000000004061372755110100200440ustar00rootroot00000000000000// +build darwin freebsd openbsd netbsd dragonfly package termios import ( "testing" "golang.org/x/sys/unix" ) func TestTcflush(t *testing.T) { f := opendev(t) defer f.Close() if err := Tcflush(f.Fd(), unix.TCIOFLUSH); err != nil { t.Fatal(err) } } term-1.1.0/termios/termios_const.go000066400000000000000000000002231372755110100173600ustar00rootroot00000000000000// +build !windows,!solaris package termios const ( TCIFLUSH = 0 TCOFLUSH = 1 TCIOFLUSH = 2 TCSANOW = 0 TCSADRAIN = 1 TCSAFLUSH = 2 ) term-1.1.0/termios/termios_const_solaris.go000066400000000000000000000003211372755110100211130ustar00rootroot00000000000000package termios // #include import "C" const ( TCIFLUSH = C.TCIFLUSH TCOFLUSH = C.TCOFLUSH TCIOFLUSH = C.TCIOFLUSH TCSANOW = C.TCSANOW TCSADRAIN = C.TCSADRAIN TCSAFLUSH = C.TCSAFLUSH ) term-1.1.0/termios/termios_linux.go000066400000000000000000000044761372755110100174070ustar00rootroot00000000000000package termios import ( "golang.org/x/sys/unix" ) const ( TCSETS = 0x5402 TCSETSW = 0x5403 TCSETSF = 0x5404 TCFLSH = 0x540B TCSBRK = 0x5409 TCSBRKP = 0x5425 IXON = 0x00000400 IXANY = 0x00000800 IXOFF = 0x00001000 CRTSCTS = 0x80000000 ) // Tcgetattr gets the current serial port settings. func Tcgetattr(fd uintptr, argp *unix.Termios) error { return unix.IoctlSetTermios(int(fd), unix.TCGETS, argp) } // Tcsetattr sets the current serial port settings. func Tcsetattr(fd, action uintptr, argp *unix.Termios) error { var request uintptr switch action { case TCSANOW: request = TCSETS case TCSADRAIN: request = TCSETSW case TCSAFLUSH: request = TCSETSF default: return unix.EINVAL } return unix.IoctlSetTermios(int(fd), uint(request), argp) } // Tcsendbreak transmits a continuous stream of zero-valued bits for a specific // duration, if the terminal is using asynchronous serial data transmission. If // duration is zero, it transmits zero-valued bits for at least 0.25 seconds, and not more that 0.5 seconds. // If duration is not zero, it sends zero-valued bits for some // implementation-defined length of time. func Tcsendbreak(fd, duration uintptr) error { return ioctl(fd, TCSBRKP, duration) } // Tcdrain waits until all output written to the object referred to by fd has been transmitted. func Tcdrain(fd uintptr) error { // simulate drain with TCSADRAIN var attr unix.Termios if err := Tcgetattr(fd, &attr); err != nil { return err } return Tcsetattr(fd, TCSADRAIN, &attr) } // Tcflush discards data written to the object referred to by fd but not transmitted, or data received but not read, depending on the value of selector. func Tcflush(fd, selector uintptr) error { return ioctl(fd, TCFLSH, selector) } // Tiocinq returns the number of bytes in the input buffer. func Tiocinq(fd uintptr) (int, error) { return unix.IoctlGetInt(int(fd), unix.TIOCINQ) } // Tiocoutq return the number of bytes in the output buffer. func Tiocoutq(fd uintptr) (int, error) { return unix.IoctlGetInt(int(fd), unix.TIOCOUTQ) } // Cfgetispeed returns the input baud rate stored in the termios structure. func Cfgetispeed(attr *unix.Termios) uint32 { return attr.Ispeed } // Cfgetospeed returns the output baud rate stored in the termios structure. func Cfgetospeed(attr *unix.Termios) uint32 { return attr.Ospeed } term-1.1.0/termios/termios_linux_test.go000066400000000000000000000002571372755110100204370ustar00rootroot00000000000000package termios import "testing" func TestTcflush(t *testing.T) { f := opendev(t) defer f.Close() if err := Tcflush(f.Fd(), TCIOFLUSH); err != nil { t.Fatal(err) } } term-1.1.0/termios/termios_solaris.go000066400000000000000000000072311372755110100177140ustar00rootroot00000000000000package termios // #include // typedef struct termios termios_t; import "C" import ( "golang.org/x/sys/unix" "unsafe" ) const ( TCSETS = 0x5402 TCSETSW = 0x5403 TCSETSF = 0x5404 TCFLSH = 0x540B TCSBRK = 0x5409 TCSBRKP = 0x5425 IXON = 0x00000400 IXANY = 0x00000800 IXOFF = 0x00001000 CRTSCTS = 0x80000000 ) // See /usr/include/sys/termios.h const FIORDCHK = C.FIORDCHK // Tcgetattr gets the current serial port settings. func Tcgetattr(fd uintptr, argp *unix.Termios) error { termios, err := unix.IoctlGetTermios(int(fd), unix.TCGETS) *argp = *(tiosTounix(termios)) return err } // Tcsetattr sets the current serial port settings. func Tcsetattr(fd, action uintptr, argp *unix.Termios) error { return unix.IoctlSetTermios(int(fd), uint(action), tiosToUnix(argp)) } // Tcsendbreak transmits a continuous stream of zero-valued bits for a specific // duration, if the terminal is using asynchronous serial data transmission. If // duration is zero, it transmits zero-valued bits for at least 0.25 seconds, and not more that 0.5 seconds. // If duration is not zero, it sends zero-valued bits for some // implementation-defined length of time. func Tcsendbreak(fd, duration uintptr) error { return ioctl(fd, TCSBRKP, duration) } // Tcdrain waits until all output written to the object referred to by fd has been transmitted. func Tcdrain(fd uintptr) error { // simulate drain with TCSADRAIN var attr unix.Termios if err := Tcgetattr(fd, &attr); err != nil { return err } return Tcsetattr(fd, TCSADRAIN, &attr) } // Tcflush discards data written to the object referred to by fd but not transmitted, or data received but not read, depending on the value of selector. func Tcflush(fd, selector uintptr) error { return ioctl(fd, TCFLSH, selector) } // Tiocinq returns the number of bytes in the input buffer. func Tiocinq(fd uintptr, argp *int) (err error) { *argp, err = unix.IoctlGetInt(int(fd), FIORDCHK) return err } // Tiocoutq return the number of bytes in the output buffer. func Tiocoutq(fd uintptr, argp *int) error { return ioctl(fd, unix.TIOCOUTQ, uintptr(unsafe.Pointer(argp))) } // Cfgetispeed returns the input baud rate stored in the termios structure. func Cfgetispeed(attr *unix.Termios) uint32 { solTermios := tiosToUnix(attr) return uint32(C.cfgetispeed((*C.termios_t)(unsafe.Pointer(solTermios)))) } // Cfsetispeed sets the input baud rate stored in the termios structure. func Cfsetispeed(attr *unix.Termios, speed uintptr) error { solTermios := tiosToUnix(attr) _, err := C.cfsetispeed((*C.termios_t)(unsafe.Pointer(solTermios)), C.speed_t(speed)) return err } // Cfgetospeed returns the output baud rate stored in the termios structure. func Cfgetospeed(attr *unix.Termios) uint32 { solTermios := tiosToUnix(attr) return uint32(C.cfgetospeed((*C.termios_t)(unsafe.Pointer(solTermios)))) } // Cfsetospeed sets the output baud rate stored in the termios structure. func Cfsetospeed(attr *unix.Termios, speed uintptr) error { solTermios := tiosToUnix(attr) _, err := C.cfsetospeed((*C.termios_t)(unsafe.Pointer(solTermios)), C.speed_t(speed)) return err } // tiosToUnix copies a unix.Termios to a x/sys/unix.Termios. // This is needed since type conversions between the two fail due to // more recent x/sys/unix.Termios renaming the padding field. func tiosToUnix(st *unix.Termios) *unix.Termios { return &unix.Termios{ Iflag: st.Iflag, Oflag: st.Oflag, Cflag: st.Cflag, Lflag: st.Lflag, Cc: st.Cc, } } // tiosTounix copies a x/sys/unix.Termios to a unix.Termios. func tiosTounix(ut *unix.Termios) *unix.Termios { return &unix.Termios{ Iflag: ut.Iflag, Oflag: ut.Oflag, Cflag: ut.Cflag, Lflag: ut.Lflag, Cc: ut.Cc, } } term-1.1.0/termios/termios_test.go000066400000000000000000000056771372755110100172330ustar00rootroot00000000000000// +build !windows package termios import ( "flag" "os" "runtime" "testing" "golang.org/x/sys/unix" ) var dev = flag.String("device", "/dev/tty", "device to use") func TestTcgetattr(t *testing.T) { f := opendev(t) defer f.Close() var termios unix.Termios if err := Tcgetattr(f.Fd(), &termios); err != nil { t.Fatal(err) } } func TestTcsetattr(t *testing.T) { f := opendev(t) defer f.Close() var termios unix.Termios if err := Tcgetattr(f.Fd(), &termios); err != nil { t.Fatal(err) } for _, opt := range []uintptr{TCSANOW, TCSADRAIN, TCSAFLUSH} { if err := Tcsetattr(f.Fd(), opt, &termios); err != nil { t.Fatal(err) } } } func TestTcsendbreak(t *testing.T) { f := opendev(t) defer f.Close() if err := Tcsendbreak(f.Fd(), 0); err != nil { t.Fatal(err) } } func TestTcdrain(t *testing.T) { f := opendev(t) defer f.Close() if err := Tcdrain(f.Fd()); err != nil { t.Fatal(err) } } func TestTiocmget(t *testing.T) { f := opendev(t) defer f.Close() if _, err := Tiocmget(f.Fd()); err != nil { checktty(t, err) t.Fatal(err) } } func TestTiocmset(t *testing.T) { f := opendev(t) defer f.Close() status, err := Tiocmget(f.Fd()) if err != nil { checktty(t, err) t.Fatal(err) } if err := Tiocmset(f.Fd(), status); err != nil { checktty(t, err) t.Fatal(err) } } func TestTiocmbis(t *testing.T) { f := opendev(t) defer f.Close() if err := Tiocmbis(f.Fd(), 0); err != nil { checktty(t, err) t.Fatal(err) } } func TestTiocmbic(t *testing.T) { f := opendev(t) defer f.Close() if err := Tiocmbic(f.Fd(), 0); err != nil { checktty(t, err) t.Fatal(err) } } func TestTiocinq(t *testing.T) { f := opendev(t) defer f.Close() inq, err := Tiocinq(f.Fd()) if err != nil { t.Fatal(err) } if inq != 0 { t.Fatalf("Expected 0 bytes, got %v", inq) } } func TestTiocoutq(t *testing.T) { f := opendev(t) defer f.Close() inq, err := Tiocoutq(f.Fd()) if err != nil { t.Fatal(err) } if inq != 0 { t.Fatalf("Expected 0 bytes, got %v", inq) } } func TestCfgetispeed(t *testing.T) { f := opendev(t) defer f.Close() var termios unix.Termios if err := Tcgetattr(f.Fd(), &termios); err != nil { t.Fatal(err) } if baud := Cfgetispeed(&termios); baud == 0 && runtime.GOOS != "linux" { t.Fatalf("Cfgetispeed: expected > 0, got %v", baud) } } func TestCfgetospeed(t *testing.T) { f := opendev(t) defer f.Close() var termios unix.Termios if err := Tcgetattr(f.Fd(), &termios); err != nil { t.Fatal(err) } if baud := Cfgetospeed(&termios); baud == 0 && runtime.GOOS != "linux" { t.Fatalf("Cfgetospeed: expected > 0, got %v", baud) } } func opendev(t *testing.T) *os.File { _, pts, err := Pty() if err != nil { t.Fatal(err) } return pts } func checktty(t *testing.T, err error) { // some ioctls fail against char devices if they do not // support a particular feature if (runtime.GOOS == "darwin" && err == unix.ENOTTY) || (runtime.GOOS == "linux" && err == unix.EINVAL) { t.Skip(err) } } term-1.1.0/termios/termios_windows.go000066400000000000000000000000201372755110100177170ustar00rootroot00000000000000package termios