2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * @(#)set.c 8.2 (Berkeley) 2/28/94
30 * $FreeBSD: src/usr.bin/tset/set.c,v 1.7.2.1 2000/11/12 07:48:29 dg Exp $
31 * $DragonFly: src/usr.bin/tset/set.c,v 1.3 2003/10/04 20:36:53 hmp Exp $
39 #define CHK(val, dft) (val <= 0 ? dft : val)
44 * Reset the terminal mode bits to a sensible state. Very useful after
45 * a child program dies in raw mode.
50 tcgetattr(STDERR_FILENO
, &mode
);
52 #if defined(VDISCARD) && defined(CDISCARD)
53 mode
.c_cc
[VDISCARD
] = CHK(mode
.c_cc
[VDISCARD
], CDISCARD
);
55 mode
.c_cc
[VEOF
] = CHK(mode
.c_cc
[VEOF
], CEOF
);
56 mode
.c_cc
[VERASE
] = CHK(mode
.c_cc
[VERASE
], CERASE
);
57 #if defined(VFLUSH) && defined(CFLUSH)
58 mode
.c_cc
[VFLUSH
] = CHK(mode
.c_cc
[VFLUSH
], CFLUSH
);
60 mode
.c_cc
[VINTR
] = CHK(mode
.c_cc
[VINTR
], CINTR
);
61 mode
.c_cc
[VKILL
] = CHK(mode
.c_cc
[VKILL
], CKILL
);
62 #if defined(VLNEXT) && defined(CLNEXT)
63 mode
.c_cc
[VLNEXT
] = CHK(mode
.c_cc
[VLNEXT
], CLNEXT
);
65 mode
.c_cc
[VQUIT
] = CHK(mode
.c_cc
[VQUIT
], CQUIT
);
66 #if defined(VREPRINT) && defined(CRPRNT)
67 mode
.c_cc
[VREPRINT
] = CHK(mode
.c_cc
[VREPRINT
], CRPRNT
);
69 mode
.c_cc
[VSTART
] = CHK(mode
.c_cc
[VSTART
], CSTART
);
70 mode
.c_cc
[VSTOP
] = CHK(mode
.c_cc
[VSTOP
], CSTOP
);
71 mode
.c_cc
[VSUSP
] = CHK(mode
.c_cc
[VSUSP
], CSUSP
);
72 #if defined(VWERASE) && defined(CWERASE)
73 mode
.c_cc
[VWERASE
] = CHK(mode
.c_cc
[VWERASE
], CWERASE
);
76 mode
.c_iflag
&= ~(IGNBRK
| PARMRK
| INPCK
| ISTRIP
| INLCR
| IGNCR
85 mode
.c_iflag
|= (BRKINT
| IGNPAR
| ICRNL
| IXON
111 | NLDLY
| CRDLY
| TABDLY
| BSDLY
| VTDLY
| FFDLY
115 mode
.c_oflag
|= (OPOST
121 mode
.c_cflag
&= ~(CSIZE
| CSTOPB
| PARENB
| PARODD
| CLOCAL
);
122 mode
.c_cflag
|= (CS8
| CREAD
);
123 mode
.c_lflag
&= ~(ECHONL
| NOFLSH
| TOSTOP
132 mode
.c_lflag
|= (ISIG
| ICANON
| ECHO
| ECHOE
| ECHOK
141 tcsetattr(STDERR_FILENO
, TCSADRAIN
, &mode
);
145 * Determine the erase, interrupt, and kill characters from the termcap
146 * entry and command line and update their values in 'mode'.
149 set_control_chars(void)
151 char *bp
, *p
, bs_char
, buf
[1024];
154 p
= tgetstr("kb", &bp
);
155 if (p
== NULL
|| p
[1] != '\0')
156 p
= tgetstr("bc", &bp
);
157 if (p
!= NULL
&& p
[1] == '\0')
159 else if (tgetflag("bs"))
164 if (erasech
== 0 && bs_char
!= 0 && !tgetflag("os"))
167 erasech
= (bs_char
!= 0) ? bs_char
: CTRL('h');
169 if (mode
.c_cc
[VERASE
] == 0 || erasech
!= 0)
170 mode
.c_cc
[VERASE
] = erasech
? erasech
: CERASE
;
172 if (mode
.c_cc
[VINTR
] == 0 || intrchar
!= 0)
173 mode
.c_cc
[VINTR
] = intrchar
? intrchar
: CINTR
;
175 if (mode
.c_cc
[VKILL
] == 0 || killch
!= 0)
176 mode
.c_cc
[VKILL
] = killch
? killch
: CKILL
;
180 * Set up various conversions in 'mode', including parity, tabs, returns,
181 * echo, and case, according to the termcap entry. If the program we're
182 * running was named with a leading upper-case character, map external
183 * uppercase to internal lowercase.
186 set_conversions(int usingupper
)
188 if (tgetflag("UC") || usingupper
) {
190 mode
.c_iflag
|= IUCLC
;
191 mode
.c_oflag
|= OLCUC
;
193 } else if (tgetflag("LC")) {
195 mode
.c_iflag
&= ~IUCLC
;
196 mode
.c_oflag
&= ~OLCUC
;
199 mode
.c_iflag
&= ~(PARMRK
| INPCK
);
200 mode
.c_lflag
|= ICANON
;
201 if (tgetflag("EP")) {
202 mode
.c_cflag
|= PARENB
;
203 mode
.c_cflag
&= ~PARODD
;
205 if (tgetflag("OP")) {
206 mode
.c_cflag
|= PARENB
;
207 mode
.c_cflag
|= PARODD
;
211 mode
.c_oflag
|= ONLCR
;
213 mode
.c_iflag
|= ICRNL
;
214 mode
.c_lflag
|= ECHO
;
215 mode
.c_oflag
|= OXTABS
;
216 if (tgetflag("NL")) { /* Newline, not linefeed. */
218 mode
.c_oflag
&= ~ONLCR
;
220 mode
.c_iflag
&= ~ICRNL
;
222 if (tgetflag("HD")) /* Half duplex. */
223 mode
.c_lflag
&= ~ECHO
;
224 if (tgetflag("pt")) /* Print tabs. */
225 mode
.c_oflag
&= ~OXTABS
;
226 mode
.c_lflag
|= (ECHOE
| ECHOK
);
229 /* Output startup string. */
237 if (tgetstr("pc", &bp
) != 0) /* Get/set pad character. */
241 if (oldmode
.c_oflag
& (TAB3
| ONLCR
| OCRNL
| ONLRET
)) {
242 oldmode
.c_oflag
&= (TAB3
| ONLCR
| OCRNL
| ONLRET
);
243 tcsetattr(STDERR_FILENO
, TCSADRAIN
, &oldmode
);
250 if (tgetstr("rs", &bp
) != 0 || tgetstr("is", &bp
) != 0) {
255 if (tgetstr("rf", &bp
) != 0 || tgetstr("if", &bp
) != 0) {
262 (void)putc('\r', stderr
);
263 (void)fflush(stderr
);
264 (void)sleep(1); /* Settle the terminal. */
269 * Set the hardware tabs on the terminal, using the ct (clear all tabs),
270 * st (set one tab) and ch (horizontal cursor addressing) capabilities.
271 * This is done before if and is, so they can patch in case we blow this.
272 * Return nonzero if we set any tab stops, zero if not.
278 char *capsp
, *clear_tabs
;
279 char *set_column
, *set_pos
, *Set_tab
;
284 Set_tab
= tgetstr("st", &capsp
);
286 if (Set_tab
&& (clear_tabs
= tgetstr("ct", &capsp
))) {
287 (void)putc('\r', stderr
); /* Force to left margin. */
288 tputs(clear_tabs
, 0, outc
);
291 set_column
= tgetstr("ch", &capsp
);
292 set_pos
= set_column
? NULL
: tgetstr("cm", &capsp
);
295 for (c
= 8; c
< Columns
; c
+= 8) {
297 * Get to the right column. "OOPS" is returned by
298 * tgoto() if it can't do the job. (*snarl*)
302 tg_out
= tgoto(set_column
, 0, c
);
303 if (*tg_out
== 'O' && set_pos
)
304 tg_out
= tgoto(set_pos
, c
, Lines
- 1);
306 tputs(tg_out
, 1, outc
);
308 (void)fprintf(stderr
, "%s", " ");
310 tputs(Set_tab
, 0, outc
);