set.c revision 200419
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 * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 3487701Smarkm#include <sys/cdefs.h> 3587701Smarkm 3687701Smarkm__FBSDID("$FreeBSD: head/usr.bin/tset/set.c 200419 2009-12-11 23:30:22Z delphij $"); 3787701Smarkm 381590Srgrimes#ifndef lint 3987701Smarkmstatic const char sccsid[] = "@(#)set.c 8.2 (Berkeley) 2/28/94"; 4028370Scharnier#endif 411590Srgrimes 4287701Smarkm#include <stdio.h> 43200419Sdelphij#include <termcap.h> 441590Srgrimes#include <termios.h> 451590Srgrimes#include <unistd.h> 4687701Smarkm 471590Srgrimes#include "extern.h" 481590Srgrimes 491590Srgrimes#define CHK(val, dft) (val <= 0 ? dft : val) 501590Srgrimes 5192922Simpint set_tabs(void); 521590Srgrimes 531590Srgrimes/* 541590Srgrimes * Reset the terminal mode bits to a sensible state. Very useful after 551590Srgrimes * a child program dies in raw mode. 561590Srgrimes */ 571590Srgrimesvoid 58200419Sdelphijreset_mode(void) 591590Srgrimes{ 601590Srgrimes tcgetattr(STDERR_FILENO, &mode); 611590Srgrimes 621590Srgrimes#if defined(VDISCARD) && defined(CDISCARD) 631590Srgrimes mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD); 641590Srgrimes#endif 651590Srgrimes mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF); 661590Srgrimes mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE); 671590Srgrimes#if defined(VFLUSH) && defined(CFLUSH) 681590Srgrimes mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH); 691590Srgrimes#endif 701590Srgrimes mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR); 711590Srgrimes mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL); 721590Srgrimes#if defined(VLNEXT) && defined(CLNEXT) 731590Srgrimes mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT); 741590Srgrimes#endif 751590Srgrimes mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT); 761590Srgrimes#if defined(VREPRINT) && defined(CRPRNT) 771590Srgrimes mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT); 781590Srgrimes#endif 791590Srgrimes mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART); 801590Srgrimes mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP); 811590Srgrimes mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP); 821590Srgrimes#if defined(VWERASE) && defined(CWERASE) 831590Srgrimes mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE); 841590Srgrimes#endif 851590Srgrimes 861590Srgrimes mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR 871590Srgrimes#ifdef IUCLC 881590Srgrimes | IUCLC 891590Srgrimes#endif 901590Srgrimes#ifdef IXANY 911590Srgrimes | IXANY 921590Srgrimes#endif 931590Srgrimes | IXOFF); 941590Srgrimes 951590Srgrimes mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON 961590Srgrimes#ifdef IMAXBEL 971590Srgrimes | IMAXBEL 981590Srgrimes#endif 991590Srgrimes ); 1001590Srgrimes 1011590Srgrimes mode.c_oflag &= ~(0 1021590Srgrimes#ifdef OLCUC 1031590Srgrimes | OLCUC 1041590Srgrimes#endif 1051590Srgrimes#ifdef OCRNL 1061590Srgrimes | OCRNL 1071590Srgrimes#endif 1081590Srgrimes#ifdef ONOCR 1091590Srgrimes | ONOCR 1101590Srgrimes#endif 1111590Srgrimes#ifdef ONLRET 1121590Srgrimes | ONLRET 1131590Srgrimes#endif 1141590Srgrimes#ifdef OFILL 1151590Srgrimes | OFILL 1161590Srgrimes#endif 1171590Srgrimes#ifdef OFDEL 1181590Srgrimes | OFDEL 1191590Srgrimes#endif 1201590Srgrimes#ifdef NLDLY 1211590Srgrimes | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY 1221590Srgrimes#endif 1231590Srgrimes ); 1241590Srgrimes 1251590Srgrimes mode.c_oflag |= (OPOST 1261590Srgrimes#ifdef ONLCR 1271590Srgrimes | ONLCR 1281590Srgrimes#endif 1291590Srgrimes ); 1301590Srgrimes 1311590Srgrimes mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | CLOCAL); 1321590Srgrimes mode.c_cflag |= (CS8 | CREAD); 1331590Srgrimes mode.c_lflag &= ~(ECHONL | NOFLSH | TOSTOP 1341590Srgrimes#ifdef ECHOPTR 1351590Srgrimes | ECHOPRT 1361590Srgrimes#endif 1371590Srgrimes#ifdef XCASE 1381590Srgrimes | XCASE 1391590Srgrimes#endif 1401590Srgrimes ); 1411590Srgrimes 1421590Srgrimes mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK 1431590Srgrimes#ifdef ECHOCTL 1441590Srgrimes | ECHOCTL 1451590Srgrimes#endif 1461590Srgrimes#ifdef ECHOKE 1471590Srgrimes | ECHOKE 1481590Srgrimes#endif 1491590Srgrimes ); 1501590Srgrimes 1511590Srgrimes tcsetattr(STDERR_FILENO, TCSADRAIN, &mode); 1521590Srgrimes} 1531590Srgrimes 1541590Srgrimes/* 1551590Srgrimes * Determine the erase, interrupt, and kill characters from the termcap 1561590Srgrimes * entry and command line and update their values in 'mode'. 1571590Srgrimes */ 1581590Srgrimesvoid 159200419Sdelphijset_control_chars(void) 1601590Srgrimes{ 1611590Srgrimes char *bp, *p, bs_char, buf[1024]; 1621590Srgrimes 1631590Srgrimes bp = buf; 1641590Srgrimes p = tgetstr("kb", &bp); 1651590Srgrimes if (p == NULL || p[1] != '\0') 1661590Srgrimes p = tgetstr("bc", &bp); 1671590Srgrimes if (p != NULL && p[1] == '\0') 1681590Srgrimes bs_char = p[0]; 1691590Srgrimes else if (tgetflag("bs")) 1701590Srgrimes bs_char = CTRL('h'); 1711590Srgrimes else 1721590Srgrimes bs_char = 0; 1731590Srgrimes 17468617Sdg if (erasech == 0 && bs_char != 0 && !tgetflag("os")) 17568617Sdg erasech = -1; 17668617Sdg if (erasech < 0) 17768617Sdg erasech = (bs_char != 0) ? bs_char : CTRL('h'); 1781590Srgrimes 17968617Sdg if (mode.c_cc[VERASE] == 0 || erasech != 0) 18068617Sdg mode.c_cc[VERASE] = erasech ? erasech : CERASE; 1811590Srgrimes 1821590Srgrimes if (mode.c_cc[VINTR] == 0 || intrchar != 0) 1831590Srgrimes mode.c_cc[VINTR] = intrchar ? intrchar : CINTR; 1841590Srgrimes 18568617Sdg if (mode.c_cc[VKILL] == 0 || killch != 0) 18668617Sdg mode.c_cc[VKILL] = killch ? killch : CKILL; 1871590Srgrimes} 1881590Srgrimes 1891590Srgrimes/* 1901590Srgrimes * Set up various conversions in 'mode', including parity, tabs, returns, 1911590Srgrimes * echo, and case, according to the termcap entry. If the program we're 1921590Srgrimes * running was named with a leading upper-case character, map external 1931590Srgrimes * uppercase to internal lowercase. 1941590Srgrimes */ 1951590Srgrimesvoid 196200419Sdelphijset_conversions(int usingupper) 1971590Srgrimes{ 1981590Srgrimes if (tgetflag("UC") || usingupper) { 1991590Srgrimes#ifdef IUCLC 2001590Srgrimes mode.c_iflag |= IUCLC; 2011590Srgrimes mode.c_oflag |= OLCUC; 2021590Srgrimes#endif 2031590Srgrimes } else if (tgetflag("LC")) { 2041590Srgrimes#ifdef IUCLC 2051590Srgrimes mode.c_iflag &= ~IUCLC; 2061590Srgrimes mode.c_oflag &= ~OLCUC; 2071590Srgrimes#endif 2081590Srgrimes } 2091590Srgrimes mode.c_iflag &= ~(PARMRK | INPCK); 2101590Srgrimes mode.c_lflag |= ICANON; 2111590Srgrimes if (tgetflag("EP")) { 2121590Srgrimes mode.c_cflag |= PARENB; 2131590Srgrimes mode.c_cflag &= ~PARODD; 2141590Srgrimes } 2151590Srgrimes if (tgetflag("OP")) { 2161590Srgrimes mode.c_cflag |= PARENB; 2171590Srgrimes mode.c_cflag |= PARODD; 2181590Srgrimes } 2191590Srgrimes 2201590Srgrimes#ifdef ONLCR 2211590Srgrimes mode.c_oflag |= ONLCR; 2221590Srgrimes#endif 2231590Srgrimes mode.c_iflag |= ICRNL; 2241590Srgrimes mode.c_lflag |= ECHO; 2251590Srgrimes mode.c_oflag |= OXTABS; 2261590Srgrimes if (tgetflag("NL")) { /* Newline, not linefeed. */ 2271590Srgrimes#ifdef ONLCR 2281590Srgrimes mode.c_oflag &= ~ONLCR; 2291590Srgrimes#endif 2301590Srgrimes mode.c_iflag &= ~ICRNL; 2311590Srgrimes } 2321590Srgrimes if (tgetflag("HD")) /* Half duplex. */ 2331590Srgrimes mode.c_lflag &= ~ECHO; 2341590Srgrimes if (tgetflag("pt")) /* Print tabs. */ 2351590Srgrimes mode.c_oflag &= ~OXTABS; 2361590Srgrimes mode.c_lflag |= (ECHOE | ECHOK); 2371590Srgrimes} 2381590Srgrimes 2391590Srgrimes/* Output startup string. */ 2401590Srgrimesvoid 241200419Sdelphijset_init(void) 2421590Srgrimes{ 2431590Srgrimes char *bp, buf[1024]; 2441590Srgrimes int settle; 2451590Srgrimes 2461590Srgrimes bp = buf; 2471590Srgrimes if (tgetstr("pc", &bp) != 0) /* Get/set pad character. */ 2481590Srgrimes PC = buf[0]; 2493397Sache 2501590Srgrimes#ifdef TAB3 2511590Srgrimes if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) { 2521590Srgrimes oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET); 2531590Srgrimes tcsetattr(STDERR_FILENO, TCSADRAIN, &oldmode); 2541590Srgrimes } 2551590Srgrimes#endif 2561590Srgrimes settle = set_tabs(); 2571590Srgrimes 2581590Srgrimes if (isreset) { 2591590Srgrimes bp = buf; 2601590Srgrimes if (tgetstr("rs", &bp) != 0 || tgetstr("is", &bp) != 0) { 2611590Srgrimes tputs(buf, 0, outc); 2621590Srgrimes settle = 1; 2631590Srgrimes } 2641590Srgrimes bp = buf; 2651590Srgrimes if (tgetstr("rf", &bp) != 0 || tgetstr("if", &bp) != 0) { 2661590Srgrimes cat(buf); 2671590Srgrimes settle = 1; 2681590Srgrimes } 2691590Srgrimes } 2701590Srgrimes 2711590Srgrimes if (settle) { 2721590Srgrimes (void)putc('\r', stderr); 2731590Srgrimes (void)fflush(stderr); 2741590Srgrimes (void)sleep(1); /* Settle the terminal. */ 2751590Srgrimes } 2761590Srgrimes} 2771590Srgrimes 2781590Srgrimes/* 2791590Srgrimes * Set the hardware tabs on the terminal, using the ct (clear all tabs), 2801590Srgrimes * st (set one tab) and ch (horizontal cursor addressing) capabilities. 2811590Srgrimes * This is done before if and is, so they can patch in case we blow this. 2821590Srgrimes * Return nonzero if we set any tab stops, zero if not. 2831590Srgrimes */ 2841590Srgrimesint 285200419Sdelphijset_tabs(void) 2861590Srgrimes{ 2871590Srgrimes int c; 2881590Srgrimes char *capsp, *clear_tabs; 28987701Smarkm char *set_column, *set_pos, *Set_tab; 2901590Srgrimes char caps[1024]; 29187701Smarkm const char *tg_out; 2921590Srgrimes 2931590Srgrimes capsp = caps; 29450638Speter Set_tab = tgetstr("st", &capsp); 2951590Srgrimes 29650638Speter if (Set_tab && (clear_tabs = tgetstr("ct", &capsp))) { 2971590Srgrimes (void)putc('\r', stderr); /* Force to left margin. */ 2981590Srgrimes tputs(clear_tabs, 0, outc); 2991590Srgrimes } 3001590Srgrimes 3011590Srgrimes set_column = tgetstr("ch", &capsp); 3021590Srgrimes set_pos = set_column ? NULL : tgetstr("cm", &capsp); 3031590Srgrimes 30450638Speter if (Set_tab) { 30550638Speter for (c = 8; c < Columns; c += 8) { 3061590Srgrimes /* 3071590Srgrimes * Get to the right column. "OOPS" is returned by 3081590Srgrimes * tgoto() if it can't do the job. (*snarl*) 3091590Srgrimes */ 3101590Srgrimes tg_out = "OOPS"; 3111590Srgrimes if (set_column) 3121590Srgrimes tg_out = tgoto(set_column, 0, c); 3131590Srgrimes if (*tg_out == 'O' && set_pos) 31450638Speter tg_out = tgoto(set_pos, c, Lines - 1); 3151590Srgrimes if (*tg_out != 'O') 3161590Srgrimes tputs(tg_out, 1, outc); 3171590Srgrimes else 3181590Srgrimes (void)fprintf(stderr, "%s", " "); 3191590Srgrimes /* Set the tab. */ 32050638Speter tputs(Set_tab, 0, outc); 3211590Srgrimes } 3221590Srgrimes putc('\r', stderr); 3231590Srgrimes return (1); 3241590Srgrimes } 3251590Srgrimes return (0); 3261590Srgrimes} 327