Imported Upstream version 2.0.26
[platform/upstream/gpg2.git] / common / ttyio.c
1 /* ttyio.c -  tty i/O functions
2  * Copyright (C) 1998,1999,2000,2001,2002,2003,2004,2006,2007,
3  *               2009 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
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.
11  *
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.
16  *
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/>.
19  */
20
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 # ifdef HAVE_WINSOCK2_H
42 #  include <winsock2.h>
43 # endif
44 # include <windows.h>
45 # ifdef HAVE_TCGETATTR
46 #  error mingw32 and termios
47 # endif
48 #endif
49 #include <errno.h>
50 #include <ctype.h>
51
52 #include "util.h"
53 #include "ttyio.h"
54 #include "estream-printf.h"
55 #include "common-defs.h"
56
57 #define CONTROL_D ('D' - 'A' + 1)
58
59 #ifdef _WIN32 /* use the odd Win32 functions */
60 static struct {
61     HANDLE in, out;
62 } con;
63 #define DEF_INPMODE  (ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT    \
64                                         |ENABLE_PROCESSED_INPUT )
65 #define HID_INPMODE  (ENABLE_LINE_INPUT|ENABLE_PROCESSED_INPUT )
66 #define DEF_OUTMODE  (ENABLE_WRAP_AT_EOL_OUTPUT|ENABLE_PROCESSED_OUTPUT)
67
68 #else /* yeah, we have a real OS */
69 static FILE *ttyfp = NULL;
70 #endif
71
72 static int initialized;
73 static int last_prompt_len;
74 static int batchmode;
75 static int no_terminal;
76
77 #ifdef HAVE_TCGETATTR
78     static struct termios termsave;
79     static int restore_termios;
80 #endif
81
82 /* Hooks set by gpgrlhelp.c if required. */
83 static void (*my_rl_set_completer) (rl_completion_func_t *);
84 static void (*my_rl_inhibit_completion) (int);
85 static void (*my_rl_cleanup_after_signal) (void);
86 static void (*my_rl_init_stream) (FILE *);
87 static char *(*my_rl_readline) (const char*);
88 static void (*my_rl_add_history) (const char*);
89
90
91 /* This is a wrapper around ttyname so that we can use it even when
92    the standard streams are redirected.  It figures the name out the
93    first time and returns it in a statically allocated buffer. */
94 const char *
95 tty_get_ttyname (void)
96 {
97   static char *name;
98
99   /* On a GNU system ctermid() always return /dev/tty, so this does
100      not make much sense - however if it is ever changed we do the
101      Right Thing now. */
102 #ifdef HAVE_CTERMID
103   static int got_name;
104
105   if (!got_name)
106     {
107       const char *s;
108       /* Note that despite our checks for these macros the function is
109          not necessarily thread save.  We mainly do this for
110          portability reasons, in case L_ctermid is not defined. */
111 # if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(_POSIX_TRHEADS)
112       char buffer[L_ctermid];
113       s = ctermid (buffer);
114 # else
115       s = ctermid (NULL);
116 # endif
117       if (s)
118         name = strdup (s);
119       got_name = 1;
120     }
121 #endif /*HAVE_CTERMID*/
122   /* Assume the standard tty on memory error or when tehre is no
123      certmid. */
124   return name? name : "/dev/tty";
125 }
126
127
128
129 #ifdef HAVE_TCGETATTR
130 static void
131 cleanup(void)
132 {
133     if( restore_termios ) {
134         restore_termios = 0; /* do it prios in case it is interrupted again */
135         if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) )
136             log_error("tcsetattr() failed: %s\n", strerror(errno) );
137     }
138 }
139 #endif
140
141 static void
142 init_ttyfp(void)
143 {
144     if( initialized )
145         return;
146
147 #if defined(_WIN32)
148     {
149         SECURITY_ATTRIBUTES sa;
150
151         memset(&sa, 0, sizeof(sa));
152         sa.nLength = sizeof(sa);
153         sa.bInheritHandle = TRUE;
154         con.out = CreateFileA( "CONOUT$", GENERIC_READ|GENERIC_WRITE,
155                                FILE_SHARE_READ|FILE_SHARE_WRITE,
156                                &sa, OPEN_EXISTING, 0, 0 );
157         if( con.out == INVALID_HANDLE_VALUE )
158             log_fatal("open(CONOUT$) failed: rc=%d", (int)GetLastError() );
159         memset(&sa, 0, sizeof(sa));
160         sa.nLength = sizeof(sa);
161         sa.bInheritHandle = TRUE;
162         con.in = CreateFileA( "CONIN$", GENERIC_READ|GENERIC_WRITE,
163                                FILE_SHARE_READ|FILE_SHARE_WRITE,
164                                &sa, OPEN_EXISTING, 0, 0 );
165         if( con.in == INVALID_HANDLE_VALUE )
166             log_fatal("open(CONIN$) failed: rc=%d", (int)GetLastError() );
167     }
168     SetConsoleMode(con.in, DEF_INPMODE );
169     SetConsoleMode(con.out, DEF_OUTMODE );
170
171 #elif defined(__EMX__)
172     ttyfp = stdout; /* Fixme: replace by the real functions: see wklib */
173     if (my_rl_init_stream)
174       my_rl_init_stream (ttyfp);
175 #else
176     ttyfp = batchmode? stderr : fopen (tty_get_ttyname (), "r+");
177     if( !ttyfp ) {
178         log_error("cannot open `%s': %s\n", tty_get_ttyname (),
179                   strerror(errno) );
180         exit(2);
181     }
182     if (my_rl_init_stream)
183       my_rl_init_stream (ttyfp);
184 #endif
185
186
187 #ifdef HAVE_TCGETATTR
188     atexit( cleanup );
189 #endif
190     initialized = 1;
191 }
192
193
194 int
195 tty_batchmode( int onoff )
196 {
197     int old = batchmode;
198     if( onoff != -1 )
199         batchmode = onoff;
200     return old;
201 }
202
203 int
204 tty_no_terminal(int onoff)
205 {
206     int old = no_terminal;
207     no_terminal = onoff ? 1 : 0;
208     return old;
209 }
210
211 void
212 tty_printf( const char *fmt, ... )
213 {
214     va_list arg_ptr;
215
216     if (no_terminal)
217         return;
218
219     if( !initialized )
220         init_ttyfp();
221
222     va_start( arg_ptr, fmt ) ;
223 #ifdef _WIN32
224     {
225         char *buf = NULL;
226         int n;
227         DWORD nwritten;
228
229         n = vasprintf(&buf, fmt, arg_ptr);
230         if( !buf )
231             log_bug("vasprintf() failed\n");
232
233         if( !WriteConsoleA( con.out, buf, n, &nwritten, NULL ) )
234             log_fatal("WriteConsole failed: rc=%d", (int)GetLastError() );
235         if( n != nwritten )
236             log_fatal("WriteConsole failed: %d != %d\n", n, (int)nwritten );
237         last_prompt_len += n;
238         xfree (buf);
239     }
240 #else
241     last_prompt_len += vfprintf(ttyfp,fmt,arg_ptr) ;
242     fflush(ttyfp);
243 #endif
244     va_end(arg_ptr);
245 }
246
247
248 /* Same as tty_printf but if FP is not NULL, behave like a regular
249    fprintf. */
250 void
251 tty_fprintf (FILE *fp, const char *fmt, ... )
252 {
253   va_list arg_ptr;
254
255   if (fp)
256     {
257       va_start (arg_ptr, fmt) ;
258       vfprintf (fp, fmt, arg_ptr );
259       va_end (arg_ptr);
260       return;
261     }
262
263   if (no_terminal)
264     return;
265
266   if( !initialized )
267     init_ttyfp();
268
269     va_start( arg_ptr, fmt ) ;
270 #ifdef _WIN32
271     {
272         char *buf = NULL;
273         int n;
274         DWORD nwritten;
275
276         n = vasprintf(&buf, fmt, arg_ptr);
277         if( !buf )
278             log_bug("vasprintf() failed\n");
279
280         if( !WriteConsoleA( con.out, buf, n, &nwritten, NULL ) )
281             log_fatal("WriteConsole failed: rc=%d", (int)GetLastError() );
282         if( n != nwritten )
283             log_fatal("WriteConsole failed: %d != %d\n", n, (int)nwritten );
284         last_prompt_len += n;
285         xfree (buf);
286     }
287 #else
288     last_prompt_len += vfprintf(ttyfp,fmt,arg_ptr) ;
289     fflush(ttyfp);
290 #endif
291     va_end(arg_ptr);
292 }
293
294
295 /****************
296  * Print a string, but filter all control characters out.
297  */
298 void
299 tty_print_string ( const byte *p, size_t n )
300 {
301     if (no_terminal)
302         return;
303
304     if( !initialized )
305         init_ttyfp();
306
307 #ifdef _WIN32
308     /* not so effective, change it if you want */
309     for( ; n; n--, p++ )
310         if( iscntrl( *p ) ) {
311             if( *p == '\n' )
312                 tty_printf("\\n");
313             else if( !*p )
314                 tty_printf("\\0");
315             else
316                 tty_printf("\\x%02x", *p);
317         }
318         else
319             tty_printf("%c", *p);
320 #else
321     for( ; n; n--, p++ )
322         if( iscntrl( *p ) ) {
323             putc('\\', ttyfp);
324             if( *p == '\n' )
325                 putc('n', ttyfp);
326             else if( !*p )
327                 putc('0', ttyfp);
328             else
329                 fprintf(ttyfp, "x%02x", *p );
330         }
331         else
332             putc(*p, ttyfp);
333 #endif
334 }
335
336 void
337 tty_print_utf8_string2( const byte *p, size_t n, size_t max_n )
338 {
339     size_t i;
340     char *buf;
341
342     if (no_terminal)
343         return;
344
345     /* we can handle plain ascii simpler, so check for it first */
346     for(i=0; i < n; i++ ) {
347         if( p[i] & 0x80 )
348             break;
349     }
350     if( i < n ) {
351         buf = utf8_to_native( (const char *)p, n, 0 );
352         if( max_n && (strlen( buf ) > max_n )) {
353             buf[max_n] = 0;
354         }
355         /*(utf8 conversion already does the control character quoting)*/
356         tty_printf("%s", buf );
357         xfree( buf );
358     }
359     else {
360         if( max_n && (n > max_n) ) {
361             n = max_n;
362         }
363         tty_print_string( p, n );
364     }
365 }
366
367 void
368 tty_print_utf8_string( const byte *p, size_t n )
369 {
370     tty_print_utf8_string2( p, n, 0 );
371 }
372
373
374 static char *
375 do_get( const char *prompt, int hidden )
376 {
377     char *buf;
378 #ifndef __riscos__
379     byte cbuf[1];
380 #endif
381     int c, n, i;
382
383     if( batchmode ) {
384         log_error("Sorry, we are in batchmode - can't get input\n");
385         exit(2);
386     }
387
388     if (no_terminal) {
389         log_error("Sorry, no terminal at all requested - can't get input\n");
390         exit(2);
391     }
392
393     if( !initialized )
394         init_ttyfp();
395
396     last_prompt_len = 0;
397     tty_printf( "%s", prompt );
398     buf = xmalloc((n=50));
399     i = 0;
400
401 #ifdef _WIN32 /* windoze version */
402     if( hidden )
403         SetConsoleMode(con.in, HID_INPMODE );
404
405     for(;;) {
406         DWORD nread;
407
408         if( !ReadConsoleA( con.in, cbuf, 1, &nread, NULL ) )
409             log_fatal("ReadConsole failed: rc=%d", (int)GetLastError() );
410         if( !nread )
411             continue;
412         if( *cbuf == '\n' )
413             break;
414
415         if( !hidden )
416             last_prompt_len++;
417         c = *cbuf;
418         if( c == '\t' )
419             c = ' ';
420         else if( c > 0xa0 )
421             ; /* we don't allow 0xa0, as this is a protected blank which may
422                * confuse the user */
423         else if( iscntrl(c) )
424             continue;
425         if( !(i < n-1) ) {
426             n += 50;
427             buf = xrealloc (buf, n);
428         }
429         buf[i++] = c;
430     }
431
432     if( hidden )
433         SetConsoleMode(con.in, DEF_INPMODE );
434
435 #elif defined(__riscos__)
436     do {
437         c = riscos_getchar();
438         if (c == 0xa || c == 0xd) { /* Return || Enter */
439             c = (int) '\n';
440         } else if (c == 0x8 || c == 0x7f) { /* Backspace || Delete */
441             if (i>0) {
442                 i--;
443                 if (!hidden) {
444                     last_prompt_len--;
445                     fputc(8, ttyfp);
446                     fputc(32, ttyfp);
447                     fputc(8, ttyfp);
448                     fflush(ttyfp);
449                 }
450             } else {
451                 fputc(7, ttyfp);
452                 fflush(ttyfp);
453             }
454             continue;
455         } else if (c == (int) '\t') { /* Tab */
456             c = ' ';
457         } else if (c > 0xa0) {
458             ; /* we don't allow 0xa0, as this is a protected blank which may
459                * confuse the user */
460         } else if (iscntrl(c)) {
461             continue;
462         }
463         if(!(i < n-1)) {
464             n += 50;
465             buf = xrealloc (buf, n);
466         }
467         buf[i++] = c;
468         if (!hidden) {
469             last_prompt_len++;
470             fputc(c, ttyfp);
471             fflush(ttyfp);
472         }
473     } while (c != '\n');
474     i = (i>0) ? i-1 : 0;
475 #else /* unix version */
476     if( hidden ) {
477 #ifdef HAVE_TCGETATTR
478         struct termios term;
479
480         if( tcgetattr(fileno(ttyfp), &termsave) )
481             log_fatal("tcgetattr() failed: %s\n", strerror(errno) );
482         restore_termios = 1;
483         term = termsave;
484         term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
485         if( tcsetattr( fileno(ttyfp), TCSAFLUSH, &term ) )
486             log_fatal("tcsetattr() failed: %s\n", strerror(errno) );
487 #endif
488     }
489
490     /* fixme: How can we avoid that the \n is echoed w/o disabling
491      * canonical mode - w/o this kill_prompt can't work */
492     while( read(fileno(ttyfp), cbuf, 1) == 1 && *cbuf != '\n' ) {
493         if( !hidden )
494             last_prompt_len++;
495         c = *cbuf;
496         if( c == CONTROL_D )
497             log_info("control d found\n");
498         if( c == '\t' )
499             c = ' ';
500         else if( c > 0xa0 )
501             ; /* we don't allow 0xa0, as this is a protected blank which may
502                * confuse the user */
503         else if( iscntrl(c) )
504             continue;
505         if( !(i < n-1) ) {
506             n += 50;
507             buf = xrealloc (buf, n );
508         }
509         buf[i++] = c;
510     }
511     if( *cbuf != '\n' ) {
512         buf[0] = CONTROL_D;
513         i = 1;
514     }
515
516
517     if( hidden ) {
518 #ifdef HAVE_TCGETATTR
519         if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) )
520             log_error("tcsetattr() failed: %s\n", strerror(errno) );
521         restore_termios = 0;
522 #endif
523     }
524 #endif /* end unix version */
525     buf[i] = 0;
526     return buf;
527 }
528
529
530 char *
531 tty_get( const char *prompt )
532 {
533   if (!batchmode && !no_terminal && my_rl_readline && my_rl_add_history)
534     {
535       char *line;
536       char *buf;
537
538       if (!initialized)
539         init_ttyfp();
540
541       last_prompt_len = 0;
542
543       line = my_rl_readline (prompt?prompt:"");
544
545       /* We need to copy it to memory controlled by our malloc
546          implementations; further we need to convert an EOF to our
547          convention. */
548       buf = xmalloc(line? strlen(line)+1:2);
549       if (line)
550         {
551           strcpy (buf, line);
552           trim_spaces (buf);
553           if (strlen (buf) > 2 )
554             my_rl_add_history (line); /* Note that we test BUF but add LINE. */
555           free (line);
556         }
557       else
558         {
559           buf[0] = CONTROL_D;
560           buf[1] = 0;
561         }
562       return buf;
563     }
564   else
565     return do_get ( prompt, 0 );
566 }
567
568 /* Variable argument version of tty_get.  The prompt is is actually a
569    format string with arguments.  */
570 char *
571 tty_getf (const char *promptfmt, ... )
572 {
573   va_list arg_ptr;
574   char *prompt;
575   char *answer;
576
577   va_start (arg_ptr, promptfmt);
578   if (estream_vasprintf (&prompt, promptfmt, arg_ptr) < 0)
579     log_fatal ("estream_vasprintf failed: %s\n", strerror (errno));
580   va_end (arg_ptr);
581   answer = tty_get (prompt);
582   xfree (prompt);
583   return answer;
584 }
585
586
587
588 char *
589 tty_get_hidden( const char *prompt )
590 {
591     return do_get( prompt, 1 );
592 }
593
594
595 void
596 tty_kill_prompt()
597 {
598     if ( no_terminal )
599         return;
600
601     if( !initialized )
602         init_ttyfp();
603
604     if( batchmode )
605         last_prompt_len = 0;
606     if( !last_prompt_len )
607         return;
608 #ifdef _WIN32
609     tty_printf("\r%*s\r", last_prompt_len, "");
610 #else
611     {
612         int i;
613         putc('\r', ttyfp);
614         for(i=0; i < last_prompt_len; i ++ )
615             putc(' ', ttyfp);
616         putc('\r', ttyfp);
617         fflush(ttyfp);
618     }
619 #endif
620     last_prompt_len = 0;
621 }
622
623
624 int
625 tty_get_answer_is_yes( const char *prompt )
626 {
627     int yes;
628     char *p = tty_get( prompt );
629     tty_kill_prompt();
630     yes = answer_is_yes(p);
631     xfree(p);
632     return yes;
633 }
634
635
636 /* Called by gnupg_rl_initialize to setup the readline support. */
637 void
638 tty_private_set_rl_hooks (void (*init_stream) (FILE *),
639                           void (*set_completer) (rl_completion_func_t*),
640                           void (*inhibit_completion) (int),
641                           void (*cleanup_after_signal) (void),
642                           char *(*readline_fun) (const char*),
643                           void (*add_history_fun) (const char*))
644 {
645   my_rl_init_stream = init_stream;
646   my_rl_set_completer = set_completer;
647   my_rl_inhibit_completion = inhibit_completion;
648   my_rl_cleanup_after_signal = cleanup_after_signal;
649   my_rl_readline = readline_fun;
650   my_rl_add_history = add_history_fun;
651 }
652
653
654 #ifdef HAVE_LIBREADLINE
655 void
656 tty_enable_completion (rl_completion_func_t *completer)
657 {
658   if (no_terminal || !my_rl_set_completer )
659     return;
660
661   if (!initialized)
662     init_ttyfp();
663
664   my_rl_set_completer (completer);
665 }
666
667 void
668 tty_disable_completion (void)
669 {
670   if (no_terminal || !my_rl_inhibit_completion)
671     return;
672
673   if (!initialized)
674     init_ttyfp();
675
676   my_rl_inhibit_completion (1);
677 }
678 #endif
679
680 void
681 tty_cleanup_after_signal (void)
682 {
683 #ifdef HAVE_TCGETATTR
684   cleanup ();
685 #endif
686 }
687
688 void
689 tty_cleanup_rl_after_signal (void)
690 {
691   if (my_rl_cleanup_after_signal)
692     my_rl_cleanup_after_signal ();
693 }