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