Installed revised and updated translation
[gnupg.git] / common / ttyio.c
1 /* ttyio.c -  tty i/O functions
2  * Copyright (C) 1998,1999,2000,2001,2002,2003,
3  *               2004, 2006 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 2 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, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20  * USA.
21  */
22
23 #include <config.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdarg.h>
28 #include <unistd.h>
29 #ifdef HAVE_TCGETATTR
30 #include <termios.h>
31 #else
32 #ifdef HAVE_TERMIO_H
33 /* simulate termios with termio */
34 #include <termio.h>
35 #define termios termio
36 #define tcsetattr ioctl
37 #define TCSAFLUSH TCSETAF
38 #define tcgetattr(A,B) ioctl(A,TCGETA,B)
39 #define HAVE_TCGETATTR
40 #endif
41 #endif
42 #ifdef _WIN32 /* use the odd Win32 functions */
43 #include <windows.h>
44 #ifdef HAVE_TCGETATTR
45 #error mingw32 and termios
46 #endif
47 #endif
48 #include <errno.h>
49 #include <ctype.h>
50
51 #include "util.h"
52 #include "ttyio.h"
53 #include "common-defs.h"
54
55 #define CONTROL_D ('D' - 'A' + 1)
56
57 #ifdef _WIN32 /* use the odd Win32 functions */
58 static struct {
59     HANDLE in, out;
60 } con;
61 #define DEF_INPMODE  (ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT    \
62                                         |ENABLE_PROCESSED_INPUT )
63 #define HID_INPMODE  (ENABLE_LINE_INPUT|ENABLE_PROCESSED_INPUT )
64 #define DEF_OUTMODE  (ENABLE_WRAP_AT_EOL_OUTPUT|ENABLE_PROCESSED_OUTPUT)
65
66 #else /* yeah, we have a real OS */
67 static FILE *ttyfp = NULL;
68 #endif
69
70 static int initialized;
71 static int last_prompt_len;
72 static int batchmode;
73 static int no_terminal;
74
75 #ifdef HAVE_TCGETATTR
76     static struct termios termsave;
77     static int restore_termios;
78 #endif
79
80 /* Hooks set by gpgrlhelp.c if required. */
81 static void (*my_rl_set_completer) (rl_completion_func_t *);
82 static void (*my_rl_inhibit_completion) (int);
83 static void (*my_rl_cleanup_after_signal) (void);
84 static void (*my_rl_init_stream) (FILE *);
85 static char *(*my_rl_readline) (const char*);
86 static void (*my_rl_add_history) (const char*);
87
88
89 /* This is a wrapper around ttyname so that we can use it even when
90    the standard streams are redirected.  It figures the name out the
91    first time and returns it in a statically allocated buffer. */
92 const char *
93 tty_get_ttyname (void)
94 {
95   static char *name;
96
97   /* On a GNU system ctermid() always return /dev/tty, so this does
98      not make much sense - however if it is ever changed we do the
99      Right Thing now. */
100 #ifdef HAVE_CTERMID
101   static int got_name;
102
103   if (!got_name)
104     {
105       const char *s;
106       /* Note that despite our checks for these macros the function is
107          not necessarily thread save.  We mainly do this for
108          portability reasons, in case L_ctermid is not defined. */
109 # if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(_POSIX_TRHEADS)
110       char buffer[L_ctermid];
111       s = ctermid (buffer);
112 # else
113       s = ctermid (NULL);
114 # endif
115       if (s)
116         name = strdup (s);
117       got_name = 1;
118     }
119 #endif /*HAVE_CTERMID*/
120   /* Assume the standard tty on memory error or when tehre is no
121      certmid. */
122   return name? name : "/dev/tty";
123 }
124
125
126
127 #ifdef HAVE_TCGETATTR
128 static void
129 cleanup(void)
130 {
131     if( restore_termios ) {
132         restore_termios = 0; /* do it prios in case it is interrupted again */
133         if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) )
134             log_error("tcsetattr() failed: %s\n", strerror(errno) );
135     }
136 }
137 #endif
138
139 static void
140 init_ttyfp(void)
141 {
142     if( initialized )
143         return;
144
145 #if defined(_WIN32)
146     {
147         SECURITY_ATTRIBUTES sa;
148
149         memset(&sa, 0, sizeof(sa));
150         sa.nLength = sizeof(sa);
151         sa.bInheritHandle = TRUE;
152         con.out = CreateFileA( "CONOUT$", GENERIC_READ|GENERIC_WRITE,
153                                FILE_SHARE_READ|FILE_SHARE_WRITE,
154                                &sa, OPEN_EXISTING, 0, 0 );
155         if( con.out == INVALID_HANDLE_VALUE )
156             log_fatal("open(CONOUT$) failed: rc=%d", (int)GetLastError() );
157         memset(&sa, 0, sizeof(sa));
158         sa.nLength = sizeof(sa);
159         sa.bInheritHandle = TRUE;
160         con.in = CreateFileA( "CONIN$", GENERIC_READ|GENERIC_WRITE,
161                                FILE_SHARE_READ|FILE_SHARE_WRITE,
162                                &sa, OPEN_EXISTING, 0, 0 );
163         if( con.in == INVALID_HANDLE_VALUE )
164             log_fatal("open(CONIN$) failed: rc=%d", (int)GetLastError() );
165     }
166     SetConsoleMode(con.in, DEF_INPMODE );
167     SetConsoleMode(con.out, DEF_OUTMODE );
168
169 #elif defined(__EMX__)
170     ttyfp = stdout; /* Fixme: replace by the real functions: see wklib */
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 #endif
179     
180     if (my_rl_init_stream)
181       my_rl_init_stream (ttyfp);
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 regualr
245    fprintf. */
246 void
247 tty_fprintf (FILE *fp, const char *fmt, ... )
248 {
249   va_list arg_ptr;
250
251   if (fp)
252     {
253       va_start (arg_ptr, fmt) ;
254       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 char *
565 tty_get_hidden( const char *prompt )
566 {
567     return do_get( prompt, 1 );
568 }
569
570
571 void
572 tty_kill_prompt()
573 {
574     if ( no_terminal )
575         return;
576
577     if( !initialized )
578         init_ttyfp();
579
580     if( batchmode )
581         last_prompt_len = 0;
582     if( !last_prompt_len )
583         return;
584 #ifdef _WIN32
585     tty_printf("\r%*s\r", last_prompt_len, "");
586 #else
587     {
588         int i;
589         putc('\r', ttyfp);
590         for(i=0; i < last_prompt_len; i ++ )
591             putc(' ', ttyfp);
592         putc('\r', ttyfp);
593         fflush(ttyfp);
594     }
595 #endif
596     last_prompt_len = 0;
597 }
598
599
600 int
601 tty_get_answer_is_yes( const char *prompt )
602 {
603     int yes;
604     char *p = tty_get( prompt );
605     tty_kill_prompt();
606     yes = answer_is_yes(p);
607     xfree(p);
608     return yes;
609 }
610
611
612 /* Called by gnupg_rl_initialize to setup the reradline support. */
613 void
614 tty_private_set_rl_hooks (void (*init_stream) (FILE *),
615                           void (*set_completer) (rl_completion_func_t*),
616                           void (*inhibit_completion) (int),
617                           void (*cleanup_after_signal) (void),
618                           char *(*readline_fun) (const char*),
619                           void (*add_history_fun) (const char*))
620 {
621   my_rl_init_stream = init_stream;
622   my_rl_set_completer = set_completer;
623   my_rl_inhibit_completion = inhibit_completion;
624   my_rl_cleanup_after_signal = cleanup_after_signal;
625   my_rl_readline = readline_fun;
626   my_rl_add_history = add_history_fun;
627 }
628
629
630 void
631 tty_enable_completion (rl_completion_func_t *completer)
632 {
633   if (no_terminal || !my_rl_set_completer )
634     return;
635
636   if (!initialized)
637     init_ttyfp();
638
639   my_rl_set_completer (completer);
640 }
641
642 void
643 tty_disable_completion (void)
644 {
645   if (no_terminal || !my_rl_inhibit_completion)
646     return;
647
648   if (!initialized)
649     init_ttyfp();
650
651   my_rl_inhibit_completion (1);
652 }
653
654
655 void
656 tty_cleanup_rl_after_signal (void)
657 {
658   if (my_rl_cleanup_after_signal)
659     my_rl_cleanup_after_signal ();
660 }