Improved detection of bad/invalid signer keys.
[gnupg.git] / common / ttyio.c
blob9882c8e3095613d862b835b629708171a8a86132
1 /* ttyio.c - tty i/O functions
2 * Copyright (C) 1998,1999,2000,2001,2002,2003,
3 * 2004, 2006 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
7 * GnuPG is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * GnuPG is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdarg.h>
26 #include <unistd.h>
27 #ifdef HAVE_TCGETATTR
28 #include <termios.h>
29 #else
30 #ifdef HAVE_TERMIO_H
31 /* simulate termios with termio */
32 #include <termio.h>
33 #define termios termio
34 #define tcsetattr ioctl
35 #define TCSAFLUSH TCSETAF
36 #define tcgetattr(A,B) ioctl(A,TCGETA,B)
37 #define HAVE_TCGETATTR
38 #endif
39 #endif
40 #ifdef _WIN32 /* use the odd Win32 functions */
41 #include <windows.h>
42 #ifdef HAVE_TCGETATTR
43 #error mingw32 and termios
44 #endif
45 #endif
46 #include <errno.h>
47 #include <ctype.h>
49 #include "util.h"
50 #include "ttyio.h"
51 #include "estream-printf.h"
52 #include "common-defs.h"
54 #define CONTROL_D ('D' - 'A' + 1)
56 #ifdef _WIN32 /* use the odd Win32 functions */
57 static struct {
58 HANDLE in, out;
59 } con;
60 #define DEF_INPMODE (ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT \
61 |ENABLE_PROCESSED_INPUT )
62 #define HID_INPMODE (ENABLE_LINE_INPUT|ENABLE_PROCESSED_INPUT )
63 #define DEF_OUTMODE (ENABLE_WRAP_AT_EOL_OUTPUT|ENABLE_PROCESSED_OUTPUT)
65 #else /* yeah, we have a real OS */
66 static FILE *ttyfp = NULL;
67 #endif
69 static int initialized;
70 static int last_prompt_len;
71 static int batchmode;
72 static int no_terminal;
74 #ifdef HAVE_TCGETATTR
75 static struct termios termsave;
76 static int restore_termios;
77 #endif
79 /* Hooks set by gpgrlhelp.c if required. */
80 static void (*my_rl_set_completer) (rl_completion_func_t *);
81 static void (*my_rl_inhibit_completion) (int);
82 static void (*my_rl_cleanup_after_signal) (void);
83 static void (*my_rl_init_stream) (FILE *);
84 static char *(*my_rl_readline) (const char*);
85 static void (*my_rl_add_history) (const char*);
88 /* This is a wrapper around ttyname so that we can use it even when
89 the standard streams are redirected. It figures the name out the
90 first time and returns it in a statically allocated buffer. */
91 const char *
92 tty_get_ttyname (void)
94 static char *name;
96 /* On a GNU system ctermid() always return /dev/tty, so this does
97 not make much sense - however if it is ever changed we do the
98 Right Thing now. */
99 #ifdef HAVE_CTERMID
100 static int got_name;
102 if (!got_name)
104 const char *s;
105 /* Note that despite our checks for these macros the function is
106 not necessarily thread save. We mainly do this for
107 portability reasons, in case L_ctermid is not defined. */
108 # if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(_POSIX_TRHEADS)
109 char buffer[L_ctermid];
110 s = ctermid (buffer);
111 # else
112 s = ctermid (NULL);
113 # endif
114 if (s)
115 name = strdup (s);
116 got_name = 1;
118 #endif /*HAVE_CTERMID*/
119 /* Assume the standard tty on memory error or when tehre is no
120 certmid. */
121 return name? name : "/dev/tty";
126 #ifdef HAVE_TCGETATTR
127 static void
128 cleanup(void)
130 if( restore_termios ) {
131 restore_termios = 0; /* do it prios in case it is interrupted again */
132 if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) )
133 log_error("tcsetattr() failed: %s\n", strerror(errno) );
136 #endif
138 static void
139 init_ttyfp(void)
141 if( initialized )
142 return;
144 #if defined(_WIN32)
146 SECURITY_ATTRIBUTES sa;
148 memset(&sa, 0, sizeof(sa));
149 sa.nLength = sizeof(sa);
150 sa.bInheritHandle = TRUE;
151 con.out = CreateFileA( "CONOUT$", GENERIC_READ|GENERIC_WRITE,
152 FILE_SHARE_READ|FILE_SHARE_WRITE,
153 &sa, OPEN_EXISTING, 0, 0 );
154 if( con.out == INVALID_HANDLE_VALUE )
155 log_fatal("open(CONOUT$) failed: rc=%d", (int)GetLastError() );
156 memset(&sa, 0, sizeof(sa));
157 sa.nLength = sizeof(sa);
158 sa.bInheritHandle = TRUE;
159 con.in = CreateFileA( "CONIN$", GENERIC_READ|GENERIC_WRITE,
160 FILE_SHARE_READ|FILE_SHARE_WRITE,
161 &sa, OPEN_EXISTING, 0, 0 );
162 if( con.in == INVALID_HANDLE_VALUE )
163 log_fatal("open(CONIN$) failed: rc=%d", (int)GetLastError() );
165 SetConsoleMode(con.in, DEF_INPMODE );
166 SetConsoleMode(con.out, DEF_OUTMODE );
168 #elif defined(__EMX__)
169 ttyfp = stdout; /* Fixme: replace by the real functions: see wklib */
170 if (my_rl_init_stream)
171 my_rl_init_stream (ttyfp);
172 #else
173 ttyfp = batchmode? stderr : fopen (tty_get_ttyname (), "r+");
174 if( !ttyfp ) {
175 log_error("cannot open `%s': %s\n", tty_get_ttyname (),
176 strerror(errno) );
177 exit(2);
179 if (my_rl_init_stream)
180 my_rl_init_stream (ttyfp);
181 #endif
184 #ifdef HAVE_TCGETATTR
185 atexit( cleanup );
186 #endif
187 initialized = 1;
192 tty_batchmode( int onoff )
194 int old = batchmode;
195 if( onoff != -1 )
196 batchmode = onoff;
197 return old;
201 tty_no_terminal(int onoff)
203 int old = no_terminal;
204 no_terminal = onoff ? 1 : 0;
205 return old;
208 void
209 tty_printf( const char *fmt, ... )
211 va_list arg_ptr;
213 if (no_terminal)
214 return;
216 if( !initialized )
217 init_ttyfp();
219 va_start( arg_ptr, fmt ) ;
220 #ifdef _WIN32
222 char *buf = NULL;
223 int n;
224 DWORD nwritten;
226 n = vasprintf(&buf, fmt, arg_ptr);
227 if( !buf )
228 log_bug("vasprintf() failed\n");
230 if( !WriteConsoleA( con.out, buf, n, &nwritten, NULL ) )
231 log_fatal("WriteConsole failed: rc=%d", (int)GetLastError() );
232 if( n != nwritten )
233 log_fatal("WriteConsole failed: %d != %d\n", n, (int)nwritten );
234 last_prompt_len += n;
235 xfree (buf);
237 #else
238 last_prompt_len += vfprintf(ttyfp,fmt,arg_ptr) ;
239 fflush(ttyfp);
240 #endif
241 va_end(arg_ptr);
245 /* Same as tty_printf but if FP is not NULL, behave like a regular
246 fprintf. */
247 void
248 tty_fprintf (FILE *fp, const char *fmt, ... )
250 va_list arg_ptr;
252 if (fp)
254 va_start (arg_ptr, fmt) ;
255 vfprintf (fp, fmt, arg_ptr );
256 va_end (arg_ptr);
257 return;
260 if (no_terminal)
261 return;
263 if( !initialized )
264 init_ttyfp();
266 va_start( arg_ptr, fmt ) ;
267 #ifdef _WIN32
269 char *buf = NULL;
270 int n;
271 DWORD nwritten;
273 n = vasprintf(&buf, fmt, arg_ptr);
274 if( !buf )
275 log_bug("vasprintf() failed\n");
277 if( !WriteConsoleA( con.out, buf, n, &nwritten, NULL ) )
278 log_fatal("WriteConsole failed: rc=%d", (int)GetLastError() );
279 if( n != nwritten )
280 log_fatal("WriteConsole failed: %d != %d\n", n, (int)nwritten );
281 last_prompt_len += n;
282 xfree (buf);
284 #else
285 last_prompt_len += vfprintf(ttyfp,fmt,arg_ptr) ;
286 fflush(ttyfp);
287 #endif
288 va_end(arg_ptr);
292 /****************
293 * Print a string, but filter all control characters out.
295 void
296 tty_print_string ( const byte *p, size_t n )
298 if (no_terminal)
299 return;
301 if( !initialized )
302 init_ttyfp();
304 #ifdef _WIN32
305 /* not so effective, change it if you want */
306 for( ; n; n--, p++ )
307 if( iscntrl( *p ) ) {
308 if( *p == '\n' )
309 tty_printf("\\n");
310 else if( !*p )
311 tty_printf("\\0");
312 else
313 tty_printf("\\x%02x", *p);
315 else
316 tty_printf("%c", *p);
317 #else
318 for( ; n; n--, p++ )
319 if( iscntrl( *p ) ) {
320 putc('\\', ttyfp);
321 if( *p == '\n' )
322 putc('n', ttyfp);
323 else if( !*p )
324 putc('0', ttyfp);
325 else
326 fprintf(ttyfp, "x%02x", *p );
328 else
329 putc(*p, ttyfp);
330 #endif
333 void
334 tty_print_utf8_string2( const byte *p, size_t n, size_t max_n )
336 size_t i;
337 char *buf;
339 if (no_terminal)
340 return;
342 /* we can handle plain ascii simpler, so check for it first */
343 for(i=0; i < n; i++ ) {
344 if( p[i] & 0x80 )
345 break;
347 if( i < n ) {
348 buf = utf8_to_native( (const char *)p, n, 0 );
349 if( max_n && (strlen( buf ) > max_n )) {
350 buf[max_n] = 0;
352 /*(utf8 conversion already does the control character quoting)*/
353 tty_printf("%s", buf );
354 xfree( buf );
356 else {
357 if( max_n && (n > max_n) ) {
358 n = max_n;
360 tty_print_string( p, n );
364 void
365 tty_print_utf8_string( const byte *p, size_t n )
367 tty_print_utf8_string2( p, n, 0 );
371 static char *
372 do_get( const char *prompt, int hidden )
374 char *buf;
375 #ifndef __riscos__
376 byte cbuf[1];
377 #endif
378 int c, n, i;
380 if( batchmode ) {
381 log_error("Sorry, we are in batchmode - can't get input\n");
382 exit(2);
385 if (no_terminal) {
386 log_error("Sorry, no terminal at all requested - can't get input\n");
387 exit(2);
390 if( !initialized )
391 init_ttyfp();
393 last_prompt_len = 0;
394 tty_printf( "%s", prompt );
395 buf = xmalloc((n=50));
396 i = 0;
398 #ifdef _WIN32 /* windoze version */
399 if( hidden )
400 SetConsoleMode(con.in, HID_INPMODE );
402 for(;;) {
403 DWORD nread;
405 if( !ReadConsoleA( con.in, cbuf, 1, &nread, NULL ) )
406 log_fatal("ReadConsole failed: rc=%d", (int)GetLastError() );
407 if( !nread )
408 continue;
409 if( *cbuf == '\n' )
410 break;
412 if( !hidden )
413 last_prompt_len++;
414 c = *cbuf;
415 if( c == '\t' )
416 c = ' ';
417 else if( c > 0xa0 )
418 ; /* we don't allow 0xa0, as this is a protected blank which may
419 * confuse the user */
420 else if( iscntrl(c) )
421 continue;
422 if( !(i < n-1) ) {
423 n += 50;
424 buf = xrealloc (buf, n);
426 buf[i++] = c;
429 if( hidden )
430 SetConsoleMode(con.in, DEF_INPMODE );
432 #elif defined(__riscos__)
433 do {
434 c = riscos_getchar();
435 if (c == 0xa || c == 0xd) { /* Return || Enter */
436 c = (int) '\n';
437 } else if (c == 0x8 || c == 0x7f) { /* Backspace || Delete */
438 if (i>0) {
439 i--;
440 if (!hidden) {
441 last_prompt_len--;
442 fputc(8, ttyfp);
443 fputc(32, ttyfp);
444 fputc(8, ttyfp);
445 fflush(ttyfp);
447 } else {
448 fputc(7, ttyfp);
449 fflush(ttyfp);
451 continue;
452 } else if (c == (int) '\t') { /* Tab */
453 c = ' ';
454 } else if (c > 0xa0) {
455 ; /* we don't allow 0xa0, as this is a protected blank which may
456 * confuse the user */
457 } else if (iscntrl(c)) {
458 continue;
460 if(!(i < n-1)) {
461 n += 50;
462 buf = xrealloc (buf, n);
464 buf[i++] = c;
465 if (!hidden) {
466 last_prompt_len++;
467 fputc(c, ttyfp);
468 fflush(ttyfp);
470 } while (c != '\n');
471 i = (i>0) ? i-1 : 0;
472 #else /* unix version */
473 if( hidden ) {
474 #ifdef HAVE_TCGETATTR
475 struct termios term;
477 if( tcgetattr(fileno(ttyfp), &termsave) )
478 log_fatal("tcgetattr() failed: %s\n", strerror(errno) );
479 restore_termios = 1;
480 term = termsave;
481 term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
482 if( tcsetattr( fileno(ttyfp), TCSAFLUSH, &term ) )
483 log_fatal("tcsetattr() failed: %s\n", strerror(errno) );
484 #endif
487 /* fixme: How can we avoid that the \n is echoed w/o disabling
488 * canonical mode - w/o this kill_prompt can't work */
489 while( read(fileno(ttyfp), cbuf, 1) == 1 && *cbuf != '\n' ) {
490 if( !hidden )
491 last_prompt_len++;
492 c = *cbuf;
493 if( c == CONTROL_D )
494 log_info("control d found\n");
495 if( c == '\t' )
496 c = ' ';
497 else if( c > 0xa0 )
498 ; /* we don't allow 0xa0, as this is a protected blank which may
499 * confuse the user */
500 else if( iscntrl(c) )
501 continue;
502 if( !(i < n-1) ) {
503 n += 50;
504 buf = xrealloc (buf, n );
506 buf[i++] = c;
508 if( *cbuf != '\n' ) {
509 buf[0] = CONTROL_D;
510 i = 1;
514 if( hidden ) {
515 #ifdef HAVE_TCGETATTR
516 if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) )
517 log_error("tcsetattr() failed: %s\n", strerror(errno) );
518 restore_termios = 0;
519 #endif
521 #endif /* end unix version */
522 buf[i] = 0;
523 return buf;
527 char *
528 tty_get( const char *prompt )
530 if (!batchmode && !no_terminal && my_rl_readline && my_rl_add_history)
532 char *line;
533 char *buf;
535 if (!initialized)
536 init_ttyfp();
538 last_prompt_len = 0;
540 line = my_rl_readline (prompt?prompt:"");
542 /* We need to copy it to memory controlled by our malloc
543 implementations; further we need to convert an EOF to our
544 convention. */
545 buf = xmalloc(line? strlen(line)+1:2);
546 if (line)
548 strcpy (buf, line);
549 trim_spaces (buf);
550 if (strlen (buf) > 2 )
551 my_rl_add_history (line); /* Note that we test BUF but add LINE. */
552 free (line);
554 else
556 buf[0] = CONTROL_D;
557 buf[1] = 0;
559 return buf;
561 else
562 return do_get ( prompt, 0 );
565 /* Variable argument version of tty_get. The prompt is is actually a
566 format string with arguments. */
567 char *
568 tty_getf (const char *promptfmt, ... )
570 va_list arg_ptr;
571 char *prompt;
572 char *answer;
574 va_start (arg_ptr, promptfmt);
575 if (estream_vasprintf (&prompt, promptfmt, arg_ptr) < 0)
576 log_fatal ("estream_vasprintf failed: %s\n", strerror (errno));
577 va_end (arg_ptr);
578 answer = tty_get (prompt);
579 xfree (prompt);
580 return answer;
585 char *
586 tty_get_hidden( const char *prompt )
588 return do_get( prompt, 1 );
592 void
593 tty_kill_prompt()
595 if ( no_terminal )
596 return;
598 if( !initialized )
599 init_ttyfp();
601 if( batchmode )
602 last_prompt_len = 0;
603 if( !last_prompt_len )
604 return;
605 #ifdef _WIN32
606 tty_printf("\r%*s\r", last_prompt_len, "");
607 #else
609 int i;
610 putc('\r', ttyfp);
611 for(i=0; i < last_prompt_len; i ++ )
612 putc(' ', ttyfp);
613 putc('\r', ttyfp);
614 fflush(ttyfp);
616 #endif
617 last_prompt_len = 0;
622 tty_get_answer_is_yes( const char *prompt )
624 int yes;
625 char *p = tty_get( prompt );
626 tty_kill_prompt();
627 yes = answer_is_yes(p);
628 xfree(p);
629 return yes;
633 /* Called by gnupg_rl_initialize to setup the readline support. */
634 void
635 tty_private_set_rl_hooks (void (*init_stream) (FILE *),
636 void (*set_completer) (rl_completion_func_t*),
637 void (*inhibit_completion) (int),
638 void (*cleanup_after_signal) (void),
639 char *(*readline_fun) (const char*),
640 void (*add_history_fun) (const char*))
642 my_rl_init_stream = init_stream;
643 my_rl_set_completer = set_completer;
644 my_rl_inhibit_completion = inhibit_completion;
645 my_rl_cleanup_after_signal = cleanup_after_signal;
646 my_rl_readline = readline_fun;
647 my_rl_add_history = add_history_fun;
651 void
652 tty_enable_completion (rl_completion_func_t *completer)
654 if (no_terminal || !my_rl_set_completer )
655 return;
657 if (!initialized)
658 init_ttyfp();
660 my_rl_set_completer (completer);
663 void
664 tty_disable_completion (void)
666 if (no_terminal || !my_rl_inhibit_completion)
667 return;
669 if (!initialized)
670 init_ttyfp();
672 my_rl_inhibit_completion (1);
676 void
677 tty_cleanup_after_signal (void)
679 #ifdef HAVE_TCGETATTR
680 cleanup ();
681 #endif
684 void
685 tty_cleanup_rl_after_signal (void)
687 if (my_rl_cleanup_after_signal)
688 my_rl_cleanup_after_signal ();