From beaee834aed2d56a37ad3df7cf381378067b1c65 Mon Sep 17 00:00:00 2001 From: Alistair Delva Date: Wed, 24 Feb 2021 11:27:23 -0800 Subject: Import mtools 4.0.26 Bug: 175204891 Bug: 180112530 Change-Id: I8a656b5da155f9857afa4f48c6b40fe72f68c052 --- tty.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 tty.c (limited to 'tty.c') diff --git a/tty.c b/tty.c new file mode 100644 index 0000000..77529f8 --- /dev/null +++ b/tty.c @@ -0,0 +1,225 @@ +/* Copyright 1997,2001,2002,2007-2009 Alain Knaff. + * This file is part of mtools. + * + * Mtools is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Mtools is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mtools. If not, see . + */ + +#include +#include "sysincludes.h" +#include "mtools.h" + +static FILE *tty=NULL; +static int notty=0; +static int ttyfd=-1; +#ifdef USE_RAWTERM +int mtools_raw_tty = 1; +#else +int mtools_raw_tty = 0; +#endif + +#ifdef USE_RAWTERM +# if defined TCSANOW && defined HAVE_TCSETATTR +/* we have tcsetattr & tcgetattr. Good */ +typedef struct termios Terminal; +# define stty(a,b) (void)tcsetattr(a,TCSANOW,b) +# define gtty(a,b) (void)tcgetattr(a,b) +# define USE_TCIFLUSH + +# elif defined TCSETS && defined TCGETS +typedef struct termios Terminal; +# define stty(a,b) (void)ioctl(a,TCSETS,(char *)b) +# define gtty(a,b) (void)ioctl(a,TCGETS,(char *)b) +# define USE_TCIFLUSH + +# elif defined TCSETA && defined TCGETA +typedef struct termio Terminal; +# define stty(a,b) (void)ioctl(a,TCSETA,(char *)b) +# define gtty(a,b) (void)ioctl(a,TCGETA,(char *)b) +# define USE_TCIFLUSH + +# elif defined(HAVE_SGTTY_H) && defined(TIOCSETP) && defined(TIOCGETP) +typedef struct sgttyb Terminal; +# define stty(a,b) (void)ioctl(a,TIOCSETP,(char *)b) +# define gtty(a,b) (void)ioctl(a,TIOCGETP,(char *)b) +# define USE_SGTTY +# define discard_input(a) /**/ + +# else +/* no way to use raw terminal */ +# warning Cannot use raw terminal code (disabled) +# undef USE_RAWTERM +# endif + +#endif + +#ifdef USE_TCIFLUSH +# if defined TCIFLUSH && defined HAVE_TCFLUSH +# define discard_input(a) tcflush(a,TCIFLUSH) +# else +# define discard_input(a) /**/ +# endif +#endif + +#ifdef USE_RAWTERM + +static int tty_mode = -1; /* 1 for raw, 0 for cooked, -1 for initial */ +static int need_tty_reset = 0; +static int handlerIsSet = 0; + +#define restore_tty(a) stty(STDIN,a) + + +#define STDIN ttyfd +#ifdef future +#define FAIL (-1) +#endif +#define DONE 0 +static Terminal in_orig; + +/*--------------- Signal Handler routines -------------*/ + +static void tty_time_out(int dummy UNUSEDP) NORETURN; +static void tty_time_out(int dummy UNUSEDP) +{ + int exit_code; + signal(SIGALRM, SIG_IGN); + if(tty && need_tty_reset) + restore_tty (&in_orig); +#ifdef future + if (fail_on_timeout) + exit_code=SHFAIL; + else { + if (default_choice && mode_defined) { + if (yes_no) { + if ('Y' == default_choice) + exit_code=0; + else + exit_code=1; + } else + exit_code=default_choice-minc+1; + } else + exit_code=DONE; + } +#else + exit_code = DONE; +#endif + exit(exit_code); +} + +static void cleanup_tty(void) +{ + if(tty && need_tty_reset) { + restore_tty (&in_orig); + setup_signal(); + } +} + +static void set_raw_tty(int mode) +{ + Terminal in_raw; + + if(mode != tty_mode && mode != -1) { + if(!handlerIsSet) { + /* Determine existing TTY settings */ + gtty (STDIN, &in_orig); + need_tty_reset = 1; + + /* Restore original TTY settings on exit */ + atexit(cleanup_tty); + handlerIsSet = 1; + } + + + setup_signal(); + signal (SIGALRM, tty_time_out); + + /* Change STDIN settings to raw */ + + gtty (STDIN, &in_raw); + if(mode) { +#ifdef USE_SGTTY + in_raw.sg_flags |= CBREAK; +#else + in_raw.c_lflag &= ~ICANON; + in_raw.c_cc[VMIN]=1; + in_raw.c_cc[VTIME]=0; +#endif + stty (STDIN, &in_raw); + } else { +#ifdef USE_SGTTY + in_raw.sg_flags &= ~CBREAK; +#else + in_raw.c_lflag |= ICANON; +#endif + stty (STDIN, &in_raw); + } + tty_mode = mode; + discard_input(STDIN); + } +} +#endif + +FILE *opentty(int mode) +{ + if(notty) + return NULL; + if (tty == NULL) { + ttyfd = open("/dev/tty", O_RDONLY); + if(ttyfd >= 0) { + tty = fdopen(ttyfd, "r"); + } + } + if (tty == NULL){ + if ( !isatty(0) ){ + notty = 1; + return NULL; + } + ttyfd = 0; + tty = stdin; + } +#ifdef USE_RAWTERM + if(mtools_raw_tty) + set_raw_tty(mode); +#endif + return tty; +} + +int ask_confirmation(const char *format, ...) +{ + char ans[10]; + va_list ap; + + if(!opentty(-1)) + return 0; + + while (1) { + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + fflush(stderr); + fflush(opentty(-1)); + if (mtools_raw_tty) { + ans[0] = fgetc(opentty(1)); + fputs("\n", stderr); + } else { + if(fgets(ans,9, opentty(0)) == NULL) + /* Treat end-of-file as no */ + ans[0] = 'n'; + } + if (ans[0] == 'y' || ans[0] == 'Y') + return 0; + if (ans[0] == 'n' || ans[0] == 'N') + return -1; + } +} -- cgit v1.2.3