1 /* $NetBSD: set.c,v 1.18 2015/06/21 08:23:22 mlelstv Exp $ */ 2 3 /*- 4 * Copyright (c) 1991, 1993 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. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __RCSID("$NetBSD: set.c,v 1.18 2015/06/21 08:23:22 mlelstv Exp $"); 34 35 #include <err.h> 36 #include <stdio.h> 37 #include <term.h> 38 #include <termios.h> 39 #include <unistd.h> 40 #include "extern.h" 41 42 #define CHK(val, dft) (val <= 0 ? dft : val) 43 44 static int set_tabs(void); 45 46 /* 47 * Reset the terminal mode bits to a sensible state. Very useful after 48 * a child program dies in raw mode. 49 */ 50 void 51 reset_mode(void) 52 { 53 tcgetattr(STDERR_FILENO, &mode); 54 55 #if defined(VDISCARD) && defined(CDISCARD) 56 mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD); 57 #endif 58 mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF); 59 mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE); 60 #if defined(VFLUSH) && defined(CFLUSH) 61 mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH); 62 #endif 63 mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR); 64 mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL); 65 #if defined(VLNEXT) && defined(CLNEXT) 66 mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT); 67 #endif 68 mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT); 69 #if defined(VREPRINT) && defined(CRPRNT) 70 mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT); 71 #endif 72 mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART); 73 mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP); 74 mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP); 75 #if defined(VWERASE) && defined(CWERASE) 76 mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE); 77 #endif 78 79 mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR 80 #ifdef IUCLC 81 | IUCLC 82 #endif 83 #ifdef IXANY 84 | IXANY 85 #endif 86 | IXOFF); 87 88 mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON 89 #ifdef IMAXBEL 90 | IMAXBEL 91 #endif 92 ); 93 94 mode.c_oflag &= ~(0 95 #ifdef OLCUC 96 | OLCUC 97 #endif 98 #ifdef OCRNL 99 | OCRNL 100 #endif 101 #ifdef ONOCR 102 | ONOCR 103 #endif 104 #ifdef ONLRET 105 | ONLRET 106 #endif 107 #ifdef OFILL 108 | OFILL 109 #endif 110 #ifdef OFDEL 111 | OFDEL 112 #endif 113 #ifdef NLDLY 114 | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY 115 #endif 116 ); 117 118 mode.c_oflag |= (OPOST 119 #ifdef ONLCR 120 | ONLCR 121 #endif 122 ); 123 124 mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD); 125 mode.c_cflag |= (CS8 | CREAD); 126 mode.c_lflag &= ~(ECHONL | NOFLSH | TOSTOP 127 #ifdef ECHOPTR 128 | ECHOPRT 129 #endif 130 #ifdef XCASE 131 | XCASE 132 #endif 133 ); 134 135 mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK 136 #ifdef ECHOCTL 137 | ECHOCTL 138 #endif 139 #ifdef ECHOKE 140 | ECHOKE 141 #endif 142 ); 143 144 tcsetattr(STDERR_FILENO, TCSADRAIN, &mode); 145 } 146 147 /* 148 * Determine the erase, interrupt, and kill characters from the terminfo 149 * entry and command line and update their values in 'mode'. 150 */ 151 void 152 set_control_chars(int erasechar, int intrchar, int killchar) 153 { 154 int bs_char; 155 156 if (key_backspace != NULL && key_backspace[1] == '\0') 157 bs_char = key_backspace[0]; 158 else 159 bs_char = 0; 160 161 if (erasechar == 0 && bs_char != 0 && !over_strike) 162 erasechar = -1; 163 if (erasechar < 0) 164 erasechar = (bs_char != 0) ? bs_char : CTRL('h'); 165 166 if (mode.c_cc[VERASE] == 0 || erasechar != 0) 167 mode.c_cc[VERASE] = erasechar ? erasechar : CERASE; 168 169 if (mode.c_cc[VINTR] == 0 || intrchar != 0) 170 mode.c_cc[VINTR] = intrchar ? intrchar : CINTR; 171 172 if (mode.c_cc[VKILL] == 0 || killchar != 0) 173 mode.c_cc[VKILL] = killchar ? killchar : CKILL; 174 } 175 176 /* 177 * Set up various conversions in 'mode', including parity, tabs, returns, 178 * echo, and case, according to the terminfo entry. If the program we're 179 * running was named with a leading upper-case character, map external 180 * uppercase to internal lowercase. 181 */ 182 void 183 set_conversions(int usingupper) 184 { 185 186 #ifdef ONLCR 187 mode.c_oflag |= ONLCR; 188 #endif 189 mode.c_iflag |= ICRNL; 190 mode.c_lflag |= ECHO; 191 mode.c_oflag |= OXTABS; 192 if (newline != NULL && newline[0] == '\n' && !newline[1]) { /* Newline, not linefeed. */ 193 #ifdef ONLCR 194 mode.c_oflag &= ~ONLCR; 195 #endif 196 mode.c_iflag &= ~ICRNL; 197 } 198 if (tab) /* Print tabs. */ 199 mode.c_oflag &= ~OXTABS; 200 mode.c_lflag |= (ECHOE | ECHOK); 201 } 202 203 /* Output startup string. */ 204 void 205 set_init(void) 206 { 207 const char *bp; 208 int settle; 209 210 #ifdef TAB3 211 if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) { 212 oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET); 213 tcsetattr(STDERR_FILENO, TCSADRAIN, &oldmode); 214 } 215 #endif 216 settle = set_tabs(); 217 218 if (isreset) { 219 if (reset_1string) { 220 tputs(reset_1string, 0, outc); 221 settle = 1; 222 } 223 if (reset_2string) { 224 tputs(reset_2string, 0, outc); 225 settle = 1; 226 } 227 if ((bp = reset_file) || (bp = init_file)) { 228 tset_cat(bp); 229 settle = 1; 230 } 231 } 232 233 if (settle) { 234 (void)putc('\r', stderr); 235 (void)fflush(stderr); 236 (void)sleep(1); /* Settle the terminal. */ 237 } 238 } 239 240 /* 241 * Set the hardware tabs on the terminal, using the ct (clear all tabs), 242 * st (set one tab) and ch (horizontal cursor addressing) capabilities. 243 * This is done before if and is, so they can patch in case we blow this. 244 * Return nonzero if we set any tab stops, zero if not. 245 */ 246 static int 247 set_tabs(void) 248 { 249 int c; 250 char *out; 251 252 if (set_tab) { 253 if (clear_all_tabs) { 254 (void)putc('\r', stderr); /* Force to left margin. */ 255 tputs(clear_all_tabs, 0, outc); 256 } 257 258 for (c = 8; c < ncolumns; c += 8) { 259 if (column_address) 260 out = tiparm(column_address, c); 261 else 262 out = NULL; 263 if (out) 264 tputs(out, 1, outc); 265 else 266 (void)fprintf(stderr, "%s", " "); 267 /* Set the tab. */ 268 tputs(set_tab, 0, outc); 269 } 270 putc('\r', stderr); 271 return (1); 272 } 273 return (0); 274 } 275