1 /*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 /*static char sccsid[] = "from: @(#)set.c 5.3 (Berkeley) 12/1/92";*/ 36 static char rcsid[] = "$Id: set.c,v 1.5 1994/03/13 14:29:34 cgd Exp $"; 37 #endif /* not lint */ 38 39 #include <termios.h> 40 #include <unistd.h> 41 #include <stdio.h> 42 #include "extern.h" 43 44 #define CHK(val, dft) (val <= 0 ? dft : val) 45 46 int set_tabs __P((void)); 47 48 /* 49 * Reset the terminal mode bits to a sensible state. Very useful after 50 * a child program dies in raw mode. 51 */ 52 void 53 reset_mode() 54 { 55 tcgetattr(STDERR_FILENO, &mode); 56 57 #if defined(VDISCARD) && defined(CDISCARD) 58 mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD); 59 #endif 60 mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF); 61 mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE); 62 #if defined(VFLUSH) && defined(CFLUSH) 63 mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH); 64 #endif 65 mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR); 66 mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL); 67 #if defined(VLNEXT) && defined(CLNEXT) 68 mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT); 69 #endif 70 mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT); 71 #if defined(VREPRINT) && defined(CRPRNT) 72 mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT); 73 #endif 74 mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART); 75 mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP); 76 mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP); 77 #if defined(VWERASE) && defined(CWERASE) 78 mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE); 79 #endif 80 81 mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR 82 #ifdef IUCLC 83 | IUCLC 84 #endif 85 #ifdef IXANY 86 | IXANY 87 #endif 88 | IXOFF); 89 90 mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON 91 #ifdef IMAXBEL 92 | IMAXBEL 93 #endif 94 ); 95 96 mode.c_oflag &= ~(0 97 #ifdef OLCUC 98 | OLCUC 99 #endif 100 #ifdef OCRNL 101 | OCRNL 102 #endif 103 #ifdef ONOCR 104 | ONOCR 105 #endif 106 #ifdef ONLRET 107 | ONLRET 108 #endif 109 #ifdef OFILL 110 | OFILL 111 #endif 112 #ifdef OFDEL 113 | OFDEL 114 #endif 115 #ifdef NLDLY 116 | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY 117 #endif 118 ); 119 120 mode.c_oflag |= (OPOST 121 #ifdef ONLCR 122 | ONLCR 123 #endif 124 ); 125 126 mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD); 127 mode.c_cflag |= (CS8 | CREAD); 128 mode.c_lflag &= ~(ECHONL | NOFLSH | TOSTOP 129 #ifdef ECHOPTR 130 | ECHOPRT 131 #endif 132 #ifdef XCASE 133 | XCASE 134 #endif 135 ); 136 137 mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK 138 #ifdef ECHOCTL 139 | ECHOCTL 140 #endif 141 #ifdef ECHOKE 142 | ECHOKE 143 #endif 144 ); 145 146 tcsetattr(STDERR_FILENO, TCSADRAIN, &mode); 147 } 148 149 /* 150 * Determine the erase, interrupt, and kill characters from the termcap 151 * entry and command line and update their values in 'mode'. 152 */ 153 void 154 set_control_chars() 155 { 156 char *bp, *p, bs_char, buf[1024]; 157 158 bp = buf; 159 p = tgetstr("kb", &bp); 160 if (p == NULL || p[1] != '\0') 161 p = tgetstr("bc", &bp); 162 if (p != NULL && p[1] == '\0') 163 bs_char = p[0]; 164 else if (tgetflag("bs")) 165 bs_char = CTRL('h'); 166 else 167 bs_char = 0; 168 169 if (erasechar == 0 && !tgetflag("os") && mode.c_cc[VERASE] != CERASE) { 170 if (tgetflag("bs") || bs_char != 0) 171 erasechar = -1; 172 } 173 if (erasechar < 0) 174 erasechar = (bs_char != 0) ? bs_char : CTRL('h'); 175 176 if (mode.c_cc[VERASE] == 0 || erasechar != 0) 177 mode.c_cc[VERASE] = erasechar ? erasechar : CERASE; 178 179 if (mode.c_cc[VINTR] == 0 || intrchar != 0) 180 mode.c_cc[VINTR] = intrchar ? intrchar : CINTR; 181 182 if (mode.c_cc[VKILL] == 0 || killchar != 0) 183 mode.c_cc[VKILL] = killchar ? killchar : CKILL; 184 } 185 186 /* 187 * Set up various conversions in 'mode', including parity, tabs, returns, 188 * echo, and case, according to the termcap entry. If the program we're 189 * running was named with a leading upper-case character, map external 190 * uppercase to internal lowercase. 191 */ 192 void 193 set_conversions(usingupper) 194 int usingupper; 195 { 196 if (tgetflag("UC") || usingupper) { 197 #ifdef IUCLC 198 mode.c_iflag |= IUCLC; 199 mode.c_oflag |= OLCUC; 200 #endif 201 } else if (tgetflag("LC")) { 202 #ifdef IUCLC 203 mode.c_iflag &= ~IUCLC; 204 mode.c_oflag &= ~OLCUC; 205 #endif 206 } 207 mode.c_iflag &= ~(PARMRK | INPCK); 208 mode.c_lflag |= ICANON; 209 if (tgetflag("EP")) { 210 mode.c_cflag |= PARENB; 211 mode.c_cflag &= ~PARODD; 212 } 213 if (tgetflag("OP")) { 214 mode.c_cflag |= PARENB; 215 mode.c_cflag |= PARODD; 216 } 217 218 #ifdef ONLCR 219 mode.c_oflag |= ONLCR; 220 #endif 221 mode.c_iflag |= ICRNL; 222 mode.c_lflag |= ECHO; 223 mode.c_oflag |= OXTABS; 224 if (tgetflag("NL")) { /* Newline, not linefeed. */ 225 #ifdef ONLCR 226 mode.c_oflag &= ~ONLCR; 227 #endif 228 mode.c_iflag &= ~ICRNL; 229 } 230 if (tgetflag("HD")) /* Half duplex. */ 231 mode.c_lflag &= ~ECHO; 232 if (tgetflag("pt")) /* Print tabs. */ 233 mode.c_oflag &= ~OXTABS; 234 mode.c_lflag |= (ECHOE | ECHOK); 235 } 236 237 /* Output startup string. */ 238 void 239 set_init() 240 { 241 char *bp, buf[1024]; 242 int settle; 243 244 bp = buf; 245 if (tgetstr("pc", &bp) != 0) /* Get/set pad character. */ 246 PC = buf[0]; 247 248 #ifdef TAB3 249 if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) { 250 oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET); 251 tcsetattr(STDERR_FILENO, TCSADRAIN, &oldmode); 252 } 253 #endif 254 settle = set_tabs(); 255 256 if (isreset) { 257 bp = buf; 258 if (tgetstr("rs", &bp) != 0 || tgetstr("is", &bp) != 0) { 259 tputs(buf, 0, outc); 260 settle = 1; 261 } 262 bp = buf; 263 if (tgetstr("rf", &bp) != 0 || tgetstr("if", &bp) != 0) { 264 cat(buf); 265 settle = 1; 266 } 267 } 268 269 if (settle) { 270 (void)putc('\r', stderr); 271 (void)fflush(stderr); 272 (void)sleep(1); /* Settle the terminal. */ 273 } 274 } 275 276 /* 277 * Set the hardware tabs on the terminal, using the ct (clear all tabs), 278 * st (set one tab) and ch (horizontal cursor addressing) capabilities. 279 * This is done before if and is, so they can patch in case we blow this. 280 * Return nonzero if we set any tab stops, zero if not. 281 */ 282 int 283 set_tabs() 284 { 285 int c; 286 char *capsp, *clear_tabs; 287 char *set_column, *set_pos, *set_tab, *tg_out; 288 char caps[1024]; 289 290 capsp = caps; 291 set_tab = tgetstr("st", &capsp); 292 293 if (set_tab && (clear_tabs = tgetstr("ct", &capsp))) { 294 (void)putc('\r', stderr); /* Force to left margin. */ 295 tputs(clear_tabs, 0, outc); 296 } 297 298 set_column = tgetstr("ch", &capsp); 299 set_pos = set_column ? NULL : tgetstr("cm", &capsp); 300 301 if (set_tab) { 302 for (c = 8; c < columns; c += 8) { 303 /* 304 * Get to the right column. "OOPS" is returned by 305 * tgoto() if it can't do the job. (*snarl*) 306 */ 307 tg_out = "OOPS"; 308 if (set_column) 309 tg_out = tgoto(set_column, 0, c); 310 if (*tg_out == 'O' && set_pos) 311 tg_out = tgoto(set_pos, c, lines - 1); 312 if (*tg_out != 'O') 313 tputs(tg_out, 1, outc); 314 else 315 (void)fprintf(stderr, "%s", " "); 316 /* Set the tab. */ 317 tputs(set_tab, 0, outc); 318 } 319 putc('\r', stderr); 320 return (1); 321 } 322 return (0); 323 } 324