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. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * @(#)set.c 8.2 (Berkeley) 2/28/94
34 * $FreeBSD: src/usr.bin/tset/set.c,v 1.7.2.1 2000/11/12 07:48:29 dg Exp $
35 * $DragonFly: src/usr.bin/tset/set.c,v 1.3 2003/10/04 20:36:53 hmp Exp $
43 #define CHK(val, dft) (val <= 0 ? dft : val)
48 * Reset the terminal mode bits to a sensible state. Very useful after
49 * a child program dies in raw mode.
54 tcgetattr(STDERR_FILENO
, &mode
);
56 #if defined(VDISCARD) && defined(CDISCARD)
57 mode
.c_cc
[VDISCARD
] = CHK(mode
.c_cc
[VDISCARD
], CDISCARD
);
59 mode
.c_cc
[VEOF
] = CHK(mode
.c_cc
[VEOF
], CEOF
);
60 mode
.c_cc
[VERASE
] = CHK(mode
.c_cc
[VERASE
], CERASE
);
61 #if defined(VFLUSH) && defined(CFLUSH)
62 mode
.c_cc
[VFLUSH
] = CHK(mode
.c_cc
[VFLUSH
], CFLUSH
);
64 mode
.c_cc
[VINTR
] = CHK(mode
.c_cc
[VINTR
], CINTR
);
65 mode
.c_cc
[VKILL
] = CHK(mode
.c_cc
[VKILL
], CKILL
);
66 #if defined(VLNEXT) && defined(CLNEXT)
67 mode
.c_cc
[VLNEXT
] = CHK(mode
.c_cc
[VLNEXT
], CLNEXT
);
69 mode
.c_cc
[VQUIT
] = CHK(mode
.c_cc
[VQUIT
], CQUIT
);
70 #if defined(VREPRINT) && defined(CRPRNT)
71 mode
.c_cc
[VREPRINT
] = CHK(mode
.c_cc
[VREPRINT
], CRPRNT
);
73 mode
.c_cc
[VSTART
] = CHK(mode
.c_cc
[VSTART
], CSTART
);
74 mode
.c_cc
[VSTOP
] = CHK(mode
.c_cc
[VSTOP
], CSTOP
);
75 mode
.c_cc
[VSUSP
] = CHK(mode
.c_cc
[VSUSP
], CSUSP
);
76 #if defined(VWERASE) && defined(CWERASE)
77 mode
.c_cc
[VWERASE
] = CHK(mode
.c_cc
[VWERASE
], CWERASE
);
80 mode
.c_iflag
&= ~(IGNBRK
| PARMRK
| INPCK
| ISTRIP
| INLCR
| IGNCR
89 mode
.c_iflag
|= (BRKINT
| IGNPAR
| ICRNL
| IXON
115 | NLDLY
| CRDLY
| TABDLY
| BSDLY
| VTDLY
| FFDLY
119 mode
.c_oflag
|= (OPOST
125 mode
.c_cflag
&= ~(CSIZE
| CSTOPB
| PARENB
| PARODD
| CLOCAL
);
126 mode
.c_cflag
|= (CS8
| CREAD
);
127 mode
.c_lflag
&= ~(ECHONL
| NOFLSH
| TOSTOP
136 mode
.c_lflag
|= (ISIG
| ICANON
| ECHO
| ECHOE
| ECHOK
145 tcsetattr(STDERR_FILENO
, TCSADRAIN
, &mode
);
149 * Determine the erase, interrupt, and kill characters from the termcap
150 * entry and command line and update their values in 'mode'.
153 set_control_chars(void)
155 char *bp
, *p
, bs_char
, buf
[1024];
158 p
= tgetstr("kb", &bp
);
159 if (p
== NULL
|| p
[1] != '\0')
160 p
= tgetstr("bc", &bp
);
161 if (p
!= NULL
&& p
[1] == '\0')
163 else if (tgetflag("bs"))
168 if (erasech
== 0 && bs_char
!= 0 && !tgetflag("os"))
171 erasech
= (bs_char
!= 0) ? bs_char
: CTRL('h');
173 if (mode
.c_cc
[VERASE
] == 0 || erasech
!= 0)
174 mode
.c_cc
[VERASE
] = erasech
? erasech
: CERASE
;
176 if (mode
.c_cc
[VINTR
] == 0 || intrchar
!= 0)
177 mode
.c_cc
[VINTR
] = intrchar
? intrchar
: CINTR
;
179 if (mode
.c_cc
[VKILL
] == 0 || killch
!= 0)
180 mode
.c_cc
[VKILL
] = killch
? killch
: CKILL
;
184 * Set up various conversions in 'mode', including parity, tabs, returns,
185 * echo, and case, according to the termcap entry. If the program we're
186 * running was named with a leading upper-case character, map external
187 * uppercase to internal lowercase.
190 set_conversions(int usingupper
)
192 if (tgetflag("UC") || usingupper
) {
194 mode
.c_iflag
|= IUCLC
;
195 mode
.c_oflag
|= OLCUC
;
197 } else if (tgetflag("LC")) {
199 mode
.c_iflag
&= ~IUCLC
;
200 mode
.c_oflag
&= ~OLCUC
;
203 mode
.c_iflag
&= ~(PARMRK
| INPCK
);
204 mode
.c_lflag
|= ICANON
;
205 if (tgetflag("EP")) {
206 mode
.c_cflag
|= PARENB
;
207 mode
.c_cflag
&= ~PARODD
;
209 if (tgetflag("OP")) {
210 mode
.c_cflag
|= PARENB
;
211 mode
.c_cflag
|= PARODD
;
215 mode
.c_oflag
|= ONLCR
;
217 mode
.c_iflag
|= ICRNL
;
218 mode
.c_lflag
|= ECHO
;
219 mode
.c_oflag
|= OXTABS
;
220 if (tgetflag("NL")) { /* Newline, not linefeed. */
222 mode
.c_oflag
&= ~ONLCR
;
224 mode
.c_iflag
&= ~ICRNL
;
226 if (tgetflag("HD")) /* Half duplex. */
227 mode
.c_lflag
&= ~ECHO
;
228 if (tgetflag("pt")) /* Print tabs. */
229 mode
.c_oflag
&= ~OXTABS
;
230 mode
.c_lflag
|= (ECHOE
| ECHOK
);
233 /* Output startup string. */
241 if (tgetstr("pc", &bp
) != 0) /* Get/set pad character. */
245 if (oldmode
.c_oflag
& (TAB3
| ONLCR
| OCRNL
| ONLRET
)) {
246 oldmode
.c_oflag
&= (TAB3
| ONLCR
| OCRNL
| ONLRET
);
247 tcsetattr(STDERR_FILENO
, TCSADRAIN
, &oldmode
);
254 if (tgetstr("rs", &bp
) != 0 || tgetstr("is", &bp
) != 0) {
259 if (tgetstr("rf", &bp
) != 0 || tgetstr("if", &bp
) != 0) {
266 (void)putc('\r', stderr
);
267 (void)fflush(stderr
);
268 (void)sleep(1); /* Settle the terminal. */
273 * Set the hardware tabs on the terminal, using the ct (clear all tabs),
274 * st (set one tab) and ch (horizontal cursor addressing) capabilities.
275 * This is done before if and is, so they can patch in case we blow this.
276 * Return nonzero if we set any tab stops, zero if not.
282 char *capsp
, *clear_tabs
;
283 char *set_column
, *set_pos
, *Set_tab
, *tg_out
;
287 Set_tab
= tgetstr("st", &capsp
);
289 if (Set_tab
&& (clear_tabs
= tgetstr("ct", &capsp
))) {
290 (void)putc('\r', stderr
); /* Force to left margin. */
291 tputs(clear_tabs
, 0, outc
);
294 set_column
= tgetstr("ch", &capsp
);
295 set_pos
= set_column
? NULL
: tgetstr("cm", &capsp
);
298 for (c
= 8; c
< Columns
; c
+= 8) {
300 * Get to the right column. "OOPS" is returned by
301 * tgoto() if it can't do the job. (*snarl*)
305 tg_out
= tgoto(set_column
, 0, c
);
306 if (*tg_out
== 'O' && set_pos
)
307 tg_out
= tgoto(set_pos
, c
, Lines
- 1);
309 tputs(tg_out
, 1, outc
);
311 (void)fprintf(stderr
, "%s", " ");
313 tputs(Set_tab
, 0, outc
);