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