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