1*32bb5217SDaniel Fojt /****************************************************************************
2*32bb5217SDaniel Fojt * Copyright 2020 Thomas E. Dickey *
3*32bb5217SDaniel Fojt * Copyright 2016,2017 Free Software Foundation, Inc. *
4*32bb5217SDaniel Fojt * *
5*32bb5217SDaniel Fojt * Permission is hereby granted, free of charge, to any person obtaining a *
6*32bb5217SDaniel Fojt * copy of this software and associated documentation files (the *
7*32bb5217SDaniel Fojt * "Software"), to deal in the Software without restriction, including *
8*32bb5217SDaniel Fojt * without limitation the rights to use, copy, modify, merge, publish, *
9*32bb5217SDaniel Fojt * distribute, distribute with modifications, sublicense, and/or sell *
10*32bb5217SDaniel Fojt * copies of the Software, and to permit persons to whom the Software is *
11*32bb5217SDaniel Fojt * furnished to do so, subject to the following conditions: *
12*32bb5217SDaniel Fojt * *
13*32bb5217SDaniel Fojt * The above copyright notice and this permission notice shall be included *
14*32bb5217SDaniel Fojt * in all copies or substantial portions of the Software. *
15*32bb5217SDaniel Fojt * *
16*32bb5217SDaniel Fojt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
17*32bb5217SDaniel Fojt * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
18*32bb5217SDaniel Fojt * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
19*32bb5217SDaniel Fojt * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
20*32bb5217SDaniel Fojt * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
21*32bb5217SDaniel Fojt * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
22*32bb5217SDaniel Fojt * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
23*32bb5217SDaniel Fojt * *
24*32bb5217SDaniel Fojt * Except as contained in this notice, the name(s) of the above copyright *
25*32bb5217SDaniel Fojt * holders shall not be used in advertising or otherwise to promote the *
26*32bb5217SDaniel Fojt * sale, use or other dealings in this Software without prior written *
27*32bb5217SDaniel Fojt * authorization. *
28*32bb5217SDaniel Fojt ****************************************************************************/
29*32bb5217SDaniel Fojt
30*32bb5217SDaniel Fojt /****************************************************************************
31*32bb5217SDaniel Fojt * Author: Thomas E. Dickey *
32*32bb5217SDaniel Fojt ****************************************************************************/
33*32bb5217SDaniel Fojt
34*32bb5217SDaniel Fojt #define USE_LIBTINFO
35*32bb5217SDaniel Fojt #include <tty_settings.h>
36*32bb5217SDaniel Fojt
37*32bb5217SDaniel Fojt #include <fcntl.h>
38*32bb5217SDaniel Fojt
39*32bb5217SDaniel Fojt MODULE_ID("$Id: tty_settings.c,v 1.6 2020/02/02 23:34:34 tom Exp $")
40*32bb5217SDaniel Fojt
41*32bb5217SDaniel Fojt static int my_fd;
42*32bb5217SDaniel Fojt static TTY original_settings;
43*32bb5217SDaniel Fojt static bool can_restore = FALSE;
44*32bb5217SDaniel Fojt
45*32bb5217SDaniel Fojt static void
failed(const char * msg)46*32bb5217SDaniel Fojt failed(const char *msg)
47*32bb5217SDaniel Fojt {
48*32bb5217SDaniel Fojt int code = errno;
49*32bb5217SDaniel Fojt
50*32bb5217SDaniel Fojt (void) fprintf(stderr, "%s: %s: %s\n", _nc_progname, msg, strerror(code));
51*32bb5217SDaniel Fojt restore_tty_settings();
52*32bb5217SDaniel Fojt (void) fprintf(stderr, "\n");
53*32bb5217SDaniel Fojt ExitProgram(ErrSystem(code));
54*32bb5217SDaniel Fojt /* NOTREACHED */
55*32bb5217SDaniel Fojt }
56*32bb5217SDaniel Fojt
57*32bb5217SDaniel Fojt static bool
get_tty_settings(int fd,TTY * tty_settings)58*32bb5217SDaniel Fojt get_tty_settings(int fd, TTY * tty_settings)
59*32bb5217SDaniel Fojt {
60*32bb5217SDaniel Fojt bool success = TRUE;
61*32bb5217SDaniel Fojt my_fd = fd;
62*32bb5217SDaniel Fojt if (fd < 0 || GET_TTY(my_fd, tty_settings) < 0) {
63*32bb5217SDaniel Fojt success = FALSE;
64*32bb5217SDaniel Fojt }
65*32bb5217SDaniel Fojt return success;
66*32bb5217SDaniel Fojt }
67*32bb5217SDaniel Fojt
68*32bb5217SDaniel Fojt /*
69*32bb5217SDaniel Fojt * Open a file descriptor on the current terminal, to obtain its settings.
70*32bb5217SDaniel Fojt * stderr is less likely to be redirected than stdout; try that first.
71*32bb5217SDaniel Fojt */
72*32bb5217SDaniel Fojt int
save_tty_settings(TTY * tty_settings,bool need_tty)73*32bb5217SDaniel Fojt save_tty_settings(TTY * tty_settings, bool need_tty)
74*32bb5217SDaniel Fojt {
75*32bb5217SDaniel Fojt if (!get_tty_settings(STDERR_FILENO, tty_settings) &&
76*32bb5217SDaniel Fojt !get_tty_settings(STDOUT_FILENO, tty_settings) &&
77*32bb5217SDaniel Fojt !get_tty_settings(STDIN_FILENO, tty_settings) &&
78*32bb5217SDaniel Fojt !get_tty_settings(open("/dev/tty", O_RDWR), tty_settings)) {
79*32bb5217SDaniel Fojt if (need_tty) {
80*32bb5217SDaniel Fojt failed("terminal attributes");
81*32bb5217SDaniel Fojt } else {
82*32bb5217SDaniel Fojt my_fd = fileno(stdout);
83*32bb5217SDaniel Fojt }
84*32bb5217SDaniel Fojt } else {
85*32bb5217SDaniel Fojt can_restore = TRUE;
86*32bb5217SDaniel Fojt original_settings = *tty_settings;
87*32bb5217SDaniel Fojt }
88*32bb5217SDaniel Fojt return my_fd;
89*32bb5217SDaniel Fojt }
90*32bb5217SDaniel Fojt
91*32bb5217SDaniel Fojt void
restore_tty_settings(void)92*32bb5217SDaniel Fojt restore_tty_settings(void)
93*32bb5217SDaniel Fojt {
94*32bb5217SDaniel Fojt if (can_restore)
95*32bb5217SDaniel Fojt SET_TTY(my_fd, &original_settings);
96*32bb5217SDaniel Fojt }
97*32bb5217SDaniel Fojt
98*32bb5217SDaniel Fojt /* Set the modes if they've changed. */
99*32bb5217SDaniel Fojt void
update_tty_settings(TTY * old_settings,TTY * new_settings)100*32bb5217SDaniel Fojt update_tty_settings(TTY * old_settings, TTY * new_settings)
101*32bb5217SDaniel Fojt {
102*32bb5217SDaniel Fojt if (memcmp(new_settings, old_settings, sizeof(TTY))) {
103*32bb5217SDaniel Fojt SET_TTY(my_fd, new_settings);
104*32bb5217SDaniel Fojt }
105*32bb5217SDaniel Fojt }
106