1 /* $NetBSD: set.c,v 1.10 2004/09/01 01:46:28 chs 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 #ifndef lint 34 #if 0 35 static char sccsid[] = "@(#)set.c 8.2 (Berkeley) 2/28/94"; 36 #endif 37 __RCSID("$NetBSD: set.c,v 1.10 2004/09/01 01:46:28 chs Exp $"); 38 #endif /* not lint */ 39 40 #include <stdio.h> 41 #include <termcap.h> 42 #include <termios.h> 43 #include <unistd.h> 44 #include "extern.h" 45 46 #define CHK(val, dft) (val <= 0 ? dft : val) 47 48 int set_tabs __P((void)); 49 50 /* 51 * Reset the terminal mode bits to a sensible state. Very useful after 52 * a child program dies in raw mode. 53 */ 54 void 55 reset_mode() 56 { 57 tcgetattr(STDERR_FILENO, &mode); 58 59 #if defined(VDISCARD) && defined(CDISCARD) 60 mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD); 61 #endif 62 mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF); 63 mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE); 64 #if defined(VFLUSH) && defined(CFLUSH) 65 mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH); 66 #endif 67 mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR); 68 mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL); 69 #if defined(VLNEXT) && defined(CLNEXT) 70 mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT); 71 #endif 72 mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT); 73 #if defined(VREPRINT) && defined(CRPRNT) 74 mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT); 75 #endif 76 mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART); 77 mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP); 78 mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP); 79 #if defined(VWERASE) && defined(CWERASE) 80 mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE); 81 #endif 82 83 mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR 84 #ifdef IUCLC 85 | IUCLC 86 #endif 87 #ifdef IXANY 88 | IXANY 89 #endif 90 | IXOFF); 91 92 mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON 93 #ifdef IMAXBEL 94 | IMAXBEL 95 #endif 96 ); 97 98 mode.c_oflag &= ~(0 99 #ifdef OLCUC 100 | OLCUC 101 #endif 102 #ifdef OCRNL 103 | OCRNL 104 #endif 105 #ifdef ONOCR 106 | ONOCR 107 #endif 108 #ifdef ONLRET 109 | ONLRET 110 #endif 111 #ifdef OFILL 112 | OFILL 113 #endif 114 #ifdef OFDEL 115 | OFDEL 116 #endif 117 #ifdef NLDLY 118 | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY 119 #endif 120 ); 121 122 mode.c_oflag |= (OPOST 123 #ifdef ONLCR 124 | ONLCR 125 #endif 126 ); 127 128 mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD); 129 mode.c_cflag |= (CS8 | CREAD); 130 mode.c_lflag &= ~(ECHONL | NOFLSH | TOSTOP 131 #ifdef ECHOPTR 132 | ECHOPRT 133 #endif 134 #ifdef XCASE 135 | XCASE 136 #endif 137 ); 138 139 mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK 140 #ifdef ECHOCTL 141 | ECHOCTL 142 #endif 143 #ifdef ECHOKE 144 | ECHOKE 145 #endif 146 ); 147 148 tcsetattr(STDERR_FILENO, TCSADRAIN, &mode); 149 } 150 151 /* 152 * Determine the erase, interrupt, and kill characters from the termcap 153 * entry and command line and update their values in 'mode'. 154 */ 155 void 156 set_control_chars(int erasechar, int intrchar, int killchar) 157 { 158 char *bp, *p, bs_char, buf[1024]; 159 160 bp = buf; 161 p = tgetstr("kb", &bp); 162 if (p == NULL || p[1] != '\0') 163 p = tgetstr("bc", &bp); 164 if (p != NULL && p[1] == '\0') 165 bs_char = p[0]; 166 else if (tgetflag("bs")) 167 bs_char = CTRL('h'); 168 else 169 bs_char = 0; 170 171 if (erasechar == 0 && !tgetflag("os") && mode.c_cc[VERASE] != CERASE) { 172 if (tgetflag("bs") || bs_char != 0) 173 erasechar = -1; 174 } 175 if (erasechar < 0) 176 erasechar = (bs_char != 0) ? bs_char : CTRL('h'); 177 178 if (mode.c_cc[VERASE] == 0 || erasechar != 0) 179 mode.c_cc[VERASE] = erasechar ? erasechar : CERASE; 180 181 if (mode.c_cc[VINTR] == 0 || intrchar != 0) 182 mode.c_cc[VINTR] = intrchar ? intrchar : CINTR; 183 184 if (mode.c_cc[VKILL] == 0 || killchar != 0) 185 mode.c_cc[VKILL] = killchar ? killchar : CKILL; 186 } 187 188 /* 189 * Set up various conversions in 'mode', including parity, tabs, returns, 190 * echo, and case, according to the termcap entry. If the program we're 191 * running was named with a leading upper-case character, map external 192 * uppercase to internal lowercase. 193 */ 194 void 195 set_conversions(int usingupper) 196 { 197 if (tgetflag("UC") || usingupper) { 198 #ifdef IUCLC 199 mode.c_iflag |= IUCLC; 200 mode.c_oflag |= OLCUC; 201 #endif 202 } else if (tgetflag("LC")) { 203 #ifdef IUCLC 204 mode.c_iflag &= ~IUCLC; 205 mode.c_oflag &= ~OLCUC; 206 #endif 207 } 208 mode.c_iflag &= ~(PARMRK | INPCK); 209 mode.c_lflag |= ICANON; 210 if (tgetflag("EP")) { 211 mode.c_cflag |= PARENB; 212 mode.c_cflag &= ~PARODD; 213 } 214 if (tgetflag("OP")) { 215 mode.c_cflag |= PARENB; 216 mode.c_cflag |= PARODD; 217 } 218 219 #ifdef ONLCR 220 mode.c_oflag |= ONLCR; 221 #endif 222 mode.c_iflag |= ICRNL; 223 mode.c_lflag |= ECHO; 224 mode.c_oflag |= OXTABS; 225 if (tgetflag("NL")) { /* Newline, not linefeed. */ 226 #ifdef ONLCR 227 mode.c_oflag &= ~ONLCR; 228 #endif 229 mode.c_iflag &= ~ICRNL; 230 } 231 if (tgetflag("HD")) /* Half duplex. */ 232 mode.c_lflag &= ~ECHO; 233 if (tgetflag("pt")) /* Print tabs. */ 234 mode.c_oflag &= ~OXTABS; 235 mode.c_lflag |= (ECHOE | ECHOK); 236 } 237 238 /* Output startup string. */ 239 void 240 set_init() 241 { 242 char *bp, buf[1024]; 243 int settle; 244 245 bp = buf; 246 if (tgetstr("pc", &bp) != 0) /* Get/set pad character. */ 247 PC = buf[0]; 248 249 #ifdef TAB3 250 if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) { 251 oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET); 252 tcsetattr(STDERR_FILENO, TCSADRAIN, &oldmode); 253 } 254 #endif 255 settle = set_tabs(); 256 257 if (isreset) { 258 bp = buf; 259 if (tgetstr("rs", &bp) != 0 || tgetstr("is", &bp) != 0) { 260 tputs(buf, 0, outc); 261 settle = 1; 262 } 263 bp = buf; 264 if (tgetstr("rf", &bp) != 0 || tgetstr("if", &bp) != 0) { 265 cat(buf); 266 settle = 1; 267 } 268 } 269 270 if (settle) { 271 (void)putc('\r', stderr); 272 (void)fflush(stderr); 273 (void)sleep(1); /* Settle the terminal. */ 274 } 275 } 276 277 /* 278 * Set the hardware tabs on the terminal, using the ct (clear all tabs), 279 * st (set one tab) and ch (horizontal cursor addressing) capabilities. 280 * This is done before if and is, so they can patch in case we blow this. 281 * Return nonzero if we set any tab stops, zero if not. 282 */ 283 int 284 set_tabs() 285 { 286 int c; 287 char *capsp, *clear_tabs; 288 char *set_column, *set_tab, *tg_out; 289 char caps[1024]; 290 291 capsp = caps; 292 set_tab = tgetstr("st", &capsp); 293 294 if (set_tab && (clear_tabs = tgetstr("ct", &capsp))) { 295 (void)putc('\r', stderr); /* Force to left margin. */ 296 tputs(clear_tabs, 0, outc); 297 } 298 299 set_column = tgetstr("ch", &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') 311 tputs(tg_out, 1, outc); 312 else 313 (void)fprintf(stderr, "%s", " "); 314 /* Set the tab. */ 315 tputs(set_tab, 0, outc); 316 } 317 putc('\r', stderr); 318 return (1); 319 } 320 return (0); 321 } 322