github.com/xyproto/u-root@v6.0.1-0.20200302025726-5528e0c77a3c+incompatible/pkg/termios/termios_linux.go (about) 1 // Copyright 2015-2017 the u-root 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 5 package termios 6 7 import ( 8 "fmt" 9 "os" 10 "os/exec" 11 "path/filepath" 12 "syscall" 13 14 "golang.org/x/sys/unix" 15 ) 16 17 // TTY is a wrapper that only allows Read and Write. 18 type TTY struct { 19 f *os.File 20 } 21 22 // New creates a new TTY using /dev/tty 23 func New() (*TTY, error) { 24 return NewWithDev("/dev/tty") 25 } 26 27 // NewWithDev creates a new TTY with the specified device 28 func NewWithDev(device string) (*TTY, error) { 29 f, err := os.OpenFile(device, os.O_RDWR, 0) 30 if err != nil { 31 return nil, err 32 } 33 return &TTY{f: f}, nil 34 } 35 36 func NewTTYS(port string) (*TTY, error) { 37 f, err := os.OpenFile(filepath.Join("/dev", port), unix.O_RDWR|unix.O_NOCTTY|unix.O_NONBLOCK, 0620) 38 if err != nil { 39 return nil, err 40 } 41 return &TTY{f: f}, nil 42 } 43 44 func (t *TTY) Read(b []byte) (int, error) { 45 return t.f.Read(b) 46 } 47 48 func (t *TTY) Write(b []byte) (int, error) { 49 return t.f.Write(b) 50 } 51 52 func GetTermios(fd uintptr) (*unix.Termios, error) { 53 return unix.IoctlGetTermios(int(fd), unix.TCGETS) 54 } 55 56 func (t *TTY) Get() (*unix.Termios, error) { 57 return GetTermios(t.f.Fd()) 58 } 59 60 func SetTermios(fd uintptr, ti *unix.Termios) error { 61 return unix.IoctlSetTermios(int(fd), unix.TCSETS, ti) 62 } 63 64 func (t *TTY) Set(ti *unix.Termios) error { 65 return SetTermios(t.f.Fd(), ti) 66 } 67 68 func GetWinSize(fd uintptr) (*unix.Winsize, error) { 69 return unix.IoctlGetWinsize(int(fd), unix.TIOCGWINSZ) 70 } 71 72 func (t *TTY) GetWinSize() (*unix.Winsize, error) { 73 return GetWinSize(t.f.Fd()) 74 } 75 76 func SetWinSize(fd uintptr, w *unix.Winsize) error { 77 return unix.IoctlSetWinsize(int(fd), unix.TIOCSWINSZ, w) 78 } 79 80 func (t *TTY) SetWinSize(w *unix.Winsize) error { 81 return SetWinSize(t.f.Fd(), w) 82 } 83 84 func (t *TTY) Ctty(c *exec.Cmd) { 85 c.Stdin, c.Stdout, c.Stderr = t.f, t.f, t.f 86 if c.SysProcAttr == nil { 87 c.SysProcAttr = &syscall.SysProcAttr{} 88 } 89 c.SysProcAttr.Setctty = true 90 c.SysProcAttr.Setsid = true 91 c.SysProcAttr.Ctty = int(t.f.Fd()) 92 } 93 94 func MakeRaw(term *unix.Termios) *unix.Termios { 95 raw := *term 96 raw.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON 97 raw.Oflag &^= unix.OPOST 98 raw.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN 99 raw.Cflag &^= unix.CSIZE | unix.PARENB 100 raw.Cflag |= unix.CS8 101 102 raw.Cc[unix.VMIN] = 1 103 raw.Cc[unix.VTIME] = 0 104 105 return &raw 106 } 107 108 // MakeSerialBaud updates the Termios to set the baudrate 109 func MakeSerialBaud(term *unix.Termios, baud int) (*unix.Termios, error) { 110 t := *term 111 rate, ok := baud2unixB[baud] 112 if !ok { 113 return nil, fmt.Errorf("%d: Unrecognized baud rate", baud) 114 } 115 116 t.Cflag &^= unix.CBAUD 117 t.Cflag |= rate 118 t.Ispeed = rate 119 t.Ospeed = rate 120 121 return &t, nil 122 } 123 124 // MakeSerialDefault updates the Termios to typical serial configuration: 125 // - Ignore all flow control (modem, hardware, software...) 126 // - Translate carriage return to newline on input 127 // - Enable canonical mode: Input is available line by line, with line editing 128 // enabled (ERASE, KILL are supported) 129 // - Local ECHO is added (and handled by line editing) 130 // - Map newline to carriage return newline on output 131 func MakeSerialDefault(term *unix.Termios) *unix.Termios { 132 t := *term 133 /* Clear all except baud, stop bit and parity settings */ 134 t.Cflag &= unix.CBAUD | unix.CSTOPB | unix.PARENB | unix.PARODD 135 /* Set: 8 bits; ignore Carrier Detect; enable receive */ 136 t.Cflag |= unix.CS8 | unix.CLOCAL | unix.CREAD 137 t.Iflag = unix.ICRNL 138 t.Lflag = unix.ICANON | unix.ISIG | unix.ECHO | unix.ECHOE | unix.ECHOK | unix.ECHOKE | unix.ECHOCTL 139 /* non-raw output; add CR to each NL */ 140 t.Oflag = unix.OPOST | unix.ONLCR 141 /* reads will block only if < 1 char is available */ 142 t.Cc[unix.VMIN] = 1 143 /* no timeout (reads block forever) */ 144 t.Cc[unix.VTIME] = 0 145 t.Line = 0 146 147 return &t 148 }