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