xref: /csrg-svn/usr.bin/tset/set.c (revision 66289)
152054Sbostic /*-
263080Sbostic  * Copyright (c) 1991, 1993
363080Sbostic  *	The Regents of the University of California.  All rights reserved.
452054Sbostic  *
552054Sbostic  * %sccs.include.redist.c%
652054Sbostic  */
752054Sbostic 
852054Sbostic #ifndef lint
9*66289Sbostic static char sccsid[] = "@(#)set.c	8.2 (Berkeley) 02/28/94";
1052054Sbostic #endif /* not lint */
1152054Sbostic 
1252054Sbostic #include <termios.h>
1352054Sbostic #include <unistd.h>
1452054Sbostic #include <stdio.h>
1552054Sbostic #include "extern.h"
1652054Sbostic 
1752054Sbostic #define	CHK(val, dft)	(val <= 0 ? dft : val)
1852054Sbostic 
1952054Sbostic int	set_tabs __P((void));
2052054Sbostic 
2152054Sbostic /*
2252054Sbostic  * Reset the terminal mode bits to a sensible state.  Very useful after
2352054Sbostic  * a child program dies in raw mode.
2452054Sbostic  */
2552054Sbostic void
reset_mode()2652054Sbostic reset_mode()
2752054Sbostic {
2852054Sbostic 	tcgetattr(STDERR_FILENO, &mode);
2952054Sbostic 
3052054Sbostic #if defined(VDISCARD) && defined(CDISCARD)
3152054Sbostic 	mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD);
3252054Sbostic #endif
3352054Sbostic 	mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF);
3452054Sbostic 	mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE);
3552054Sbostic #if defined(VFLUSH) && defined(CFLUSH)
3652054Sbostic 	mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH);
3752054Sbostic #endif
3852054Sbostic 	mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR);
3952054Sbostic 	mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL);
4052054Sbostic #if defined(VLNEXT) && defined(CLNEXT)
4152054Sbostic 	mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT);
4252054Sbostic #endif
4352054Sbostic 	mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT);
4452054Sbostic #if defined(VREPRINT) && defined(CRPRNT)
4552054Sbostic 	mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT);
4652054Sbostic #endif
4752054Sbostic 	mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART);
4852054Sbostic 	mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP);
4952054Sbostic 	mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP);
5052054Sbostic #if defined(VWERASE) && defined(CWERASE)
5152054Sbostic 	mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE);
5252054Sbostic #endif
5352054Sbostic 
5452054Sbostic 	mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR
5552054Sbostic #ifdef IUCLC
5652054Sbostic 			  | IUCLC
5752054Sbostic #endif
5852054Sbostic #ifdef IXANY
5952054Sbostic 			  | IXANY
6052054Sbostic #endif
6152054Sbostic 			  | IXOFF);
6252054Sbostic 
6352054Sbostic 	mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON
6452054Sbostic #ifdef IMAXBEL
6552054Sbostic 			 | IMAXBEL
6652054Sbostic #endif
6752054Sbostic 			 );
6852054Sbostic 
6952054Sbostic 	mode.c_oflag &= ~(0
7052054Sbostic #ifdef OLCUC
7152054Sbostic 			  | OLCUC
7252054Sbostic #endif
7352054Sbostic #ifdef OCRNL
7452054Sbostic 			  | OCRNL
7552054Sbostic #endif
7652054Sbostic #ifdef ONOCR
7752054Sbostic 			  | ONOCR
7852054Sbostic #endif
7952054Sbostic #ifdef ONLRET
8052054Sbostic 			  | ONLRET
8152054Sbostic #endif
8252054Sbostic #ifdef OFILL
8352054Sbostic 			  | OFILL
8452054Sbostic #endif
8552054Sbostic #ifdef OFDEL
8652054Sbostic 			  | OFDEL
8752054Sbostic #endif
8852054Sbostic #ifdef NLDLY
8952054Sbostic 			  | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY
9052054Sbostic #endif
9152054Sbostic 			  );
9252054Sbostic 
9352054Sbostic 	mode.c_oflag |= (OPOST
9452054Sbostic #ifdef ONLCR
9552054Sbostic 			 | ONLCR
9652054Sbostic #endif
9752054Sbostic 			 );
9852054Sbostic 
9952054Sbostic 	mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | CLOCAL);
10052054Sbostic 	mode.c_cflag |= (CS8 | CREAD);
10152054Sbostic 	mode.c_lflag &= ~(ECHONL | NOFLSH | TOSTOP
10252054Sbostic #ifdef ECHOPTR
10352054Sbostic 			  | ECHOPRT
10452054Sbostic #endif
10552054Sbostic #ifdef XCASE
10652054Sbostic 			  | XCASE
10752054Sbostic #endif
10852054Sbostic 			  );
10952054Sbostic 
11052054Sbostic 	mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK
11152054Sbostic #ifdef ECHOCTL
11252054Sbostic 			 | ECHOCTL
11352054Sbostic #endif
11452054Sbostic #ifdef ECHOKE
11552054Sbostic 			 | ECHOKE
11652054Sbostic #endif
11752054Sbostic  			 );
11852054Sbostic 
11952054Sbostic 	tcsetattr(STDERR_FILENO, TCSADRAIN, &mode);
12052054Sbostic }
12152054Sbostic 
12252054Sbostic /*
12352054Sbostic  * Determine the erase, interrupt, and kill characters from the termcap
12452054Sbostic  * entry and command line and update their values in 'mode'.
12552054Sbostic  */
12652054Sbostic void
set_control_chars()12752054Sbostic set_control_chars()
12852054Sbostic {
12952054Sbostic 	char *bp, *p, bs_char, buf[1024];
13052054Sbostic 
13152054Sbostic 	bp = buf;
13252054Sbostic 	p = tgetstr("kb", &bp);
13352054Sbostic 	if (p == NULL || p[1] != '\0')
13452054Sbostic 		p = tgetstr("bc", &bp);
13552054Sbostic 	if (p != NULL && p[1] == '\0')
13652054Sbostic 		bs_char = p[0];
13752054Sbostic 	else if (tgetflag("bs"))
13852054Sbostic 		bs_char = CTRL('h');
13952054Sbostic 	else
14052054Sbostic 		bs_char = 0;
14152054Sbostic 
14256931Sbostic 	if (erasechar == 0 && !tgetflag("os") && mode.c_cc[VERASE] != CERASE) {
14352054Sbostic 		if (tgetflag("bs") || bs_char != 0)
14452054Sbostic 			erasechar = -1;
14552054Sbostic 	}
14652054Sbostic 	if (erasechar < 0)
14752054Sbostic 		erasechar = (bs_char != 0) ? bs_char : CTRL('h');
14852063Sbostic 
14952054Sbostic 	if (mode.c_cc[VERASE] == 0 || erasechar != 0)
15052054Sbostic 		mode.c_cc[VERASE] = erasechar ? erasechar : CERASE;
15152063Sbostic 
15252054Sbostic 	if (mode.c_cc[VINTR] == 0 || intrchar != 0)
15352054Sbostic 		 mode.c_cc[VINTR] = intrchar ? intrchar : CINTR;
15452063Sbostic 
15552054Sbostic 	if (mode.c_cc[VKILL] == 0 || killchar != 0)
15652054Sbostic 		mode.c_cc[VKILL] = killchar ? killchar : CKILL;
15752054Sbostic }
15852054Sbostic 
15952054Sbostic /*
16052054Sbostic  * Set up various conversions in 'mode', including parity, tabs, returns,
16152054Sbostic  * echo, and case, according to the termcap entry.  If the program we're
16252054Sbostic  * running was named with a leading upper-case character, map external
16352054Sbostic  * uppercase to internal lowercase.
16452054Sbostic  */
16552054Sbostic void
set_conversions(usingupper)16652054Sbostic set_conversions(usingupper)
16752054Sbostic 	int usingupper;
16852054Sbostic {
16952054Sbostic 	if (tgetflag("UC") || usingupper) {
17052054Sbostic #ifdef IUCLC
17152054Sbostic 		mode.c_iflag |= IUCLC;
17252054Sbostic 		mode.c_oflag |= OLCUC;
17352054Sbostic #endif
17452054Sbostic 	} else if (tgetflag("LC")) {
17552054Sbostic #ifdef IUCLC
17652054Sbostic 		mode.c_iflag &= ~IUCLC;
17752054Sbostic 		mode.c_oflag &= ~OLCUC;
17852054Sbostic #endif
17952054Sbostic 	}
18052054Sbostic 	mode.c_iflag &= ~(PARMRK | INPCK);
18152054Sbostic 	mode.c_lflag |= ICANON;
18252054Sbostic 	if (tgetflag("EP")) {
18352054Sbostic 		mode.c_cflag |= PARENB;
18452054Sbostic 		mode.c_cflag &= ~PARODD;
18552054Sbostic 	}
18652054Sbostic 	if (tgetflag("OP")) {
18752054Sbostic 		mode.c_cflag |= PARENB;
18852054Sbostic 		mode.c_cflag |= PARODD;
18952054Sbostic 	}
19052063Sbostic 
19152054Sbostic #ifdef ONLCR
19252054Sbostic 	mode.c_oflag |= ONLCR;
19352054Sbostic #endif
19452054Sbostic 	mode.c_iflag |= ICRNL;
19552054Sbostic 	mode.c_lflag |= ECHO;
19652054Sbostic 	mode.c_oflag |= OXTABS;
19752054Sbostic 	if (tgetflag("NL")) {			/* Newline, not linefeed. */
19852054Sbostic #ifdef ONLCR
19952054Sbostic 		mode.c_oflag &= ~ONLCR;
20052054Sbostic #endif
20152054Sbostic 		mode.c_iflag &= ~ICRNL;
20252054Sbostic 	}
20352054Sbostic 	if (tgetflag("HD"))			/* Half duplex. */
20452054Sbostic 		mode.c_lflag &= ~ECHO;
20552054Sbostic 	if (tgetflag("pt"))			/* Print tabs. */
20652054Sbostic 		mode.c_oflag &= ~OXTABS;
20752054Sbostic 	mode.c_lflag |= (ECHOE | ECHOK);
20852054Sbostic }
20952054Sbostic 
21052054Sbostic /* Output startup string. */
21152054Sbostic void
set_init()21252054Sbostic set_init()
21352054Sbostic {
21452054Sbostic 	char *bp, buf[1024];
21552054Sbostic 	int settle;
21652054Sbostic 
21752054Sbostic 	bp = buf;
21852054Sbostic 	if (tgetstr("pc", &bp) != 0)		/* Get/set pad character. */
21952054Sbostic 		PC = buf[0];
22052054Sbostic 
22152054Sbostic #ifdef TAB3
22252054Sbostic 	if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) {
22352054Sbostic 		oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET);
22452054Sbostic 		tcsetattr(STDERR_FILENO, TCSADRAIN, &oldmode);
22552054Sbostic 	}
22652054Sbostic #endif
22752054Sbostic 	settle = set_tabs();
22852054Sbostic 
22952054Sbostic 	if (isreset) {
230*66289Sbostic 		bp = buf;
23152054Sbostic 		if (tgetstr("rs", &bp) != 0 || tgetstr("is", &bp) != 0) {
23252054Sbostic 			tputs(buf, 0, outc);
23352054Sbostic 			settle = 1;
23452054Sbostic 		}
235*66289Sbostic 		bp = buf;
23652054Sbostic 		if (tgetstr("rf", &bp) != 0 || tgetstr("if", &bp) != 0) {
23752054Sbostic 			cat(buf);
23852054Sbostic 			settle = 1;
23952054Sbostic 		}
24052054Sbostic 	}
24152063Sbostic 
24252054Sbostic 	if (settle) {
24352054Sbostic 		(void)putc('\r', stderr);
24452054Sbostic 		(void)fflush(stderr);
24552054Sbostic 		(void)sleep(1);			/* Settle the terminal. */
24652054Sbostic 	}
24752054Sbostic }
24852054Sbostic 
24952054Sbostic /*
25052054Sbostic  * Set the hardware tabs on the terminal, using the ct (clear all tabs),
25152054Sbostic  * st (set one tab) and ch (horizontal cursor addressing) capabilities.
25252054Sbostic  * This is done before if and is, so they can patch in case we blow this.
25352054Sbostic  * Return nonzero if we set any tab stops, zero if not.
25452054Sbostic  */
25552054Sbostic int
set_tabs()25652054Sbostic set_tabs()
25752054Sbostic {
25852054Sbostic 	int c;
25952054Sbostic 	char *capsp, *clear_tabs;
26052054Sbostic 	char *set_column, *set_pos, *set_tab, *tg_out;
26152054Sbostic 	char caps[1024];
26252054Sbostic 
26352054Sbostic 	capsp = caps;
26452054Sbostic 	set_tab = tgetstr("st", &capsp);
26552054Sbostic 
26652054Sbostic 	if (set_tab && (clear_tabs = tgetstr("ct", &capsp))) {
26752054Sbostic 		(void)putc('\r', stderr);	/* Force to left margin. */
26852054Sbostic 		tputs(clear_tabs, 0, outc);
26952054Sbostic 	}
27052054Sbostic 
27152054Sbostic 	set_column = tgetstr("ch", &capsp);
27252054Sbostic 	set_pos = set_column ? NULL : tgetstr("cm", &capsp);
27352054Sbostic 
27452054Sbostic 	if (set_tab) {
27552054Sbostic 		for (c = 8; c < columns; c += 8) {
27652054Sbostic 			/*
27752054Sbostic 			 * Get to the right column.  "OOPS" is returned by
27852054Sbostic 			 * tgoto() if it can't do the job.  (*snarl*)
27952054Sbostic 			 */
28052054Sbostic 			tg_out = "OOPS";
28152054Sbostic 			if (set_column)
28252054Sbostic 				tg_out = tgoto(set_column, 0, c);
28352054Sbostic 			if (*tg_out == 'O' && set_pos)
28452054Sbostic 				tg_out = tgoto(set_pos, c, lines - 1);
28552054Sbostic 			if (*tg_out != 'O')
28652054Sbostic 				tputs(tg_out, 1, outc);
28752054Sbostic 			else
28852054Sbostic 				(void)fprintf(stderr, "%s", "        ");
28952054Sbostic 			/* Set the tab. */
29052054Sbostic 			tputs(set_tab, 0, outc);
29152054Sbostic 		}
29252054Sbostic 		putc('\r', stderr);
29352054Sbostic 		return (1);
29452054Sbostic 	}
29552054Sbostic 	return (0);
29652054Sbostic }
297