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