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