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) ;
312 /* Print a string, but filter all control characters out. If FP is
313 * not NULL print to that stream instead to the tty. */
315 do_print_string (estream_t fp, const byte *p, size_t n )
317 if (no_terminal && !fp)
320 if (!initialized && !fp)
325 print_utf8_buffer (fp, p, n);
329 #ifdef USE_W32_CONSOLE
330 /* Not so effective, change it if you want */
340 tty_printf ("\\x%02x", *p);
343 tty_printf ("%c", *p);
356 fprintf (ttyfp, "x%02x", *p );
366 tty_print_utf8_string2 (estream_t fp, const byte *p, size_t n, size_t max_n)
371 if (no_terminal && !fp)
374 /* we can handle plain ascii simpler, so check for it first */
375 for(i=0; i < n; i++ ) {
380 buf = utf8_to_native( (const char *)p, n, 0 );
381 if( max_n && (strlen( buf ) > max_n )) {
384 /*(utf8 conversion already does the control character quoting)*/
385 tty_fprintf (fp, "%s", buf);
389 if( max_n && (n > max_n) ) {
392 do_print_string (fp, p, n );
398 tty_print_utf8_string( const byte *p, size_t n )
400 tty_print_utf8_string2 (NULL, p, n, 0);
405 do_get( const char *prompt, int hidden )
414 log_error("Sorry, we are in batchmode - can't get input\n");
419 log_error("Sorry, no terminal at all requested - can't get input\n");
427 tty_printf( "%s", prompt );
428 buf = xmalloc((n=50));
431 #ifdef USE_W32_CONSOLE
433 SetConsoleMode(con.in, HID_INPMODE );
438 if( !ReadConsoleA( con.in, cbuf, 1, &nread, NULL ) )
439 log_fatal("ReadConsole failed: rc=%d", (int)GetLastError() );
451 ; /* we don't allow 0xa0, as this is a protected blank which may
452 * confuse the user */
453 else if( iscntrl(c) )
457 buf = xrealloc (buf, n);
463 SetConsoleMode(con.in, DEF_INPMODE );
465 #elif defined(__riscos__) || defined(HAVE_W32CE_SYSTEM)
467 #ifdef HAVE_W32CE_SYSTEM
468 /* Using getchar is not a correct solution but for now it
469 doesn't matter because we have no real console at all. We
470 should rework this as soon as we have switched this entire
471 module to estream. */
474 c = riscos_getchar();
476 if (c == 0xa || c == 0xd) { /* Return || Enter */
478 } else if (c == 0x8 || c == 0x7f) { /* Backspace || Delete */
493 } else if (c == (int) '\t') { /* Tab */
495 } else if (c > 0xa0) {
496 ; /* we don't allow 0xa0, as this is a protected blank which may
497 * confuse the user */
498 } else if (iscntrl(c)) {
503 buf = xrealloc (buf, n);
513 #else /* Other systems. */
515 #ifdef HAVE_TCGETATTR
518 if( tcgetattr(fileno(ttyfp), &termsave) )
519 log_fatal("tcgetattr() failed: %s\n", strerror(errno) );
522 term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
523 if( tcsetattr( fileno(ttyfp), TCSAFLUSH, &term ) )
524 log_fatal("tcsetattr() failed: %s\n", strerror(errno) );
528 /* fixme: How can we avoid that the \n is echoed w/o disabling
529 * canonical mode - w/o this kill_prompt can't work */
530 while( read(fileno(ttyfp), cbuf, 1) == 1 && *cbuf != '\n' ) {
535 log_info("control d found\n");
539 ; /* we don't allow 0xa0, as this is a protected blank which may
540 * confuse the user */
541 else if( iscntrl(c) )
545 buf = xrealloc (buf, n );
549 if( *cbuf != '\n' ) {
555 #ifdef HAVE_TCGETATTR
556 if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) )
557 log_error("tcsetattr() failed: %s\n", strerror(errno) );
561 #endif /* end unix version */
568 tty_get( const char *prompt )
570 if (!batchmode && !no_terminal && my_rl_readline && my_rl_add_history)
580 line = my_rl_readline (prompt?prompt:"");
582 /* We need to copy it to memory controlled by our malloc
583 implementations; further we need to convert an EOF to our
585 buf = xmalloc(line? strlen(line)+1:2);
590 if (strlen (buf) > 2 )
591 my_rl_add_history (line); /* Note that we test BUF but add LINE. */
602 return do_get ( prompt, 0 );
605 /* Variable argument version of tty_get. The prompt is is actually a
606 format string with arguments. */
608 tty_getf (const char *promptfmt, ... )
614 va_start (arg_ptr, promptfmt);
615 if (gpgrt_vasprintf (&prompt, promptfmt, arg_ptr) < 0)
616 log_fatal ("estream_vasprintf failed: %s\n", strerror (errno));
618 answer = tty_get (prompt);
626 tty_get_hidden( const char *prompt )
628 return do_get( prompt, 1 );
643 if( !last_prompt_len )
645 #ifdef USE_W32_CONSOLE
646 tty_printf("\r%*s\r", last_prompt_len, "");
651 for(i=0; i < last_prompt_len; i ++ )
662 tty_get_answer_is_yes( const char *prompt )
665 char *p = tty_get( prompt );
667 yes = answer_is_yes(p);
673 /* Called by gnupg_rl_initialize to setup the readline support. */
675 tty_private_set_rl_hooks (void (*init_stream) (FILE *),
676 void (*set_completer) (rl_completion_func_t*),
677 void (*inhibit_completion) (int),
678 void (*cleanup_after_signal) (void),
679 char *(*readline_fun) (const char*),
680 void (*add_history_fun) (const char*))
682 my_rl_init_stream = init_stream;
683 my_rl_set_completer = set_completer;
684 my_rl_inhibit_completion = inhibit_completion;
685 my_rl_cleanup_after_signal = cleanup_after_signal;
686 my_rl_readline = readline_fun;
687 my_rl_add_history = add_history_fun;
691 #ifdef HAVE_LIBREADLINE
693 tty_enable_completion (rl_completion_func_t *completer)
695 if (no_terminal || !my_rl_set_completer )
701 my_rl_set_completer (completer);
705 tty_disable_completion (void)
707 if (no_terminal || !my_rl_inhibit_completion)
713 my_rl_inhibit_completion (1);
718 tty_cleanup_after_signal (void)
720 #ifdef HAVE_TCGETATTR
726 tty_cleanup_rl_after_signal (void)
728 if (my_rl_cleanup_after_signal)
729 my_rl_cleanup_after_signal ();