1 /* ttyio.c - tty i/O functions
2 * Copyright (C) 1998,1999,2000,2001,2002,2003,2004,2006,2007,
3 * 2009, 2010 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
7 * This file is free software; you can redistribute it and/or modify
8 * it under the terms of either
10 * - the GNU Lesser General Public License as published by the Free
11 * Software Foundation; either version 3 of the License, or (at
12 * your option) any later version.
16 * - the GNU General Public License as published by the Free
17 * Software Foundation; either version 2 of the License, or (at
18 * your option) any later version.
20 * or both in parallel, as here.
22 * This file is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, see <https://www.gnu.org/licenses/>.
38 #if defined(HAVE_W32_SYSTEM) && !defined(HAVE_W32CE_SYSTEM)
39 # define USE_W32_CONSOLE 1
46 /* simulate termios with termio */
48 #define termios termio
49 #define tcsetattr ioctl
50 #define TCSAFLUSH TCSETAF
51 #define tcgetattr(A,B) ioctl(A,TCGETA,B)
52 #define HAVE_TCGETATTR
55 #ifdef USE_W32_CONSOLE
56 # ifdef HAVE_WINSOCK2_H
57 # include <winsock2.h>
60 # ifdef HAVE_TCGETATTR
61 # error mingw32 and termios
69 #include "common-defs.h"
71 #define CONTROL_D ('D' - 'A' + 1)
74 #ifdef USE_W32_CONSOLE
78 #define DEF_INPMODE (ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT \
79 |ENABLE_PROCESSED_INPUT )
80 #define HID_INPMODE (ENABLE_LINE_INPUT|ENABLE_PROCESSED_INPUT )
81 #define DEF_OUTMODE (ENABLE_WRAP_AT_EOL_OUTPUT|ENABLE_PROCESSED_OUTPUT)
83 #else /* yeah, we have a real OS */
84 static FILE *ttyfp = NULL;
87 static int initialized;
88 static int last_prompt_len;
90 static int no_terminal;
93 static struct termios termsave;
94 static int restore_termios;
97 /* Hooks set by gpgrlhelp.c if required. */
98 static void (*my_rl_set_completer) (rl_completion_func_t *);
99 static void (*my_rl_inhibit_completion) (int);
100 static void (*my_rl_cleanup_after_signal) (void);
101 static void (*my_rl_init_stream) (FILE *);
102 static char *(*my_rl_readline) (const char*);
103 static void (*my_rl_add_history) (const char*);
106 /* This is a wrapper around ttyname so that we can use it even when
107 the standard streams are redirected. It figures the name out the
108 first time and returns it in a statically allocated buffer. */
110 tty_get_ttyname (void)
114 /* On a GNU system ctermid() always return /dev/tty, so this does
115 not make much sense - however if it is ever changed we do the
123 /* Note that despite our checks for these macros the function is
124 not necessarily thread save. We mainly do this for
125 portability reasons, in case L_ctermid is not defined. */
126 # if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(_POSIX_TRHEADS)
127 char buffer[L_ctermid];
128 s = ctermid (buffer);
136 #endif /*HAVE_CTERMID*/
137 /* Assume the standard tty on memory error or when there is no
139 return name? name : "/dev/tty";
144 #ifdef HAVE_TCGETATTR
148 if( restore_termios ) {
149 restore_termios = 0; /* do it prios in case it is interrupted again */
150 if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) )
151 log_error("tcsetattr() failed: %s\n", strerror(errno) );
162 #if defined(USE_W32_CONSOLE)
164 SECURITY_ATTRIBUTES sa;
166 memset(&sa, 0, sizeof(sa));
167 sa.nLength = sizeof(sa);
168 sa.bInheritHandle = TRUE;
169 con.out = CreateFileA( "CONOUT$", GENERIC_READ|GENERIC_WRITE,
170 FILE_SHARE_READ|FILE_SHARE_WRITE,
171 &sa, OPEN_EXISTING, 0, 0 );
172 if( con.out == INVALID_HANDLE_VALUE )
173 log_fatal("open(CONOUT$) failed: rc=%d", (int)GetLastError() );
174 memset(&sa, 0, sizeof(sa));
175 sa.nLength = sizeof(sa);
176 sa.bInheritHandle = TRUE;
177 con.in = CreateFileA( "CONIN$", GENERIC_READ|GENERIC_WRITE,
178 FILE_SHARE_READ|FILE_SHARE_WRITE,
179 &sa, OPEN_EXISTING, 0, 0 );
180 if( con.in == INVALID_HANDLE_VALUE )
181 log_fatal("open(CONIN$) failed: rc=%d", (int)GetLastError() );
183 SetConsoleMode(con.in, DEF_INPMODE );
184 SetConsoleMode(con.out, DEF_OUTMODE );
186 #elif defined(__EMX__)
187 ttyfp = stdout; /* Fixme: replace by the real functions: see wklib */
188 if (my_rl_init_stream)
189 my_rl_init_stream (ttyfp);
190 #elif defined (HAVE_W32CE_SYSTEM)
193 ttyfp = batchmode? stderr : fopen (tty_get_ttyname (), "r+");
195 log_error("cannot open '%s': %s\n", tty_get_ttyname (),
199 if (my_rl_init_stream)
200 my_rl_init_stream (ttyfp);
204 #ifdef HAVE_TCGETATTR
212 tty_batchmode( int onoff )
221 tty_no_terminal(int onoff)
223 int old = no_terminal;
224 no_terminal = onoff ? 1 : 0;
229 tty_printf( const char *fmt, ... )
239 va_start( arg_ptr, fmt ) ;
240 #ifdef USE_W32_CONSOLE
246 n = vasprintf(&buf, fmt, arg_ptr);
248 log_bug("vasprintf() failed\n");
250 if( !WriteConsoleA( con.out, buf, n, &nwritten, NULL ) )
251 log_fatal("WriteConsole failed: rc=%d", (int)GetLastError() );
253 log_fatal("WriteConsole failed: %d != %d\n", n, (int)nwritten );
254 last_prompt_len += n;
258 last_prompt_len += vfprintf(ttyfp,fmt,arg_ptr) ;
265 /* Same as tty_printf but if FP is not NULL, behave like a regular
268 tty_fprintf (estream_t fp, const char *fmt, ... )
274 va_start (arg_ptr, fmt) ;
275 es_vfprintf (fp, fmt, arg_ptr );
286 va_start (arg_ptr, fmt);
287 #ifdef USE_W32_CONSOLE
293 n = vasprintf(&buf, fmt, arg_ptr);
295 log_bug("vasprintf() failed\n");
297 if (!WriteConsoleA( con.out, buf, n, &nwritten, NULL ))
298 log_fatal("WriteConsole failed: rc=%d", (int)GetLastError() );
300 log_fatal("WriteConsole failed: %d != %d\n", n, (int)nwritten );
301 last_prompt_len += n;
305 last_prompt_len += vfprintf(ttyfp,fmt,arg_ptr) ;
313 * Print a string, but filter all control characters out. If FP is
314 * not NULL print to that stream instead to the tty.
317 tty_print_string (estream_t fp, const byte *p, size_t n )
319 if (no_terminal && !fp)
322 if( !initialized & !fp)
325 #ifdef USE_W32_CONSOLE
326 /* not so effective, change it if you want */
334 tty_fprintf (fp, "\\n");
336 tty_fprintf (fp, "\\0");
338 tty_fprintf (fp, "\\x%02x", *p);
341 tty_fprintf (fp, "%c", *p);
355 tty_printf ("\\x%02x", *p);
358 tty_printf ("%c", *p);
374 es_fprintf (fp, "x%02x", *p);
392 fprintf (ttyfp, "x%02x", *p );
402 tty_print_utf8_string2 (estream_t fp, const byte *p, size_t n, size_t max_n)
407 if (no_terminal && !fp)
410 /* we can handle plain ascii simpler, so check for it first */
411 for(i=0; i < n; i++ ) {
416 buf = utf8_to_native( (const char *)p, n, 0 );
417 if( max_n && (strlen( buf ) > max_n )) {
420 /*(utf8 conversion already does the control character quoting)*/
421 tty_fprintf (fp, "%s", buf);
425 if( max_n && (n > max_n) ) {
428 tty_print_string (fp, p, n );
434 tty_print_utf8_string( const byte *p, size_t n )
436 tty_print_utf8_string2 (NULL, p, n, 0);
441 do_get( const char *prompt, int hidden )
450 log_error("Sorry, we are in batchmode - can't get input\n");
455 log_error("Sorry, no terminal at all requested - can't get input\n");
463 tty_printf( "%s", prompt );
464 buf = xmalloc((n=50));
467 #ifdef USE_W32_CONSOLE
469 SetConsoleMode(con.in, HID_INPMODE );
474 if( !ReadConsoleA( con.in, cbuf, 1, &nread, NULL ) )
475 log_fatal("ReadConsole failed: rc=%d", (int)GetLastError() );
487 ; /* we don't allow 0xa0, as this is a protected blank which may
488 * confuse the user */
489 else if( iscntrl(c) )
493 buf = xrealloc (buf, n);
499 SetConsoleMode(con.in, DEF_INPMODE );
501 #elif defined(__riscos__) || defined(HAVE_W32CE_SYSTEM)
503 #ifdef HAVE_W32CE_SYSTEM
504 /* Using getchar is not a correct solution but for now it
505 doesn't matter because we have no real console at all. We
506 should rework this as soon as we have switched this entire
507 module to estream. */
510 c = riscos_getchar();
512 if (c == 0xa || c == 0xd) { /* Return || Enter */
514 } else if (c == 0x8 || c == 0x7f) { /* Backspace || Delete */
529 } else if (c == (int) '\t') { /* Tab */
531 } else if (c > 0xa0) {
532 ; /* we don't allow 0xa0, as this is a protected blank which may
533 * confuse the user */
534 } else if (iscntrl(c)) {
539 buf = xrealloc (buf, n);
549 #else /* Other systems. */
551 #ifdef HAVE_TCGETATTR
554 if( tcgetattr(fileno(ttyfp), &termsave) )
555 log_fatal("tcgetattr() failed: %s\n", strerror(errno) );
558 term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
559 if( tcsetattr( fileno(ttyfp), TCSAFLUSH, &term ) )
560 log_fatal("tcsetattr() failed: %s\n", strerror(errno) );
564 /* fixme: How can we avoid that the \n is echoed w/o disabling
565 * canonical mode - w/o this kill_prompt can't work */
566 while( read(fileno(ttyfp), cbuf, 1) == 1 && *cbuf != '\n' ) {
571 log_info("control d found\n");
575 ; /* we don't allow 0xa0, as this is a protected blank which may
576 * confuse the user */
577 else if( iscntrl(c) )
581 buf = xrealloc (buf, n );
585 if( *cbuf != '\n' ) {
591 #ifdef HAVE_TCGETATTR
592 if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) )
593 log_error("tcsetattr() failed: %s\n", strerror(errno) );
597 #endif /* end unix version */
604 tty_get( const char *prompt )
606 if (!batchmode && !no_terminal && my_rl_readline && my_rl_add_history)
616 line = my_rl_readline (prompt?prompt:"");
618 /* We need to copy it to memory controlled by our malloc
619 implementations; further we need to convert an EOF to our
621 buf = xmalloc(line? strlen(line)+1:2);
626 if (strlen (buf) > 2 )
627 my_rl_add_history (line); /* Note that we test BUF but add LINE. */
638 return do_get ( prompt, 0 );
641 /* Variable argument version of tty_get. The prompt is is actually a
642 format string with arguments. */
644 tty_getf (const char *promptfmt, ... )
650 va_start (arg_ptr, promptfmt);
651 if (gpgrt_vasprintf (&prompt, promptfmt, arg_ptr) < 0)
652 log_fatal ("estream_vasprintf failed: %s\n", strerror (errno));
654 answer = tty_get (prompt);
662 tty_get_hidden( const char *prompt )
664 return do_get( prompt, 1 );
679 if( !last_prompt_len )
681 #ifdef USE_W32_CONSOLE
682 tty_printf("\r%*s\r", last_prompt_len, "");
687 for(i=0; i < last_prompt_len; i ++ )
698 tty_get_answer_is_yes( const char *prompt )
701 char *p = tty_get( prompt );
703 yes = answer_is_yes(p);
709 /* Called by gnupg_rl_initialize to setup the readline support. */
711 tty_private_set_rl_hooks (void (*init_stream) (FILE *),
712 void (*set_completer) (rl_completion_func_t*),
713 void (*inhibit_completion) (int),
714 void (*cleanup_after_signal) (void),
715 char *(*readline_fun) (const char*),
716 void (*add_history_fun) (const char*))
718 my_rl_init_stream = init_stream;
719 my_rl_set_completer = set_completer;
720 my_rl_inhibit_completion = inhibit_completion;
721 my_rl_cleanup_after_signal = cleanup_after_signal;
722 my_rl_readline = readline_fun;
723 my_rl_add_history = add_history_fun;
727 #ifdef HAVE_LIBREADLINE
729 tty_enable_completion (rl_completion_func_t *completer)
731 if (no_terminal || !my_rl_set_completer )
737 my_rl_set_completer (completer);
741 tty_disable_completion (void)
743 if (no_terminal || !my_rl_inhibit_completion)
749 my_rl_inhibit_completion (1);
754 tty_cleanup_after_signal (void)
756 #ifdef HAVE_TCGETATTR
762 tty_cleanup_rl_after_signal (void)
764 if (my_rl_cleanup_after_signal)
765 my_rl_cleanup_after_signal ();