1// +build solaris 2 3// Copyright 2017 The TCell Authors 4// 5// Licensed under the Apache License, Version 2.0 (the "License"); 6// you may not use file except in compliance with the License. 7// You may obtain a copy of the license at 8// 9// http://www.apache.org/licenses/LICENSE-2.0 10// 11// Unless required by applicable law or agreed to in writing, software 12// distributed under the License is distributed on an "AS IS" BASIS, 13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14// See the License for the specific language governing permissions and 15// limitations under the License. 16 17package tcell 18 19import ( 20 "os" 21 "os/signal" 22 "syscall" 23 24 "golang.org/x/sys/unix" 25) 26 27type termiosPrivate struct { 28 tio *unix.Termios 29} 30 31const ( 32 // These are for missing CBAUDEXT and CIBAUDEXT. 33 // The values are fixed for Solaris and illumos, and cannot ever 34 // change without breaking applications. 35 cBaudExt = 0x200000 36 ciBaudExt = 0x400000 37) 38 39// getbaud is sort of cfgetospeed, but in Go. 40func getbaud(tios *unix.Termios) int { 41 // First we mask off the rate by looking at the Cflag. 42 bval := tios.Cflag & unix.CBAUD 43 if (tios.Cflag & cBaudExt) != 0 { 44 bval += unix.CBAUD + 1 45 } 46 47 // This gives us the appropriate BXXX value, so convert 48 switch bval { 49 case unix.B0: 50 return 0 51 case unix.B50: 52 return 50 53 case unix.B75: 54 return 75 55 case unix.B110: 56 return 110 57 case unix.B134: 58 return 134 59 case unix.B150: 60 return 150 61 case unix.B200: 62 return 200 63 case unix.B300: 64 return 300 65 case unix.B600: 66 return 600 67 case unix.B1200: 68 return 1200 69 case unix.B1800: 70 return 1800 71 case unix.B2400: 72 return 2400 73 case unix.B4800: 74 return 4800 75 case unix.B9600: 76 return 9600 77 case unix.B19200: 78 return 19200 79 case unix.B38400: 80 return 38400 81 case unix.B57600: 82 return 57600 83 case unix.B76800: 84 return 76800 85 case unix.B115200: 86 return 115200 87 case unix.B153600: 88 return 153600 89 case unix.B230400: 90 return 230400 91 case unix.B307200: 92 return 307200 93 case unix.B460800: 94 return 460800 95 case unix.B921600: 96 return 921600 97 } 98 return 0 99} 100 101func (t *tScreen) termioInit() error { 102 var e error 103 var raw *unix.Termios 104 var tio *unix.Termios 105 106 if t.in, e = os.OpenFile("/dev/tty", os.O_RDONLY, 0); e != nil { 107 goto failed 108 } 109 if t.out, e = os.OpenFile("/dev/tty", os.O_WRONLY, 0); e != nil { 110 goto failed 111 } 112 113 tio, e = unix.IoctlGetTermios(int(t.out.Fd()), unix.TCGETS) 114 if e != nil { 115 goto failed 116 } 117 118 t.tiosp = &termiosPrivate{tio: tio} 119 t.baud = getbaud(tio) 120 121 // make a local copy, to make it raw 122 raw = &unix.Termios{ 123 Cflag: tio.Cflag, 124 Oflag: tio.Oflag, 125 Iflag: tio.Iflag, 126 Lflag: tio.Lflag, 127 Cc: tio.Cc, 128 } 129 130 raw.Iflag &^= (unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.INLCR | 131 unix.IGNCR | unix.ICRNL | unix.IXON) 132 raw.Oflag &^= unix.OPOST 133 raw.Lflag &^= (unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN) 134 raw.Cflag &^= (unix.CSIZE | unix.PARENB) 135 raw.Cflag |= unix.CS8 136 137 // This is setup for blocking reads. In the past we attempted to 138 // use non-blocking reads, but now a separate input loop and timer 139 // copes with the problems we had on some systems (BSD/Darwin) 140 // where close hung forever. 141 raw.Cc[unix.VMIN] = 1 142 raw.Cc[unix.VTIME] = 0 143 144 e = unix.IoctlSetTermios(int(t.out.Fd()), unix.TCSETS, raw) 145 if e != nil { 146 goto failed 147 } 148 149 signal.Notify(t.sigwinch, syscall.SIGWINCH) 150 151 if w, h, e := t.getWinSize(); e == nil && w != 0 && h != 0 { 152 t.cells.Resize(w, h) 153 } 154 155 return nil 156 157failed: 158 if t.in != nil { 159 t.in.Close() 160 } 161 if t.out != nil { 162 t.out.Close() 163 } 164 return e 165} 166 167func (t *tScreen) termioFini() { 168 169 signal.Stop(t.sigwinch) 170 171 <-t.indoneq 172 173 if t.out != nil && t.tiosp != nil { 174 unix.IoctlSetTermios(int(t.out.Fd()), unix.TCSETSF, t.tiosp.tio) 175 t.out.Close() 176 } 177 if t.in != nil { 178 t.in.Close() 179 } 180} 181 182func (t *tScreen) getWinSize() (int, int, error) { 183 wsz, err := unix.IoctlGetWinsize(int(t.out.Fd()), unix.TIOCGWINSZ) 184 if err != nil { 185 return -1, -1, err 186 } 187 return int(wsz.Col), int(wsz.Row), nil 188} 189