Annotation of src/usr.bin/tset/set.c, Revision 1.3
1.3 ! millert 1: /* $OpenBSD: set.c,v 1.2 1996/06/26 05:41:56 deraadt Exp $ */
1.1 deraadt 2: /* $NetBSD: set.c,v 1.6 1994/12/07 05:08:10 jtc Exp $ */
3:
4: /*-
5: * Copyright (c) 1991, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: */
36:
37: #ifndef lint
38: #if 0
39: static char sccsid[] = "@(#)set.c 8.2 (Berkeley) 2/28/94";
40: #endif
1.3 ! millert 41: static char rcsid[] = "$OpenBSD: set.c,v 1.2 1996/06/26 05:41:56 deraadt Exp $";
1.1 deraadt 42: #endif /* not lint */
43:
44: #include <termios.h>
45: #include <unistd.h>
46: #include <stdio.h>
47: #include "extern.h"
48:
49: #define CHK(val, dft) (val <= 0 ? dft : val)
50:
51: int set_tabs __P((void));
52:
53: /*
54: * Reset the terminal mode bits to a sensible state. Very useful after
55: * a child program dies in raw mode.
56: */
57: void
58: reset_mode()
59: {
60: tcgetattr(STDERR_FILENO, &mode);
61:
62: #if defined(VDISCARD) && defined(CDISCARD)
63: mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD);
64: #endif
65: mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF);
66: mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE);
67: #if defined(VFLUSH) && defined(CFLUSH)
68: mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH);
69: #endif
70: mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR);
71: mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL);
72: #if defined(VLNEXT) && defined(CLNEXT)
73: mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT);
74: #endif
75: mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT);
76: #if defined(VREPRINT) && defined(CRPRNT)
77: mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT);
78: #endif
79: mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART);
80: mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP);
81: mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP);
82: #if defined(VWERASE) && defined(CWERASE)
83: mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE);
84: #endif
85:
86: mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR
87: #ifdef IUCLC
88: | IUCLC
89: #endif
90: #ifdef IXANY
91: | IXANY
92: #endif
93: | IXOFF);
94:
95: mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON
96: #ifdef IMAXBEL
97: | IMAXBEL
98: #endif
99: );
100:
101: mode.c_oflag &= ~(0
102: #ifdef OLCUC
103: | OLCUC
104: #endif
105: #ifdef OCRNL
106: | OCRNL
107: #endif
108: #ifdef ONOCR
109: | ONOCR
110: #endif
111: #ifdef ONLRET
112: | ONLRET
113: #endif
114: #ifdef OFILL
115: | OFILL
116: #endif
117: #ifdef OFDEL
118: | OFDEL
119: #endif
120: #ifdef NLDLY
121: | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY
122: #endif
123: );
124:
125: mode.c_oflag |= (OPOST
126: #ifdef ONLCR
127: | ONLCR
128: #endif
129: );
130:
131: mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD);
132: mode.c_cflag |= (CS8 | CREAD);
133: mode.c_lflag &= ~(ECHONL | NOFLSH | TOSTOP
134: #ifdef ECHOPTR
135: | ECHOPRT
136: #endif
137: #ifdef XCASE
138: | XCASE
139: #endif
140: );
141:
142: mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK
143: #ifdef ECHOCTL
144: | ECHOCTL
145: #endif
146: #ifdef ECHOKE
147: | ECHOKE
148: #endif
149: );
150:
151: tcsetattr(STDERR_FILENO, TCSADRAIN, &mode);
152: }
153:
154: /*
155: * Determine the erase, interrupt, and kill characters from the termcap
156: * entry and command line and update their values in 'mode'.
157: */
158: void
159: set_control_chars()
160: {
161: char *bp, *p, bs_char, buf[1024];
162:
163: bp = buf;
164: p = tgetstr("kb", &bp);
165: if (p == NULL || p[1] != '\0')
166: p = tgetstr("bc", &bp);
167: if (p != NULL && p[1] == '\0')
168: bs_char = p[0];
169: else if (tgetflag("bs"))
170: bs_char = CTRL('h');
171: else
172: bs_char = 0;
173:
174: if (erasechar == 0 && !tgetflag("os") && mode.c_cc[VERASE] != CERASE) {
175: if (tgetflag("bs") || bs_char != 0)
176: erasechar = -1;
177: }
178: if (erasechar < 0)
179: erasechar = (bs_char != 0) ? bs_char : CTRL('h');
180:
181: if (mode.c_cc[VERASE] == 0 || erasechar != 0)
182: mode.c_cc[VERASE] = erasechar ? erasechar : CERASE;
183:
184: if (mode.c_cc[VINTR] == 0 || intrchar != 0)
185: mode.c_cc[VINTR] = intrchar ? intrchar : CINTR;
186:
187: if (mode.c_cc[VKILL] == 0 || killchar != 0)
188: mode.c_cc[VKILL] = killchar ? killchar : CKILL;
189: }
190:
191: /*
192: * Set up various conversions in 'mode', including parity, tabs, returns,
193: * echo, and case, according to the termcap entry. If the program we're
194: * running was named with a leading upper-case character, map external
195: * uppercase to internal lowercase.
196: */
197: void
198: set_conversions(usingupper)
199: int usingupper;
200: {
201: if (tgetflag("UC") || usingupper) {
202: #ifdef IUCLC
203: mode.c_iflag |= IUCLC;
204: mode.c_oflag |= OLCUC;
205: #endif
206: } else if (tgetflag("LC")) {
207: #ifdef IUCLC
208: mode.c_iflag &= ~IUCLC;
209: mode.c_oflag &= ~OLCUC;
210: #endif
211: }
212: mode.c_iflag &= ~(PARMRK | INPCK);
213: mode.c_lflag |= ICANON;
214: if (tgetflag("EP")) {
215: mode.c_cflag |= PARENB;
216: mode.c_cflag &= ~PARODD;
217: }
218: if (tgetflag("OP")) {
219: mode.c_cflag |= PARENB;
220: mode.c_cflag |= PARODD;
221: }
222:
223: #ifdef ONLCR
224: mode.c_oflag |= ONLCR;
225: #endif
226: mode.c_iflag |= ICRNL;
227: mode.c_lflag |= ECHO;
228: mode.c_oflag |= OXTABS;
229: if (tgetflag("NL")) { /* Newline, not linefeed. */
230: #ifdef ONLCR
231: mode.c_oflag &= ~ONLCR;
232: #endif
233: mode.c_iflag &= ~ICRNL;
234: }
235: if (tgetflag("HD")) /* Half duplex. */
236: mode.c_lflag &= ~ECHO;
237: if (tgetflag("pt")) /* Print tabs. */
238: mode.c_oflag &= ~OXTABS;
239: mode.c_lflag |= (ECHOE | ECHOK);
240: }
241:
242: /* Output startup string. */
243: void
244: set_init()
245: {
246: char *bp, buf[1024];
247: int settle;
248:
249: bp = buf;
250: if (tgetstr("pc", &bp) != 0) /* Get/set pad character. */
251: PC = buf[0];
252:
253: #ifdef TAB3
254: if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) {
255: oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET);
256: tcsetattr(STDERR_FILENO, TCSADRAIN, &oldmode);
257: }
258: #endif
259: settle = set_tabs();
260:
261: if (isreset) {
262: bp = buf;
263: if (tgetstr("rs", &bp) != 0 || tgetstr("is", &bp) != 0) {
264: tputs(buf, 0, outc);
265: settle = 1;
266: }
267: bp = buf;
268: if (tgetstr("rf", &bp) != 0 || tgetstr("if", &bp) != 0) {
269: cat(buf);
270: settle = 1;
271: }
272: }
273:
274: if (settle) {
275: (void)putc('\r', stderr);
276: (void)sleep(1); /* Settle the terminal. */
277: }
278: }
279:
280: /*
281: * Set the hardware tabs on the terminal, using the ct (clear all tabs),
282: * st (set one tab) and ch (horizontal cursor addressing) capabilities.
283: * This is done before if and is, so they can patch in case we blow this.
284: * Return nonzero if we set any tab stops, zero if not.
285: */
286: int
287: set_tabs()
288: {
289: int c;
290: char *capsp, *clear_tabs;
291: char *set_column, *set_pos, *set_tab, *tg_out;
292: char caps[1024];
293:
294: capsp = caps;
295: set_tab = tgetstr("st", &capsp);
296:
297: if (set_tab && (clear_tabs = tgetstr("ct", &capsp))) {
298: (void)putc('\r', stderr); /* Force to left margin. */
299: tputs(clear_tabs, 0, outc);
300: }
301:
302: set_column = tgetstr("ch", &capsp);
303: set_pos = set_column ? NULL : tgetstr("cm", &capsp);
304:
305: if (set_tab) {
306: for (c = 8; c < columns; c += 8) {
307: /*
308: * Get to the right column. "OOPS" is returned by
309: * tgoto() if it can't do the job. (*snarl*)
310: */
311: tg_out = "OOPS";
312: if (set_column)
313: tg_out = tgoto(set_column, 0, c);
314: if (*tg_out == 'O' && set_pos)
315: tg_out = tgoto(set_pos, c, lines - 1);
316: if (*tg_out != 'O')
317: tputs(tg_out, 1, outc);
318: else
319: (void)fprintf(stderr, "%s", " ");
320: /* Set the tab. */
321: tputs(set_tab, 0, outc);
322: }
1.3 ! millert 323: (void)putc('\r', stderr);
1.1 deraadt 324: return (1);
325: }
326: return (0);
327: }