11590Srgrimes/*- 21590Srgrimes * Copyright (c) 1991, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 4. Neither the name of the University nor the names of its contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 291590Srgrimes 3087701Smarkm#include <sys/cdefs.h> 3187701Smarkm 3287701Smarkm__FBSDID("$FreeBSD$"); 3387701Smarkm 341590Srgrimes#ifndef lint 3587701Smarkmstatic const char sccsid[] = "@(#)set.c 8.2 (Berkeley) 2/28/94"; 3628370Scharnier#endif 371590Srgrimes 3887701Smarkm#include <stdio.h> 39200419Sdelphij#include <termcap.h> 401590Srgrimes#include <termios.h> 411590Srgrimes#include <unistd.h> 4287701Smarkm 431590Srgrimes#include "extern.h" 441590Srgrimes 451590Srgrimes#define CHK(val, dft) (val <= 0 ? dft : val) 461590Srgrimes 4792922Simpint set_tabs(void); 481590Srgrimes 491590Srgrimes/* 501590Srgrimes * Reset the terminal mode bits to a sensible state. Very useful after 511590Srgrimes * a child program dies in raw mode. 521590Srgrimes */ 531590Srgrimesvoid 54200419Sdelphijreset_mode(void) 551590Srgrimes{ 561590Srgrimes tcgetattr(STDERR_FILENO, &mode); 571590Srgrimes 581590Srgrimes#if defined(VDISCARD) && defined(CDISCARD) 591590Srgrimes mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD); 601590Srgrimes#endif 611590Srgrimes mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF); 621590Srgrimes mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE); 631590Srgrimes#if defined(VFLUSH) && defined(CFLUSH) 641590Srgrimes mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH); 651590Srgrimes#endif 661590Srgrimes mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR); 671590Srgrimes mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL); 681590Srgrimes#if defined(VLNEXT) && defined(CLNEXT) 691590Srgrimes mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT); 701590Srgrimes#endif 711590Srgrimes mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT); 721590Srgrimes#if defined(VREPRINT) && defined(CRPRNT) 731590Srgrimes mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT); 741590Srgrimes#endif 751590Srgrimes mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART); 761590Srgrimes mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP); 771590Srgrimes mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP); 781590Srgrimes#if defined(VWERASE) && defined(CWERASE) 791590Srgrimes mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE); 801590Srgrimes#endif 811590Srgrimes 821590Srgrimes mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR 831590Srgrimes#ifdef IUCLC 841590Srgrimes | IUCLC 851590Srgrimes#endif 861590Srgrimes#ifdef IXANY 871590Srgrimes | IXANY 881590Srgrimes#endif 891590Srgrimes | IXOFF); 901590Srgrimes 911590Srgrimes mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON 921590Srgrimes#ifdef IMAXBEL 931590Srgrimes | IMAXBEL 941590Srgrimes#endif 951590Srgrimes ); 961590Srgrimes 971590Srgrimes mode.c_oflag &= ~(0 981590Srgrimes#ifdef OLCUC 991590Srgrimes | OLCUC 1001590Srgrimes#endif 1011590Srgrimes#ifdef OCRNL 1021590Srgrimes | OCRNL 1031590Srgrimes#endif 1041590Srgrimes#ifdef ONOCR 1051590Srgrimes | ONOCR 1061590Srgrimes#endif 1071590Srgrimes#ifdef ONLRET 1081590Srgrimes | ONLRET 1091590Srgrimes#endif 1101590Srgrimes#ifdef OFILL 1111590Srgrimes | OFILL 1121590Srgrimes#endif 1131590Srgrimes#ifdef OFDEL 1141590Srgrimes | OFDEL 1151590Srgrimes#endif 1161590Srgrimes#ifdef NLDLY 1171590Srgrimes | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY 1181590Srgrimes#endif 1191590Srgrimes ); 1201590Srgrimes 1211590Srgrimes mode.c_oflag |= (OPOST 1221590Srgrimes#ifdef ONLCR 1231590Srgrimes | ONLCR 1241590Srgrimes#endif 1251590Srgrimes ); 1261590Srgrimes 1271590Srgrimes mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | CLOCAL); 1281590Srgrimes mode.c_cflag |= (CS8 | CREAD); 1291590Srgrimes mode.c_lflag &= ~(ECHONL | NOFLSH | TOSTOP 1301590Srgrimes#ifdef ECHOPTR 1311590Srgrimes | ECHOPRT 1321590Srgrimes#endif 1331590Srgrimes#ifdef XCASE 1341590Srgrimes | XCASE 1351590Srgrimes#endif 1361590Srgrimes ); 1371590Srgrimes 1381590Srgrimes mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK 1391590Srgrimes#ifdef ECHOCTL 1401590Srgrimes | ECHOCTL 1411590Srgrimes#endif 1421590Srgrimes#ifdef ECHOKE 1431590Srgrimes | ECHOKE 1441590Srgrimes#endif 1451590Srgrimes ); 1461590Srgrimes 1471590Srgrimes tcsetattr(STDERR_FILENO, TCSADRAIN, &mode); 1481590Srgrimes} 1491590Srgrimes 1501590Srgrimes/* 1511590Srgrimes * Determine the erase, interrupt, and kill characters from the termcap 1521590Srgrimes * entry and command line and update their values in 'mode'. 1531590Srgrimes */ 1541590Srgrimesvoid 155200419Sdelphijset_control_chars(void) 1561590Srgrimes{ 1571590Srgrimes char *bp, *p, bs_char, buf[1024]; 1581590Srgrimes 1591590Srgrimes bp = buf; 1601590Srgrimes p = tgetstr("kb", &bp); 1611590Srgrimes if (p == NULL || p[1] != '\0') 1621590Srgrimes p = tgetstr("bc", &bp); 1631590Srgrimes if (p != NULL && p[1] == '\0') 1641590Srgrimes bs_char = p[0]; 1651590Srgrimes else if (tgetflag("bs")) 1661590Srgrimes bs_char = CTRL('h'); 1671590Srgrimes else 1681590Srgrimes bs_char = 0; 1691590Srgrimes 17068617Sdg if (erasech == 0 && bs_char != 0 && !tgetflag("os")) 17168617Sdg erasech = -1; 17268617Sdg if (erasech < 0) 17368617Sdg erasech = (bs_char != 0) ? bs_char : CTRL('h'); 1741590Srgrimes 17568617Sdg if (mode.c_cc[VERASE] == 0 || erasech != 0) 17668617Sdg mode.c_cc[VERASE] = erasech ? erasech : CERASE; 1771590Srgrimes 1781590Srgrimes if (mode.c_cc[VINTR] == 0 || intrchar != 0) 1791590Srgrimes mode.c_cc[VINTR] = intrchar ? intrchar : CINTR; 1801590Srgrimes 18168617Sdg if (mode.c_cc[VKILL] == 0 || killch != 0) 18268617Sdg mode.c_cc[VKILL] = killch ? killch : CKILL; 1831590Srgrimes} 1841590Srgrimes 1851590Srgrimes/* 1861590Srgrimes * Set up various conversions in 'mode', including parity, tabs, returns, 1871590Srgrimes * echo, and case, according to the termcap entry. If the program we're 1881590Srgrimes * running was named with a leading upper-case character, map external 1891590Srgrimes * uppercase to internal lowercase. 1901590Srgrimes */ 1911590Srgrimesvoid 192200419Sdelphijset_conversions(int usingupper) 1931590Srgrimes{ 1941590Srgrimes if (tgetflag("UC") || usingupper) { 1951590Srgrimes#ifdef IUCLC 1961590Srgrimes mode.c_iflag |= IUCLC; 1971590Srgrimes mode.c_oflag |= OLCUC; 1981590Srgrimes#endif 1991590Srgrimes } else if (tgetflag("LC")) { 2001590Srgrimes#ifdef IUCLC 2011590Srgrimes mode.c_iflag &= ~IUCLC; 2021590Srgrimes mode.c_oflag &= ~OLCUC; 2031590Srgrimes#endif 2041590Srgrimes } 2051590Srgrimes mode.c_iflag &= ~(PARMRK | INPCK); 2061590Srgrimes mode.c_lflag |= ICANON; 2071590Srgrimes if (tgetflag("EP")) { 2081590Srgrimes mode.c_cflag |= PARENB; 2091590Srgrimes mode.c_cflag &= ~PARODD; 2101590Srgrimes } 2111590Srgrimes if (tgetflag("OP")) { 2121590Srgrimes mode.c_cflag |= PARENB; 2131590Srgrimes mode.c_cflag |= PARODD; 2141590Srgrimes } 2151590Srgrimes 2161590Srgrimes#ifdef ONLCR 2171590Srgrimes mode.c_oflag |= ONLCR; 2181590Srgrimes#endif 2191590Srgrimes mode.c_iflag |= ICRNL; 2201590Srgrimes mode.c_lflag |= ECHO; 2211590Srgrimes mode.c_oflag |= OXTABS; 2221590Srgrimes if (tgetflag("NL")) { /* Newline, not linefeed. */ 2231590Srgrimes#ifdef ONLCR 2241590Srgrimes mode.c_oflag &= ~ONLCR; 2251590Srgrimes#endif 2261590Srgrimes mode.c_iflag &= ~ICRNL; 2271590Srgrimes } 2281590Srgrimes if (tgetflag("HD")) /* Half duplex. */ 2291590Srgrimes mode.c_lflag &= ~ECHO; 2301590Srgrimes if (tgetflag("pt")) /* Print tabs. */ 2311590Srgrimes mode.c_oflag &= ~OXTABS; 2321590Srgrimes mode.c_lflag |= (ECHOE | ECHOK); 2331590Srgrimes} 2341590Srgrimes 2351590Srgrimes/* Output startup string. */ 2361590Srgrimesvoid 237200419Sdelphijset_init(void) 2381590Srgrimes{ 2391590Srgrimes char *bp, buf[1024]; 2401590Srgrimes int settle; 2411590Srgrimes 2421590Srgrimes bp = buf; 2431590Srgrimes if (tgetstr("pc", &bp) != 0) /* Get/set pad character. */ 2441590Srgrimes PC = buf[0]; 2453397Sache 2461590Srgrimes#ifdef TAB3 2471590Srgrimes if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) { 2481590Srgrimes oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET); 2491590Srgrimes tcsetattr(STDERR_FILENO, TCSADRAIN, &oldmode); 2501590Srgrimes } 2511590Srgrimes#endif 2521590Srgrimes settle = set_tabs(); 2531590Srgrimes 2541590Srgrimes if (isreset) { 2551590Srgrimes bp = buf; 2561590Srgrimes if (tgetstr("rs", &bp) != 0 || tgetstr("is", &bp) != 0) { 2571590Srgrimes tputs(buf, 0, outc); 2581590Srgrimes settle = 1; 2591590Srgrimes } 2601590Srgrimes bp = buf; 2611590Srgrimes if (tgetstr("rf", &bp) != 0 || tgetstr("if", &bp) != 0) { 2621590Srgrimes cat(buf); 2631590Srgrimes settle = 1; 2641590Srgrimes } 2651590Srgrimes } 2661590Srgrimes 2671590Srgrimes if (settle) { 2681590Srgrimes (void)putc('\r', stderr); 2691590Srgrimes (void)fflush(stderr); 2701590Srgrimes (void)sleep(1); /* Settle the terminal. */ 2711590Srgrimes } 2721590Srgrimes} 2731590Srgrimes 2741590Srgrimes/* 2751590Srgrimes * Set the hardware tabs on the terminal, using the ct (clear all tabs), 2761590Srgrimes * st (set one tab) and ch (horizontal cursor addressing) capabilities. 2771590Srgrimes * This is done before if and is, so they can patch in case we blow this. 2781590Srgrimes * Return nonzero if we set any tab stops, zero if not. 2791590Srgrimes */ 2801590Srgrimesint 281200419Sdelphijset_tabs(void) 2821590Srgrimes{ 2831590Srgrimes int c; 2841590Srgrimes char *capsp, *clear_tabs; 28587701Smarkm char *set_column, *set_pos, *Set_tab; 2861590Srgrimes char caps[1024]; 28787701Smarkm const char *tg_out; 2881590Srgrimes 2891590Srgrimes capsp = caps; 29050638Speter Set_tab = tgetstr("st", &capsp); 2911590Srgrimes 29250638Speter if (Set_tab && (clear_tabs = tgetstr("ct", &capsp))) { 2931590Srgrimes (void)putc('\r', stderr); /* Force to left margin. */ 2941590Srgrimes tputs(clear_tabs, 0, outc); 2951590Srgrimes } 2961590Srgrimes 2971590Srgrimes set_column = tgetstr("ch", &capsp); 2981590Srgrimes set_pos = set_column ? NULL : tgetstr("cm", &capsp); 2991590Srgrimes 30050638Speter if (Set_tab) { 30150638Speter for (c = 8; c < Columns; c += 8) { 3021590Srgrimes /* 3031590Srgrimes * Get to the right column. "OOPS" is returned by 3041590Srgrimes * tgoto() if it can't do the job. (*snarl*) 3051590Srgrimes */ 3061590Srgrimes tg_out = "OOPS"; 3071590Srgrimes if (set_column) 3081590Srgrimes tg_out = tgoto(set_column, 0, c); 3091590Srgrimes if (*tg_out == 'O' && set_pos) 31050638Speter tg_out = tgoto(set_pos, c, Lines - 1); 3111590Srgrimes if (*tg_out != 'O') 3121590Srgrimes tputs(tg_out, 1, outc); 3131590Srgrimes else 3141590Srgrimes (void)fprintf(stderr, "%s", " "); 3151590Srgrimes /* Set the tab. */ 31650638Speter tputs(Set_tab, 0, outc); 3171590Srgrimes } 3181590Srgrimes putc('\r', stderr); 3191590Srgrimes return (1); 3201590Srgrimes } 3211590Srgrimes return (0); 3221590Srgrimes} 323