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