1*c7ef0cfcSnicm /****************************************************************************
2*c7ef0cfcSnicm * Copyright 2019-2021,2023 Thomas E. Dickey *
3*c7ef0cfcSnicm * Copyright 2016,2017 Free Software Foundation, Inc. *
4*c7ef0cfcSnicm * *
5*c7ef0cfcSnicm * Permission is hereby granted, free of charge, to any person obtaining a *
6*c7ef0cfcSnicm * copy of this software and associated documentation files (the *
7*c7ef0cfcSnicm * "Software"), to deal in the Software without restriction, including *
8*c7ef0cfcSnicm * without limitation the rights to use, copy, modify, merge, publish, *
9*c7ef0cfcSnicm * distribute, distribute with modifications, sublicense, and/or sell *
10*c7ef0cfcSnicm * copies of the Software, and to permit persons to whom the Software is *
11*c7ef0cfcSnicm * furnished to do so, subject to the following conditions: *
12*c7ef0cfcSnicm * *
13*c7ef0cfcSnicm * The above copyright notice and this permission notice shall be included *
14*c7ef0cfcSnicm * in all copies or substantial portions of the Software. *
15*c7ef0cfcSnicm * *
16*c7ef0cfcSnicm * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
17*c7ef0cfcSnicm * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
18*c7ef0cfcSnicm * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
19*c7ef0cfcSnicm * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
20*c7ef0cfcSnicm * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
21*c7ef0cfcSnicm * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
22*c7ef0cfcSnicm * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
23*c7ef0cfcSnicm * *
24*c7ef0cfcSnicm * Except as contained in this notice, the name(s) of the above copyright *
25*c7ef0cfcSnicm * holders shall not be used in advertising or otherwise to promote the *
26*c7ef0cfcSnicm * sale, use or other dealings in this Software without prior written *
27*c7ef0cfcSnicm * authorization. *
28*c7ef0cfcSnicm ****************************************************************************/
29*c7ef0cfcSnicm
30*c7ef0cfcSnicm /****************************************************************************
31*c7ef0cfcSnicm * Author: Thomas E. Dickey *
32*c7ef0cfcSnicm ****************************************************************************/
33*c7ef0cfcSnicm
34*c7ef0cfcSnicm #include <reset_cmd.h>
35*c7ef0cfcSnicm #include <tty_settings.h>
36*c7ef0cfcSnicm
37*c7ef0cfcSnicm #include <errno.h>
38*c7ef0cfcSnicm #include <stdio.h>
39*c7ef0cfcSnicm #include <fcntl.h>
40*c7ef0cfcSnicm
41*c7ef0cfcSnicm #if HAVE_SIZECHANGE
42*c7ef0cfcSnicm # if !defined(sun) || !TERMIOS
43*c7ef0cfcSnicm # if HAVE_SYS_IOCTL_H
44*c7ef0cfcSnicm # include <sys/ioctl.h>
45*c7ef0cfcSnicm # endif
46*c7ef0cfcSnicm # endif
47*c7ef0cfcSnicm #endif
48*c7ef0cfcSnicm
49*c7ef0cfcSnicm #if NEED_PTEM_H
50*c7ef0cfcSnicm /* they neglected to define struct winsize in termios.h -- it is only
51*c7ef0cfcSnicm in termio.h */
52*c7ef0cfcSnicm #include <sys/stream.h>
53*c7ef0cfcSnicm #include <sys/ptem.h>
54*c7ef0cfcSnicm #endif
55*c7ef0cfcSnicm
56*c7ef0cfcSnicm MODULE_ID("$Id: reset_cmd.c,v 1.1 2023/10/17 09:52:10 nicm Exp $")
57*c7ef0cfcSnicm
58*c7ef0cfcSnicm /*
59*c7ef0cfcSnicm * SCO defines TIOCGSIZE and the corresponding struct. Other systems (SunOS,
60*c7ef0cfcSnicm * Solaris, IRIX) define TIOCGWINSZ and struct winsize.
61*c7ef0cfcSnicm */
62*c7ef0cfcSnicm #ifdef TIOCGSIZE
63*c7ef0cfcSnicm # define IOCTL_GET_WINSIZE TIOCGSIZE
64*c7ef0cfcSnicm # define IOCTL_SET_WINSIZE TIOCSSIZE
65*c7ef0cfcSnicm # define STRUCT_WINSIZE struct ttysize
66*c7ef0cfcSnicm # define WINSIZE_ROWS(n) n.ts_lines
67*c7ef0cfcSnicm # define WINSIZE_COLS(n) n.ts_cols
68*c7ef0cfcSnicm #else
69*c7ef0cfcSnicm # ifdef TIOCGWINSZ
70*c7ef0cfcSnicm # define IOCTL_GET_WINSIZE TIOCGWINSZ
71*c7ef0cfcSnicm # define IOCTL_SET_WINSIZE TIOCSWINSZ
72*c7ef0cfcSnicm # define STRUCT_WINSIZE struct winsize
73*c7ef0cfcSnicm # define WINSIZE_ROWS(n) n.ws_row
74*c7ef0cfcSnicm # define WINSIZE_COLS(n) n.ws_col
75*c7ef0cfcSnicm # endif
76*c7ef0cfcSnicm #endif
77*c7ef0cfcSnicm
78*c7ef0cfcSnicm static FILE *my_file;
79*c7ef0cfcSnicm
80*c7ef0cfcSnicm static bool use_reset = FALSE; /* invoked as reset */
81*c7ef0cfcSnicm static bool use_init = FALSE; /* invoked as init */
82*c7ef0cfcSnicm
83*c7ef0cfcSnicm static GCC_NORETURN void
failed(const char * msg)84*c7ef0cfcSnicm failed(const char *msg)
85*c7ef0cfcSnicm {
86*c7ef0cfcSnicm int code = errno;
87*c7ef0cfcSnicm
88*c7ef0cfcSnicm (void) fprintf(stderr, "%s: %s: %s\n", _nc_progname, msg, strerror(code));
89*c7ef0cfcSnicm restore_tty_settings();
90*c7ef0cfcSnicm (void) fprintf(my_file, "\n");
91*c7ef0cfcSnicm fflush(my_file);
92*c7ef0cfcSnicm ExitProgram(ErrSystem(code));
93*c7ef0cfcSnicm /* NOTREACHED */
94*c7ef0cfcSnicm }
95*c7ef0cfcSnicm
96*c7ef0cfcSnicm static bool
cat_file(char * file)97*c7ef0cfcSnicm cat_file(char *file)
98*c7ef0cfcSnicm {
99*c7ef0cfcSnicm FILE *fp;
100*c7ef0cfcSnicm size_t nr;
101*c7ef0cfcSnicm char buf[BUFSIZ];
102*c7ef0cfcSnicm bool sent = FALSE;
103*c7ef0cfcSnicm
104*c7ef0cfcSnicm if (file != 0) {
105*c7ef0cfcSnicm if ((fp = safe_fopen(file, "r")) == 0)
106*c7ef0cfcSnicm failed(file);
107*c7ef0cfcSnicm
108*c7ef0cfcSnicm while ((nr = fread(buf, sizeof(char), sizeof(buf), fp)) != 0) {
109*c7ef0cfcSnicm if (fwrite(buf, sizeof(char), nr, my_file) != nr) {
110*c7ef0cfcSnicm failed(file);
111*c7ef0cfcSnicm }
112*c7ef0cfcSnicm sent = TRUE;
113*c7ef0cfcSnicm }
114*c7ef0cfcSnicm fclose(fp);
115*c7ef0cfcSnicm }
116*c7ef0cfcSnicm return sent;
117*c7ef0cfcSnicm }
118*c7ef0cfcSnicm
119*c7ef0cfcSnicm static int
out_char(int c)120*c7ef0cfcSnicm out_char(int c)
121*c7ef0cfcSnicm {
122*c7ef0cfcSnicm return putc(c, my_file);
123*c7ef0cfcSnicm }
124*c7ef0cfcSnicm
125*c7ef0cfcSnicm /**************************************************************************
126*c7ef0cfcSnicm * Mode-setting logic
127*c7ef0cfcSnicm **************************************************************************/
128*c7ef0cfcSnicm
129*c7ef0cfcSnicm /* some BSD systems have these built in, some systems are missing
130*c7ef0cfcSnicm * one or more definitions. The safest solution is to override unless the
131*c7ef0cfcSnicm * commonly-altered ones are defined.
132*c7ef0cfcSnicm */
133*c7ef0cfcSnicm #if !(defined(CERASE) && defined(CINTR) && defined(CKILL) && defined(CQUIT))
134*c7ef0cfcSnicm #undef CEOF
135*c7ef0cfcSnicm #undef CERASE
136*c7ef0cfcSnicm #undef CINTR
137*c7ef0cfcSnicm #undef CKILL
138*c7ef0cfcSnicm #undef CLNEXT
139*c7ef0cfcSnicm #undef CRPRNT
140*c7ef0cfcSnicm #undef CQUIT
141*c7ef0cfcSnicm #undef CSTART
142*c7ef0cfcSnicm #undef CSTOP
143*c7ef0cfcSnicm #undef CSUSP
144*c7ef0cfcSnicm #endif
145*c7ef0cfcSnicm
146*c7ef0cfcSnicm /* control-character defaults */
147*c7ef0cfcSnicm #ifndef CEOF
148*c7ef0cfcSnicm #define CEOF CTRL('D')
149*c7ef0cfcSnicm #endif
150*c7ef0cfcSnicm #ifndef CERASE
151*c7ef0cfcSnicm #define CERASE CTRL('H')
152*c7ef0cfcSnicm #endif
153*c7ef0cfcSnicm #ifndef CINTR
154*c7ef0cfcSnicm #define CINTR 127 /* ^? */
155*c7ef0cfcSnicm #endif
156*c7ef0cfcSnicm #ifndef CKILL
157*c7ef0cfcSnicm #define CKILL CTRL('U')
158*c7ef0cfcSnicm #endif
159*c7ef0cfcSnicm #ifndef CLNEXT
160*c7ef0cfcSnicm #define CLNEXT CTRL('v')
161*c7ef0cfcSnicm #endif
162*c7ef0cfcSnicm #ifndef CRPRNT
163*c7ef0cfcSnicm #define CRPRNT CTRL('r')
164*c7ef0cfcSnicm #endif
165*c7ef0cfcSnicm #ifndef CQUIT
166*c7ef0cfcSnicm #define CQUIT CTRL('\\')
167*c7ef0cfcSnicm #endif
168*c7ef0cfcSnicm #ifndef CSTART
169*c7ef0cfcSnicm #define CSTART CTRL('Q')
170*c7ef0cfcSnicm #endif
171*c7ef0cfcSnicm #ifndef CSTOP
172*c7ef0cfcSnicm #define CSTOP CTRL('S')
173*c7ef0cfcSnicm #endif
174*c7ef0cfcSnicm #ifndef CSUSP
175*c7ef0cfcSnicm #define CSUSP CTRL('Z')
176*c7ef0cfcSnicm #endif
177*c7ef0cfcSnicm
178*c7ef0cfcSnicm #if defined(_POSIX_VDISABLE)
179*c7ef0cfcSnicm #define DISABLED(val) (((_POSIX_VDISABLE != -1) \
180*c7ef0cfcSnicm && ((val) == _POSIX_VDISABLE)) \
181*c7ef0cfcSnicm || ((val) <= 0))
182*c7ef0cfcSnicm #else
183*c7ef0cfcSnicm #define DISABLED(val) ((int)(val) <= 0)
184*c7ef0cfcSnicm #endif
185*c7ef0cfcSnicm
186*c7ef0cfcSnicm #define CHK(val, dft) (unsigned char) (DISABLED(val) ? dft : val)
187*c7ef0cfcSnicm
188*c7ef0cfcSnicm #define reset_char(item, value) \
189*c7ef0cfcSnicm tty_settings->c_cc[item] = CHK(tty_settings->c_cc[item], value)
190*c7ef0cfcSnicm
191*c7ef0cfcSnicm /*
192*c7ef0cfcSnicm * Reset the terminal mode bits to a sensible state. Very useful after
193*c7ef0cfcSnicm * a child program dies in raw mode.
194*c7ef0cfcSnicm */
195*c7ef0cfcSnicm void
reset_tty_settings(int fd,TTY * tty_settings,int noset)196*c7ef0cfcSnicm reset_tty_settings(int fd, TTY * tty_settings, int noset)
197*c7ef0cfcSnicm {
198*c7ef0cfcSnicm GET_TTY(fd, tty_settings);
199*c7ef0cfcSnicm
200*c7ef0cfcSnicm #ifdef TERMIOS
201*c7ef0cfcSnicm #if defined(VDISCARD) && defined(CDISCARD)
202*c7ef0cfcSnicm reset_char(VDISCARD, CDISCARD);
203*c7ef0cfcSnicm #endif
204*c7ef0cfcSnicm reset_char(VEOF, CEOF);
205*c7ef0cfcSnicm reset_char(VERASE, CERASE);
206*c7ef0cfcSnicm #if defined(VERASE2) && defined(CERASE2)
207*c7ef0cfcSnicm reset_char(VERASE2, CERASE2);
208*c7ef0cfcSnicm #endif
209*c7ef0cfcSnicm #if defined(VFLUSH) && defined(CFLUSH)
210*c7ef0cfcSnicm reset_char(VFLUSH, CFLUSH);
211*c7ef0cfcSnicm #endif
212*c7ef0cfcSnicm reset_char(VINTR, CINTR);
213*c7ef0cfcSnicm reset_char(VKILL, CKILL);
214*c7ef0cfcSnicm #if defined(VLNEXT) && defined(CLNEXT)
215*c7ef0cfcSnicm reset_char(VLNEXT, CLNEXT);
216*c7ef0cfcSnicm #endif
217*c7ef0cfcSnicm reset_char(VQUIT, CQUIT);
218*c7ef0cfcSnicm #if defined(VREPRINT) && defined(CRPRNT)
219*c7ef0cfcSnicm reset_char(VREPRINT, CRPRNT);
220*c7ef0cfcSnicm #endif
221*c7ef0cfcSnicm #if defined(VSTART) && defined(CSTART)
222*c7ef0cfcSnicm reset_char(VSTART, CSTART);
223*c7ef0cfcSnicm #endif
224*c7ef0cfcSnicm #if defined(VSTOP) && defined(CSTOP)
225*c7ef0cfcSnicm reset_char(VSTOP, CSTOP);
226*c7ef0cfcSnicm #endif
227*c7ef0cfcSnicm #if defined(VSUSP) && defined(CSUSP)
228*c7ef0cfcSnicm reset_char(VSUSP, CSUSP);
229*c7ef0cfcSnicm #endif
230*c7ef0cfcSnicm #if defined(VWERASE) && defined(CWERASE)
231*c7ef0cfcSnicm reset_char(VWERASE, CWERASE);
232*c7ef0cfcSnicm #endif
233*c7ef0cfcSnicm
234*c7ef0cfcSnicm tty_settings->c_iflag &= ~((unsigned) (IGNBRK
235*c7ef0cfcSnicm | PARMRK
236*c7ef0cfcSnicm | INPCK
237*c7ef0cfcSnicm | ISTRIP
238*c7ef0cfcSnicm | INLCR
239*c7ef0cfcSnicm | IGNCR
240*c7ef0cfcSnicm #ifdef IUCLC
241*c7ef0cfcSnicm | IUCLC
242*c7ef0cfcSnicm #endif
243*c7ef0cfcSnicm #ifdef IXANY
244*c7ef0cfcSnicm | IXANY
245*c7ef0cfcSnicm #endif
246*c7ef0cfcSnicm | IXOFF));
247*c7ef0cfcSnicm
248*c7ef0cfcSnicm tty_settings->c_iflag |= (BRKINT
249*c7ef0cfcSnicm | IGNPAR
250*c7ef0cfcSnicm | ICRNL
251*c7ef0cfcSnicm | IXON
252*c7ef0cfcSnicm #ifdef IMAXBEL
253*c7ef0cfcSnicm | IMAXBEL
254*c7ef0cfcSnicm #endif
255*c7ef0cfcSnicm );
256*c7ef0cfcSnicm
257*c7ef0cfcSnicm tty_settings->c_oflag &= ~((unsigned) (0
258*c7ef0cfcSnicm #ifdef OLCUC
259*c7ef0cfcSnicm | OLCUC
260*c7ef0cfcSnicm #endif
261*c7ef0cfcSnicm #ifdef OCRNL
262*c7ef0cfcSnicm | OCRNL
263*c7ef0cfcSnicm #endif
264*c7ef0cfcSnicm #ifdef ONOCR
265*c7ef0cfcSnicm | ONOCR
266*c7ef0cfcSnicm #endif
267*c7ef0cfcSnicm #ifdef ONLRET
268*c7ef0cfcSnicm | ONLRET
269*c7ef0cfcSnicm #endif
270*c7ef0cfcSnicm #ifdef OFILL
271*c7ef0cfcSnicm | OFILL
272*c7ef0cfcSnicm #endif
273*c7ef0cfcSnicm #ifdef OFDEL
274*c7ef0cfcSnicm | OFDEL
275*c7ef0cfcSnicm #endif
276*c7ef0cfcSnicm #ifdef NLDLY
277*c7ef0cfcSnicm | NLDLY
278*c7ef0cfcSnicm #endif
279*c7ef0cfcSnicm #ifdef CRDLY
280*c7ef0cfcSnicm | CRDLY
281*c7ef0cfcSnicm #endif
282*c7ef0cfcSnicm #ifdef TABDLY
283*c7ef0cfcSnicm | TABDLY
284*c7ef0cfcSnicm #endif
285*c7ef0cfcSnicm #ifdef BSDLY
286*c7ef0cfcSnicm | BSDLY
287*c7ef0cfcSnicm #endif
288*c7ef0cfcSnicm #ifdef VTDLY
289*c7ef0cfcSnicm | VTDLY
290*c7ef0cfcSnicm #endif
291*c7ef0cfcSnicm #ifdef FFDLY
292*c7ef0cfcSnicm | FFDLY
293*c7ef0cfcSnicm #endif
294*c7ef0cfcSnicm ));
295*c7ef0cfcSnicm
296*c7ef0cfcSnicm tty_settings->c_oflag |= (OPOST
297*c7ef0cfcSnicm #ifdef ONLCR
298*c7ef0cfcSnicm | ONLCR
299*c7ef0cfcSnicm #endif
300*c7ef0cfcSnicm );
301*c7ef0cfcSnicm
302*c7ef0cfcSnicm tty_settings->c_cflag &= ~((unsigned) (CSIZE
303*c7ef0cfcSnicm | CSTOPB
304*c7ef0cfcSnicm | PARENB
305*c7ef0cfcSnicm | PARODD
306*c7ef0cfcSnicm | CLOCAL));
307*c7ef0cfcSnicm tty_settings->c_cflag |= (CS8 | CREAD);
308*c7ef0cfcSnicm tty_settings->c_lflag &= ~((unsigned) (ECHONL
309*c7ef0cfcSnicm | NOFLSH
310*c7ef0cfcSnicm #ifdef TOSTOP
311*c7ef0cfcSnicm | TOSTOP
312*c7ef0cfcSnicm #endif
313*c7ef0cfcSnicm #ifdef ECHOPTR
314*c7ef0cfcSnicm | ECHOPRT
315*c7ef0cfcSnicm #endif
316*c7ef0cfcSnicm #ifdef XCASE
317*c7ef0cfcSnicm | XCASE
318*c7ef0cfcSnicm #endif
319*c7ef0cfcSnicm ));
320*c7ef0cfcSnicm
321*c7ef0cfcSnicm tty_settings->c_lflag |= (ISIG
322*c7ef0cfcSnicm | ICANON
323*c7ef0cfcSnicm | ECHO
324*c7ef0cfcSnicm | ECHOE
325*c7ef0cfcSnicm | ECHOK
326*c7ef0cfcSnicm #ifdef ECHOCTL
327*c7ef0cfcSnicm | ECHOCTL
328*c7ef0cfcSnicm #endif
329*c7ef0cfcSnicm #ifdef ECHOKE
330*c7ef0cfcSnicm | ECHOKE
331*c7ef0cfcSnicm #endif
332*c7ef0cfcSnicm );
333*c7ef0cfcSnicm #endif
334*c7ef0cfcSnicm
335*c7ef0cfcSnicm if (!noset) {
336*c7ef0cfcSnicm SET_TTY(fd, tty_settings);
337*c7ef0cfcSnicm }
338*c7ef0cfcSnicm }
339*c7ef0cfcSnicm
340*c7ef0cfcSnicm /*
341*c7ef0cfcSnicm * Returns a "good" value for the erase character. This is loosely based on
342*c7ef0cfcSnicm * the BSD4.4 logic.
343*c7ef0cfcSnicm */
344*c7ef0cfcSnicm static int
default_erase(void)345*c7ef0cfcSnicm default_erase(void)
346*c7ef0cfcSnicm {
347*c7ef0cfcSnicm int result;
348*c7ef0cfcSnicm
349*c7ef0cfcSnicm if (over_strike
350*c7ef0cfcSnicm && VALID_STRING(key_backspace)
351*c7ef0cfcSnicm && strlen(key_backspace) == 1) {
352*c7ef0cfcSnicm result = key_backspace[0];
353*c7ef0cfcSnicm } else {
354*c7ef0cfcSnicm result = CERASE;
355*c7ef0cfcSnicm }
356*c7ef0cfcSnicm
357*c7ef0cfcSnicm return result;
358*c7ef0cfcSnicm }
359*c7ef0cfcSnicm
360*c7ef0cfcSnicm /*
361*c7ef0cfcSnicm * Update the values of the erase, interrupt, and kill characters in the TTY
362*c7ef0cfcSnicm * parameter.
363*c7ef0cfcSnicm *
364*c7ef0cfcSnicm * SVr4 tset (e.g., Solaris 2.5) only modifies the intr, quit or erase
365*c7ef0cfcSnicm * characters if they're unset, or if we specify them as options. This differs
366*c7ef0cfcSnicm * from BSD 4.4 tset, which always sets erase.
367*c7ef0cfcSnicm */
368*c7ef0cfcSnicm void
set_control_chars(TTY * tty_settings,int my_erase,int my_intr,int my_kill)369*c7ef0cfcSnicm set_control_chars(TTY * tty_settings, int my_erase, int my_intr, int my_kill)
370*c7ef0cfcSnicm {
371*c7ef0cfcSnicm #if defined(EXP_WIN32_DRIVER)
372*c7ef0cfcSnicm /* noop */
373*c7ef0cfcSnicm (void) tty_settings;
374*c7ef0cfcSnicm (void) my_erase;
375*c7ef0cfcSnicm (void) my_intr;
376*c7ef0cfcSnicm (void) my_kill;
377*c7ef0cfcSnicm #else
378*c7ef0cfcSnicm if (DISABLED(tty_settings->c_cc[VERASE]) || my_erase >= 0) {
379*c7ef0cfcSnicm tty_settings->c_cc[VERASE] = UChar((my_erase >= 0)
380*c7ef0cfcSnicm ? my_erase
381*c7ef0cfcSnicm : default_erase());
382*c7ef0cfcSnicm }
383*c7ef0cfcSnicm
384*c7ef0cfcSnicm if (DISABLED(tty_settings->c_cc[VINTR]) || my_intr >= 0) {
385*c7ef0cfcSnicm tty_settings->c_cc[VINTR] = UChar((my_intr >= 0)
386*c7ef0cfcSnicm ? my_intr
387*c7ef0cfcSnicm : CINTR);
388*c7ef0cfcSnicm }
389*c7ef0cfcSnicm
390*c7ef0cfcSnicm if (DISABLED(tty_settings->c_cc[VKILL]) || my_kill >= 0) {
391*c7ef0cfcSnicm tty_settings->c_cc[VKILL] = UChar((my_kill >= 0)
392*c7ef0cfcSnicm ? my_kill
393*c7ef0cfcSnicm : CKILL);
394*c7ef0cfcSnicm }
395*c7ef0cfcSnicm #endif
396*c7ef0cfcSnicm }
397*c7ef0cfcSnicm
398*c7ef0cfcSnicm /*
399*c7ef0cfcSnicm * Set up various conversions in the TTY parameter, including parity, tabs,
400*c7ef0cfcSnicm * returns, echo, and case, according to the termcap entry.
401*c7ef0cfcSnicm */
402*c7ef0cfcSnicm void
set_conversions(TTY * tty_settings)403*c7ef0cfcSnicm set_conversions(TTY * tty_settings)
404*c7ef0cfcSnicm {
405*c7ef0cfcSnicm #if defined(EXP_WIN32_DRIVER)
406*c7ef0cfcSnicm /* FIXME */
407*c7ef0cfcSnicm #else
408*c7ef0cfcSnicm #ifdef ONLCR
409*c7ef0cfcSnicm tty_settings->c_oflag |= ONLCR;
410*c7ef0cfcSnicm #endif
411*c7ef0cfcSnicm tty_settings->c_iflag |= ICRNL;
412*c7ef0cfcSnicm tty_settings->c_lflag |= ECHO;
413*c7ef0cfcSnicm #ifdef OXTABS
414*c7ef0cfcSnicm tty_settings->c_oflag |= OXTABS;
415*c7ef0cfcSnicm #endif /* OXTABS */
416*c7ef0cfcSnicm
417*c7ef0cfcSnicm /* test used to be tgetflag("NL") */
418*c7ef0cfcSnicm if (VALID_STRING(newline) && newline[0] == '\n' && !newline[1]) {
419*c7ef0cfcSnicm /* Newline, not linefeed. */
420*c7ef0cfcSnicm #ifdef ONLCR
421*c7ef0cfcSnicm tty_settings->c_oflag &= ~((unsigned) ONLCR);
422*c7ef0cfcSnicm #endif
423*c7ef0cfcSnicm tty_settings->c_iflag &= ~((unsigned) ICRNL);
424*c7ef0cfcSnicm }
425*c7ef0cfcSnicm #ifdef OXTABS
426*c7ef0cfcSnicm /* test used to be tgetflag("pt") */
427*c7ef0cfcSnicm if (VALID_STRING(set_tab) && VALID_STRING(clear_all_tabs))
428*c7ef0cfcSnicm tty_settings->c_oflag &= ~OXTABS;
429*c7ef0cfcSnicm #endif /* OXTABS */
430*c7ef0cfcSnicm tty_settings->c_lflag |= (ECHOE | ECHOK);
431*c7ef0cfcSnicm #endif
432*c7ef0cfcSnicm }
433*c7ef0cfcSnicm
434*c7ef0cfcSnicm static bool
sent_string(const char * s)435*c7ef0cfcSnicm sent_string(const char *s)
436*c7ef0cfcSnicm {
437*c7ef0cfcSnicm bool sent = FALSE;
438*c7ef0cfcSnicm if (VALID_STRING(s)) {
439*c7ef0cfcSnicm tputs(s, 0, out_char);
440*c7ef0cfcSnicm sent = TRUE;
441*c7ef0cfcSnicm }
442*c7ef0cfcSnicm return sent;
443*c7ef0cfcSnicm }
444*c7ef0cfcSnicm
445*c7ef0cfcSnicm static bool
to_left_margin(void)446*c7ef0cfcSnicm to_left_margin(void)
447*c7ef0cfcSnicm {
448*c7ef0cfcSnicm if (VALID_STRING(carriage_return)) {
449*c7ef0cfcSnicm sent_string(carriage_return);
450*c7ef0cfcSnicm } else {
451*c7ef0cfcSnicm out_char('\r');
452*c7ef0cfcSnicm }
453*c7ef0cfcSnicm return TRUE;
454*c7ef0cfcSnicm }
455*c7ef0cfcSnicm
456*c7ef0cfcSnicm /*
457*c7ef0cfcSnicm * Set the hardware tabs on the terminal, using the 'ct' (clear all tabs),
458*c7ef0cfcSnicm * 'st' (set one tab) and 'ch' (horizontal cursor addressing) capabilities.
459*c7ef0cfcSnicm * This is done before 'if' and 'is', so they can recover in case of error.
460*c7ef0cfcSnicm *
461*c7ef0cfcSnicm * Return TRUE if we set any tab stops, FALSE if not.
462*c7ef0cfcSnicm */
463*c7ef0cfcSnicm static bool
reset_tabstops(int wide)464*c7ef0cfcSnicm reset_tabstops(int wide)
465*c7ef0cfcSnicm {
466*c7ef0cfcSnicm if ((init_tabs != 8)
467*c7ef0cfcSnicm && VALID_NUMERIC(init_tabs)
468*c7ef0cfcSnicm && VALID_STRING(set_tab)
469*c7ef0cfcSnicm && VALID_STRING(clear_all_tabs)) {
470*c7ef0cfcSnicm int c;
471*c7ef0cfcSnicm
472*c7ef0cfcSnicm to_left_margin();
473*c7ef0cfcSnicm tputs(clear_all_tabs, 0, out_char);
474*c7ef0cfcSnicm if (init_tabs > 1) {
475*c7ef0cfcSnicm if (init_tabs > wide)
476*c7ef0cfcSnicm init_tabs = (short) wide;
477*c7ef0cfcSnicm for (c = init_tabs; c < wide; c += init_tabs) {
478*c7ef0cfcSnicm fprintf(my_file, "%*s", init_tabs, " ");
479*c7ef0cfcSnicm tputs(set_tab, 0, out_char);
480*c7ef0cfcSnicm }
481*c7ef0cfcSnicm to_left_margin();
482*c7ef0cfcSnicm }
483*c7ef0cfcSnicm return (TRUE);
484*c7ef0cfcSnicm }
485*c7ef0cfcSnicm return (FALSE);
486*c7ef0cfcSnicm }
487*c7ef0cfcSnicm
488*c7ef0cfcSnicm /* Output startup string. */
489*c7ef0cfcSnicm bool
send_init_strings(int fd GCC_UNUSED,TTY * old_settings)490*c7ef0cfcSnicm send_init_strings(int fd GCC_UNUSED, TTY * old_settings)
491*c7ef0cfcSnicm {
492*c7ef0cfcSnicm int i;
493*c7ef0cfcSnicm bool need_flush = FALSE;
494*c7ef0cfcSnicm
495*c7ef0cfcSnicm (void) old_settings;
496*c7ef0cfcSnicm #ifdef TAB3
497*c7ef0cfcSnicm if (old_settings != 0 &&
498*c7ef0cfcSnicm old_settings->c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) {
499*c7ef0cfcSnicm old_settings->c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET);
500*c7ef0cfcSnicm SET_TTY(fd, old_settings);
501*c7ef0cfcSnicm }
502*c7ef0cfcSnicm #endif
503*c7ef0cfcSnicm if (use_reset || use_init) {
504*c7ef0cfcSnicm if (VALID_STRING(init_prog)) {
505*c7ef0cfcSnicm IGNORE_RC(system(init_prog));
506*c7ef0cfcSnicm }
507*c7ef0cfcSnicm
508*c7ef0cfcSnicm need_flush |= sent_string((use_reset && (reset_1string != 0))
509*c7ef0cfcSnicm ? reset_1string
510*c7ef0cfcSnicm : init_1string);
511*c7ef0cfcSnicm
512*c7ef0cfcSnicm need_flush |= sent_string((use_reset && (reset_2string != 0))
513*c7ef0cfcSnicm ? reset_2string
514*c7ef0cfcSnicm : init_2string);
515*c7ef0cfcSnicm
516*c7ef0cfcSnicm if (VALID_STRING(clear_margins)) {
517*c7ef0cfcSnicm need_flush |= sent_string(clear_margins);
518*c7ef0cfcSnicm } else
519*c7ef0cfcSnicm #if defined(set_lr_margin)
520*c7ef0cfcSnicm if (VALID_STRING(set_lr_margin)) {
521*c7ef0cfcSnicm need_flush |= sent_string(TIPARM_2(set_lr_margin, 0, columns - 1));
522*c7ef0cfcSnicm } else
523*c7ef0cfcSnicm #endif
524*c7ef0cfcSnicm #if defined(set_left_margin_parm) && defined(set_right_margin_parm)
525*c7ef0cfcSnicm if (VALID_STRING(set_left_margin_parm)
526*c7ef0cfcSnicm && VALID_STRING(set_right_margin_parm)) {
527*c7ef0cfcSnicm need_flush |= sent_string(TIPARM_1(set_left_margin_parm, 0));
528*c7ef0cfcSnicm need_flush |= sent_string(TIPARM_1(set_right_margin_parm,
529*c7ef0cfcSnicm columns - 1));
530*c7ef0cfcSnicm } else
531*c7ef0cfcSnicm #endif
532*c7ef0cfcSnicm if (VALID_STRING(set_left_margin)
533*c7ef0cfcSnicm && VALID_STRING(set_right_margin)) {
534*c7ef0cfcSnicm need_flush |= to_left_margin();
535*c7ef0cfcSnicm need_flush |= sent_string(set_left_margin);
536*c7ef0cfcSnicm if (VALID_STRING(parm_right_cursor)) {
537*c7ef0cfcSnicm need_flush |= sent_string(TIPARM_1(parm_right_cursor,
538*c7ef0cfcSnicm columns - 1));
539*c7ef0cfcSnicm } else {
540*c7ef0cfcSnicm for (i = 0; i < columns - 1; i++) {
541*c7ef0cfcSnicm out_char(' ');
542*c7ef0cfcSnicm need_flush = TRUE;
543*c7ef0cfcSnicm }
544*c7ef0cfcSnicm }
545*c7ef0cfcSnicm need_flush |= sent_string(set_right_margin);
546*c7ef0cfcSnicm need_flush |= to_left_margin();
547*c7ef0cfcSnicm }
548*c7ef0cfcSnicm
549*c7ef0cfcSnicm need_flush |= reset_tabstops(columns);
550*c7ef0cfcSnicm
551*c7ef0cfcSnicm need_flush |= cat_file((use_reset && reset_file) ? reset_file : init_file);
552*c7ef0cfcSnicm
553*c7ef0cfcSnicm need_flush |= sent_string((use_reset && (reset_3string != 0))
554*c7ef0cfcSnicm ? reset_3string
555*c7ef0cfcSnicm : init_3string);
556*c7ef0cfcSnicm }
557*c7ef0cfcSnicm
558*c7ef0cfcSnicm return need_flush;
559*c7ef0cfcSnicm }
560*c7ef0cfcSnicm
561*c7ef0cfcSnicm /*
562*c7ef0cfcSnicm * Tell the user if a control key has been changed from the default value.
563*c7ef0cfcSnicm */
564*c7ef0cfcSnicm static void
show_tty_change(TTY * old_settings,TTY * new_settings,const char * name,int which,unsigned def)565*c7ef0cfcSnicm show_tty_change(TTY * old_settings,
566*c7ef0cfcSnicm TTY * new_settings,
567*c7ef0cfcSnicm const char *name,
568*c7ef0cfcSnicm int which,
569*c7ef0cfcSnicm unsigned def)
570*c7ef0cfcSnicm {
571*c7ef0cfcSnicm unsigned older = 0, newer = 0;
572*c7ef0cfcSnicm char *p;
573*c7ef0cfcSnicm
574*c7ef0cfcSnicm #if defined(EXP_WIN32_DRIVER)
575*c7ef0cfcSnicm /* noop */
576*c7ef0cfcSnicm (void) old_settings;
577*c7ef0cfcSnicm (void) new_settings;
578*c7ef0cfcSnicm (void) name;
579*c7ef0cfcSnicm (void) which;
580*c7ef0cfcSnicm (void) def;
581*c7ef0cfcSnicm #else
582*c7ef0cfcSnicm newer = new_settings->c_cc[which];
583*c7ef0cfcSnicm older = old_settings->c_cc[which];
584*c7ef0cfcSnicm
585*c7ef0cfcSnicm if (older == newer && older == def)
586*c7ef0cfcSnicm return;
587*c7ef0cfcSnicm #endif
588*c7ef0cfcSnicm (void) fprintf(stderr, "%s %s ", name, older == newer ? "is" : "set to");
589*c7ef0cfcSnicm
590*c7ef0cfcSnicm if (DISABLED(newer)) {
591*c7ef0cfcSnicm (void) fprintf(stderr, "undef.\n");
592*c7ef0cfcSnicm /*
593*c7ef0cfcSnicm * Check 'delete' before 'backspace', since the key_backspace value
594*c7ef0cfcSnicm * is ambiguous.
595*c7ef0cfcSnicm */
596*c7ef0cfcSnicm } else if (newer == 0177) {
597*c7ef0cfcSnicm (void) fprintf(stderr, "delete.\n");
598*c7ef0cfcSnicm } else if ((p = key_backspace) != 0
599*c7ef0cfcSnicm && newer == (unsigned char) p[0]
600*c7ef0cfcSnicm && p[1] == '\0') {
601*c7ef0cfcSnicm (void) fprintf(stderr, "backspace.\n");
602*c7ef0cfcSnicm } else if (newer < 040) {
603*c7ef0cfcSnicm newer ^= 0100;
604*c7ef0cfcSnicm (void) fprintf(stderr, "control-%c (^%c).\n", UChar(newer), UChar(newer));
605*c7ef0cfcSnicm } else
606*c7ef0cfcSnicm (void) fprintf(stderr, "%c.\n", UChar(newer));
607*c7ef0cfcSnicm }
608*c7ef0cfcSnicm
609*c7ef0cfcSnicm /**************************************************************************
610*c7ef0cfcSnicm * Miscellaneous.
611*c7ef0cfcSnicm **************************************************************************/
612*c7ef0cfcSnicm
613*c7ef0cfcSnicm void
reset_start(FILE * fp,bool is_reset,bool is_init)614*c7ef0cfcSnicm reset_start(FILE *fp, bool is_reset, bool is_init)
615*c7ef0cfcSnicm {
616*c7ef0cfcSnicm my_file = fp;
617*c7ef0cfcSnicm use_reset = is_reset;
618*c7ef0cfcSnicm use_init = is_init;
619*c7ef0cfcSnicm }
620*c7ef0cfcSnicm
621*c7ef0cfcSnicm void
reset_flush(void)622*c7ef0cfcSnicm reset_flush(void)
623*c7ef0cfcSnicm {
624*c7ef0cfcSnicm if (my_file != 0)
625*c7ef0cfcSnicm fflush(my_file);
626*c7ef0cfcSnicm }
627*c7ef0cfcSnicm
628*c7ef0cfcSnicm void
print_tty_chars(TTY * old_settings,TTY * new_settings)629*c7ef0cfcSnicm print_tty_chars(TTY * old_settings, TTY * new_settings)
630*c7ef0cfcSnicm {
631*c7ef0cfcSnicm #if defined(EXP_WIN32_DRIVER)
632*c7ef0cfcSnicm /* noop */
633*c7ef0cfcSnicm #else
634*c7ef0cfcSnicm show_tty_change(old_settings, new_settings, "Erase", VERASE, CERASE);
635*c7ef0cfcSnicm show_tty_change(old_settings, new_settings, "Kill", VKILL, CKILL);
636*c7ef0cfcSnicm show_tty_change(old_settings, new_settings, "Interrupt", VINTR, CINTR);
637*c7ef0cfcSnicm #endif
638*c7ef0cfcSnicm }
639*c7ef0cfcSnicm
640*c7ef0cfcSnicm #if HAVE_SIZECHANGE
641*c7ef0cfcSnicm /*
642*c7ef0cfcSnicm * Set window size if not set already, but update our copy of the values if the
643*c7ef0cfcSnicm * size was set.
644*c7ef0cfcSnicm */
645*c7ef0cfcSnicm void
set_window_size(int fd,short * high,short * wide)646*c7ef0cfcSnicm set_window_size(int fd, short *high, short *wide)
647*c7ef0cfcSnicm {
648*c7ef0cfcSnicm STRUCT_WINSIZE win;
649*c7ef0cfcSnicm (void) ioctl(fd, IOCTL_GET_WINSIZE, &win);
650*c7ef0cfcSnicm if (WINSIZE_ROWS(win) == 0 &&
651*c7ef0cfcSnicm WINSIZE_COLS(win) == 0) {
652*c7ef0cfcSnicm if (*high > 0 && *wide > 0) {
653*c7ef0cfcSnicm WINSIZE_ROWS(win) = (unsigned short) *high;
654*c7ef0cfcSnicm WINSIZE_COLS(win) = (unsigned short) *wide;
655*c7ef0cfcSnicm (void) ioctl(fd, IOCTL_SET_WINSIZE, &win);
656*c7ef0cfcSnicm }
657*c7ef0cfcSnicm } else if (WINSIZE_ROWS(win) > 0 &&
658*c7ef0cfcSnicm WINSIZE_COLS(win) > 0) {
659*c7ef0cfcSnicm *high = (short) WINSIZE_ROWS(win);
660*c7ef0cfcSnicm *wide = (short) WINSIZE_COLS(win);
661*c7ef0cfcSnicm }
662*c7ef0cfcSnicm }
663*c7ef0cfcSnicm #endif
664