set.c revision 68617
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#ifndef lint 35#if 0 36static char sccsid[] = "@(#)set.c 8.2 (Berkeley) 2/28/94"; 37#endif 38static const char rcsid[] = 39 "$FreeBSD: head/usr.bin/tset/set.c 68617 2000-11-11 23:03:38Z dg $"; 40#endif /* not lint */ 41 42#include <termios.h> 43#include <unistd.h> 44#include <stdio.h> 45#include "extern.h" 46 47#define CHK(val, dft) (val <= 0 ? dft : val) 48 49int set_tabs __P((void)); 50 51/* 52 * Reset the terminal mode bits to a sensible state. Very useful after 53 * a child program dies in raw mode. 54 */ 55void 56reset_mode() 57{ 58 tcgetattr(STDERR_FILENO, &mode); 59 60#if defined(VDISCARD) && defined(CDISCARD) 61 mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD); 62#endif 63 mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF); 64 mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE); 65#if defined(VFLUSH) && defined(CFLUSH) 66 mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH); 67#endif 68 mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR); 69 mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL); 70#if defined(VLNEXT) && defined(CLNEXT) 71 mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT); 72#endif 73 mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT); 74#if defined(VREPRINT) && defined(CRPRNT) 75 mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT); 76#endif 77 mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART); 78 mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP); 79 mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP); 80#if defined(VWERASE) && defined(CWERASE) 81 mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE); 82#endif 83 84 mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR 85#ifdef IUCLC 86 | IUCLC 87#endif 88#ifdef IXANY 89 | IXANY 90#endif 91 | IXOFF); 92 93 mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON 94#ifdef IMAXBEL 95 | IMAXBEL 96#endif 97 ); 98 99 mode.c_oflag &= ~(0 100#ifdef OLCUC 101 | OLCUC 102#endif 103#ifdef OCRNL 104 | OCRNL 105#endif 106#ifdef ONOCR 107 | ONOCR 108#endif 109#ifdef ONLRET 110 | ONLRET 111#endif 112#ifdef OFILL 113 | OFILL 114#endif 115#ifdef OFDEL 116 | OFDEL 117#endif 118#ifdef NLDLY 119 | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY 120#endif 121 ); 122 123 mode.c_oflag |= (OPOST 124#ifdef ONLCR 125 | ONLCR 126#endif 127 ); 128 129 mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | CLOCAL); 130 mode.c_cflag |= (CS8 | CREAD); 131 mode.c_lflag &= ~(ECHONL | NOFLSH | TOSTOP 132#ifdef ECHOPTR 133 | ECHOPRT 134#endif 135#ifdef XCASE 136 | XCASE 137#endif 138 ); 139 140 mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK 141#ifdef ECHOCTL 142 | ECHOCTL 143#endif 144#ifdef ECHOKE 145 | ECHOKE 146#endif 147 ); 148 149 tcsetattr(STDERR_FILENO, TCSADRAIN, &mode); 150} 151 152/* 153 * Determine the erase, interrupt, and kill characters from the termcap 154 * entry and command line and update their values in 'mode'. 155 */ 156void 157set_control_chars() 158{ 159 char *bp, *p, bs_char, buf[1024]; 160 161 bp = buf; 162 p = tgetstr("kb", &bp); 163 if (p == NULL || p[1] != '\0') 164 p = tgetstr("bc", &bp); 165 if (p != NULL && p[1] == '\0') 166 bs_char = p[0]; 167 else if (tgetflag("bs")) 168 bs_char = CTRL('h'); 169 else 170 bs_char = 0; 171 172 if (erasech == 0 && bs_char != 0 && !tgetflag("os")) 173 erasech = -1; 174 if (erasech < 0) 175 erasech = (bs_char != 0) ? bs_char : CTRL('h'); 176 177 if (mode.c_cc[VERASE] == 0 || erasech != 0) 178 mode.c_cc[VERASE] = erasech ? erasech : CERASE; 179 180 if (mode.c_cc[VINTR] == 0 || intrchar != 0) 181 mode.c_cc[VINTR] = intrchar ? intrchar : CINTR; 182 183 if (mode.c_cc[VKILL] == 0 || killch != 0) 184 mode.c_cc[VKILL] = killch ? killch : CKILL; 185} 186 187/* 188 * Set up various conversions in 'mode', including parity, tabs, returns, 189 * echo, and case, according to the termcap entry. If the program we're 190 * running was named with a leading upper-case character, map external 191 * uppercase to internal lowercase. 192 */ 193void 194set_conversions(usingupper) 195 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. */ 239void 240set_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 */ 283int 284set_tabs() 285{ 286 int c; 287 char *capsp, *clear_tabs; 288 char *set_column, *set_pos, *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 set_pos = set_column ? NULL : tgetstr("cm", &capsp); 301 302 if (Set_tab) { 303 for (c = 8; c < Columns; c += 8) { 304 /* 305 * Get to the right column. "OOPS" is returned by 306 * tgoto() if it can't do the job. (*snarl*) 307 */ 308 tg_out = "OOPS"; 309 if (set_column) 310 tg_out = tgoto(set_column, 0, c); 311 if (*tg_out == 'O' && set_pos) 312 tg_out = tgoto(set_pos, c, Lines - 1); 313 if (*tg_out != 'O') 314 tputs(tg_out, 1, outc); 315 else 316 (void)fprintf(stderr, "%s", " "); 317 /* Set the tab. */ 318 tputs(Set_tab, 0, outc); 319 } 320 putc('\r', stderr); 321 return (1); 322 } 323 return (0); 324} 325