1 /* $NetBSD: tty.c,v 1.8 1997/09/12 21:08:26 phil Exp $ */ 2 3 /*- 4 * Copyright (c) 1992, 1993, 1994 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <sys/cdefs.h> 37 #ifndef lint 38 #if 0 39 static char sccsid[] = "@(#)tty.c 8.5 (Berkeley) 8/13/94"; 40 #else 41 __RCSID("$NetBSD: tty.c,v 1.8 1997/09/12 21:08:26 phil Exp $"); 42 #endif 43 #endif /* not lint */ 44 45 #include <stdlib.h> 46 #include <termios.h> 47 #include <unistd.h> 48 49 #include "curses.h" 50 51 /* 52 * In general, curses should leave tty hardware settings alone (speed, parity, 53 * word size). This is most easily done in BSD by using TCSASOFT on all 54 * tcsetattr calls. On other systems, it would be better to get and restore 55 * those attributes at each change, or at least when stopped and restarted. 56 * See also the comments in getterm(). 57 */ 58 #ifdef TCSASOFT 59 int __tcaction = 1; /* Ignore hardware settings. */ 60 #else 61 int __tcaction = 0; 62 #endif 63 64 struct termios __orig_termios, __baset; 65 int __endwin; 66 static struct termios cbreakt, rawt, *curt; 67 static int useraw; 68 69 #ifndef OXTABS 70 #ifdef XTABS /* SMI uses XTABS. */ 71 #define OXTABS XTABS 72 #else 73 #define OXTABS 0 74 #endif 75 #endif 76 77 /* 78 * gettmode -- 79 * Do terminal type initialization. 80 */ 81 int 82 gettmode() 83 { 84 useraw = 0; 85 86 if (tcgetattr(STDIN_FILENO, &__orig_termios)) 87 return (ERR); 88 89 __baset = __orig_termios; 90 __baset.c_oflag &= ~OXTABS; 91 92 GT = 0; /* historical. was used before we wired OXTABS off */ 93 NONL = (__baset.c_oflag & ONLCR) == 0; 94 95 /* 96 * XXX 97 * System V and SMI systems overload VMIN and VTIME, such that 98 * VMIN is the same as the VEOF element, and VTIME is the same 99 * as the VEOL element. This means that, if VEOF was ^D, the 100 * default VMIN is 4. Majorly stupid. 101 */ 102 cbreakt = __baset; 103 cbreakt.c_lflag &= ~ICANON; 104 cbreakt.c_cc[VMIN] = 1; 105 cbreakt.c_cc[VTIME] = 0; 106 107 rawt = cbreakt; 108 rawt.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|INLCR|IGNCR|ICRNL|IXON); 109 rawt.c_oflag &= ~OPOST; 110 rawt.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); 111 112 /* 113 * In general, curses should leave hardware-related settings alone. 114 * This includes parity and word size. Older versions set the tty 115 * to 8 bits, no parity in raw(), but this is considered to be an 116 * artifact of the old tty interface. If it's desired to change 117 * parity and word size, the TCSASOFT bit has to be removed from the 118 * calls that switch to/from "raw" mode. 119 */ 120 if (!__tcaction) { 121 rawt.c_iflag &= ~ISTRIP; 122 rawt.c_cflag &= ~(CSIZE|PARENB); 123 rawt.c_cflag |= CS8; 124 } 125 126 curt = &__baset; 127 return (tcsetattr(STDIN_FILENO, __tcaction ? 128 TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK); 129 } 130 131 int 132 raw() 133 { 134 useraw = __pfast = __rawmode = 1; 135 curt = &rawt; 136 return (tcsetattr(STDIN_FILENO, __tcaction ? 137 TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK); 138 } 139 140 int 141 noraw() 142 { 143 useraw = __pfast = __rawmode = 0; 144 curt = &__baset; 145 return (tcsetattr(STDIN_FILENO, __tcaction ? 146 TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK); 147 } 148 149 int 150 cbreak() 151 { 152 153 __rawmode = 1; 154 curt = useraw ? &rawt : &cbreakt; 155 return (tcsetattr(STDIN_FILENO, __tcaction ? 156 TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK); 157 } 158 159 int 160 nocbreak() 161 { 162 163 __rawmode = 0; 164 curt = useraw ? &rawt : &__baset; 165 return (tcsetattr(STDIN_FILENO, __tcaction ? 166 TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK); 167 } 168 169 int 170 echo() 171 { 172 rawt.c_lflag |= ECHO; 173 cbreakt.c_lflag |= ECHO; 174 __baset.c_lflag |= ECHO; 175 176 __echoit = 1; 177 return (tcsetattr(STDIN_FILENO, __tcaction ? 178 TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK); 179 } 180 181 int 182 noecho() 183 { 184 rawt.c_lflag &= ~ECHO; 185 cbreakt.c_lflag &= ~ECHO; 186 __baset.c_lflag &= ~ECHO; 187 188 __echoit = 0; 189 return (tcsetattr(STDIN_FILENO, __tcaction ? 190 TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK); 191 } 192 193 int 194 nl() 195 { 196 rawt.c_iflag |= ICRNL; 197 rawt.c_oflag |= ONLCR; 198 cbreakt.c_iflag |= ICRNL; 199 cbreakt.c_oflag |= ONLCR; 200 __baset.c_iflag |= ICRNL; 201 __baset.c_oflag |= ONLCR; 202 203 __pfast = __rawmode; 204 return (tcsetattr(STDIN_FILENO, __tcaction ? 205 TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK); 206 } 207 208 int 209 nonl() 210 { 211 rawt.c_iflag &= ~ICRNL; 212 rawt.c_oflag &= ~ONLCR; 213 cbreakt.c_iflag &= ~ICRNL; 214 cbreakt.c_oflag &= ~ONLCR; 215 __baset.c_iflag &= ~ICRNL; 216 __baset.c_oflag &= ~ONLCR; 217 218 __pfast = 1; 219 return (tcsetattr(STDIN_FILENO, __tcaction ? 220 TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK); 221 } 222 223 void 224 __startwin() 225 { 226 static char *stdbuf; 227 static size_t len; 228 229 (void)fflush(stdout); 230 231 /* 232 * Some C libraries default to a 1K buffer when talking to a tty. 233 * With a larger screen, especially across a network, we'd like 234 * to get it to all flush in a single write. Make it twice as big 235 * as just the characters (so that we have room for cursor motions 236 * and standout information) but no more than 8K. 237 */ 238 if (stdbuf == NULL) { 239 if ((len = LINES * COLS * 2) > 8192) 240 len = 8192; 241 if ((stdbuf = malloc(len)) == NULL) 242 len = 0; 243 } 244 (void)setvbuf(stdout, stdbuf, _IOFBF, len); 245 246 tputs(TI, 0, __cputchar); 247 tputs(VS, 0, __cputchar); 248 } 249 250 int 251 endwin() 252 { 253 __endwin = 1; 254 return __stopwin(); 255 } 256 257 /* 258 * The following routines, savetty and resetty are completely useless and 259 * are left in only as stubs. If people actually use them they will almost 260 * certainly screw up the state of the world. 261 */ 262 static struct termios savedtty; 263 int 264 savetty() 265 { 266 return (tcgetattr(STDIN_FILENO, &savedtty) ? ERR : OK); 267 } 268 269 int 270 resetty() 271 { 272 return (tcsetattr(STDIN_FILENO, __tcaction ? 273 TCSASOFT | TCSADRAIN : TCSADRAIN, &savedtty) ? ERR : OK); 274 } 275