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