gpgtar: Improve error messages.
[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 <https://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 there 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 /* Print a string, but filter all control characters out.  If FP is
313  * not NULL print to that stream instead to the tty.  */
314 static void
315 do_print_string (estream_t fp, const byte *p, size_t n )
316 {
317   if (no_terminal && !fp)
318     return;
319
320   if (!initialized && !fp)
321     init_ttyfp();
322
323   if (fp)
324     {
325       print_utf8_buffer (fp, p, n);
326       return;
327     }
328
329 #ifdef USE_W32_CONSOLE
330   /* Not so effective, change it if you want */
331   for (; n; n--, p++)
332     {
333       if (iscntrl (*p))
334         {
335           if( *p == '\n' )
336             tty_printf ("\\n");
337           else if( !*p )
338             tty_printf ("\\0");
339           else
340             tty_printf ("\\x%02x", *p);
341         }
342       else
343         tty_printf ("%c", *p);
344     }
345 #else
346   for (; n; n--, p++)
347     {
348       if (iscntrl (*p))
349         {
350           putc ('\\', ttyfp);
351           if ( *p == '\n' )
352             putc ('n', ttyfp);
353           else if ( !*p )
354             putc ('0', ttyfp);
355           else
356             fprintf (ttyfp, "x%02x", *p );
357         }
358       else
359         putc (*p, ttyfp);
360     }
361 #endif
362 }
363
364
365 void
366 tty_print_utf8_string2 (estream_t fp, const byte *p, size_t n, size_t max_n)
367 {
368     size_t i;
369     char *buf;
370
371     if (no_terminal && !fp)
372         return;
373
374     /* we can handle plain ascii simpler, so check for it first */
375     for(i=0; i < n; i++ ) {
376         if( p[i] & 0x80 )
377             break;
378     }
379     if( i < n ) {
380         buf = utf8_to_native( (const char *)p, n, 0 );
381         if( max_n && (strlen( buf ) > max_n )) {
382             buf[max_n] = 0;
383         }
384         /*(utf8 conversion already does the control character quoting)*/
385         tty_fprintf (fp, "%s", buf);
386         xfree (buf);
387     }
388     else {
389         if( max_n && (n > max_n) ) {
390             n = max_n;
391         }
392         do_print_string (fp, p, n );
393     }
394 }
395
396
397 void
398 tty_print_utf8_string( const byte *p, size_t n )
399 {
400   tty_print_utf8_string2 (NULL, p, n, 0);
401 }
402
403
404 static char *
405 do_get( const char *prompt, int hidden )
406 {
407     char *buf;
408 #ifndef __riscos__
409     byte cbuf[1];
410 #endif
411     int c, n, i;
412
413     if( batchmode ) {
414         log_error("Sorry, we are in batchmode - can't get input\n");
415         exit(2);
416     }
417
418     if (no_terminal) {
419         log_error("Sorry, no terminal at all requested - can't get input\n");
420         exit(2);
421     }
422
423     if( !initialized )
424         init_ttyfp();
425
426     last_prompt_len = 0;
427     tty_printf( "%s", prompt );
428     buf = xmalloc((n=50));
429     i = 0;
430
431 #ifdef USE_W32_CONSOLE
432     if( hidden )
433         SetConsoleMode(con.in, HID_INPMODE );
434
435     for(;;) {
436         DWORD nread;
437
438         if( !ReadConsoleA( con.in, cbuf, 1, &nread, NULL ) )
439             log_fatal("ReadConsole failed: rc=%d", (int)GetLastError() );
440         if( !nread )
441             continue;
442         if( *cbuf == '\n' )
443             break;
444
445         if( !hidden )
446             last_prompt_len++;
447         c = *cbuf;
448         if( c == '\t' )
449             c = ' ';
450         else if( c > 0xa0 )
451             ; /* we don't allow 0xa0, as this is a protected blank which may
452                * confuse the user */
453         else if( iscntrl(c) )
454             continue;
455         if( !(i < n-1) ) {
456             n += 50;
457             buf = xrealloc (buf, n);
458         }
459         buf[i++] = c;
460     }
461
462     if( hidden )
463         SetConsoleMode(con.in, DEF_INPMODE );
464
465 #elif defined(__riscos__) || defined(HAVE_W32CE_SYSTEM)
466     do {
467 #ifdef HAVE_W32CE_SYSTEM
468       /* Using getchar is not a correct solution but for now it
469          doesn't matter because we have no real console at all.  We
470          should rework this as soon as we have switched this entire
471          module to estream.  */
472         c = getchar();
473 #else
474         c = riscos_getchar();
475 #endif
476         if (c == 0xa || c == 0xd) { /* Return || Enter */
477             c = (int) '\n';
478         } else if (c == 0x8 || c == 0x7f) { /* Backspace || Delete */
479             if (i>0) {
480                 i--;
481                 if (!hidden) {
482                     last_prompt_len--;
483                     fputc(8, ttyfp);
484                     fputc(32, ttyfp);
485                     fputc(8, ttyfp);
486                     fflush(ttyfp);
487                 }
488             } else {
489                 fputc(7, ttyfp);
490                 fflush(ttyfp);
491             }
492             continue;
493         } else if (c == (int) '\t') { /* Tab */
494             c = ' ';
495         } else if (c > 0xa0) {
496             ; /* we don't allow 0xa0, as this is a protected blank which may
497                * confuse the user */
498         } else if (iscntrl(c)) {
499             continue;
500         }
501         if(!(i < n-1)) {
502             n += 50;
503             buf = xrealloc (buf, n);
504         }
505         buf[i++] = c;
506         if (!hidden) {
507             last_prompt_len++;
508             fputc(c, ttyfp);
509             fflush(ttyfp);
510         }
511     } while (c != '\n');
512     i = (i>0) ? i-1 : 0;
513 #else /* Other systems. */
514     if( hidden ) {
515 #ifdef HAVE_TCGETATTR
516         struct termios term;
517
518         if( tcgetattr(fileno(ttyfp), &termsave) )
519             log_fatal("tcgetattr() failed: %s\n", strerror(errno) );
520         restore_termios = 1;
521         term = termsave;
522         term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
523         if( tcsetattr( fileno(ttyfp), TCSAFLUSH, &term ) )
524             log_fatal("tcsetattr() failed: %s\n", strerror(errno) );
525 #endif
526     }
527
528     /* fixme: How can we avoid that the \n is echoed w/o disabling
529      * canonical mode - w/o this kill_prompt can't work */
530     while( read(fileno(ttyfp), cbuf, 1) == 1 && *cbuf != '\n' ) {
531         if( !hidden )
532             last_prompt_len++;
533         c = *cbuf;
534         if( c == CONTROL_D )
535             log_info("control d found\n");
536         if( c == '\t' )
537             c = ' ';
538         else if( c > 0xa0 )
539             ; /* we don't allow 0xa0, as this is a protected blank which may
540                * confuse the user */
541         else if( iscntrl(c) )
542             continue;
543         if( !(i < n-1) ) {
544             n += 50;
545             buf = xrealloc (buf, n );
546         }
547         buf[i++] = c;
548     }
549     if( *cbuf != '\n' ) {
550         buf[0] = CONTROL_D;
551         i = 1;
552     }
553
554     if( hidden ) {
555 #ifdef HAVE_TCGETATTR
556         if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) )
557             log_error("tcsetattr() failed: %s\n", strerror(errno) );
558         restore_termios = 0;
559 #endif
560     }
561 #endif /* end unix version */
562     buf[i] = 0;
563     return buf;
564 }
565
566
567
568 /* Note: This function never returns NULL. */
569 char *
570 tty_get( const char *prompt )
571 {
572   if (!batchmode && !no_terminal && my_rl_readline && my_rl_add_history)
573     {
574       char *line;
575       char *buf;
576
577       if (!initialized)
578         init_ttyfp();
579
580       last_prompt_len = 0;
581
582       line = my_rl_readline (prompt?prompt:"");
583
584       /* We need to copy it to memory controlled by our malloc
585          implementations; further we need to convert an EOF to our
586          convention. */
587       buf = xmalloc(line? strlen(line)+1:2);
588       if (line)
589         {
590           strcpy (buf, line);
591           trim_spaces (buf);
592           if (strlen (buf) > 2 )
593             my_rl_add_history (line); /* Note that we test BUF but add LINE. */
594           free (line);
595         }
596       else
597         {
598           buf[0] = CONTROL_D;
599           buf[1] = 0;
600         }
601       return buf;
602     }
603   else
604     return do_get ( prompt, 0 );
605 }
606
607 /* Variable argument version of tty_get.  The prompt is actually a
608    format string with arguments.  */
609 char *
610 tty_getf (const char *promptfmt, ... )
611 {
612   va_list arg_ptr;
613   char *prompt;
614   char *answer;
615
616   va_start (arg_ptr, promptfmt);
617   if (gpgrt_vasprintf (&prompt, promptfmt, arg_ptr) < 0)
618     log_fatal ("estream_vasprintf failed: %s\n", strerror (errno));
619   va_end (arg_ptr);
620   answer = tty_get (prompt);
621   xfree (prompt);
622   return answer;
623 }
624
625
626
627 char *
628 tty_get_hidden( const char *prompt )
629 {
630     return do_get( prompt, 1 );
631 }
632
633
634 void
635 tty_kill_prompt()
636 {
637     if ( no_terminal )
638         return;
639
640     if( !initialized )
641         init_ttyfp();
642
643     if( batchmode )
644         last_prompt_len = 0;
645     if( !last_prompt_len )
646         return;
647 #ifdef USE_W32_CONSOLE
648     tty_printf("\r%*s\r", last_prompt_len, "");
649 #else
650     {
651         int i;
652         putc('\r', ttyfp);
653         for(i=0; i < last_prompt_len; i ++ )
654             putc(' ', ttyfp);
655         putc('\r', ttyfp);
656         fflush(ttyfp);
657     }
658 #endif
659     last_prompt_len = 0;
660 }
661
662
663 int
664 tty_get_answer_is_yes( const char *prompt )
665 {
666     int yes;
667     char *p = tty_get( prompt );
668     tty_kill_prompt();
669     yes = answer_is_yes(p);
670     xfree(p);
671     return yes;
672 }
673
674
675 /* Called by gnupg_rl_initialize to setup the readline support. */
676 void
677 tty_private_set_rl_hooks (void (*init_stream) (FILE *),
678                           void (*set_completer) (rl_completion_func_t*),
679                           void (*inhibit_completion) (int),
680                           void (*cleanup_after_signal) (void),
681                           char *(*readline_fun) (const char*),
682                           void (*add_history_fun) (const char*))
683 {
684   my_rl_init_stream = init_stream;
685   my_rl_set_completer = set_completer;
686   my_rl_inhibit_completion = inhibit_completion;
687   my_rl_cleanup_after_signal = cleanup_after_signal;
688   my_rl_readline = readline_fun;
689   my_rl_add_history = add_history_fun;
690 }
691
692
693 #ifdef HAVE_LIBREADLINE
694 void
695 tty_enable_completion (rl_completion_func_t *completer)
696 {
697   if (no_terminal || !my_rl_set_completer )
698     return;
699
700   if (!initialized)
701     init_ttyfp();
702
703   my_rl_set_completer (completer);
704 }
705
706 void
707 tty_disable_completion (void)
708 {
709   if (no_terminal || !my_rl_inhibit_completion)
710     return;
711
712   if (!initialized)
713     init_ttyfp();
714
715   my_rl_inhibit_completion (1);
716 }
717 #endif
718
719 void
720 tty_cleanup_after_signal (void)
721 {
722 #ifdef HAVE_TCGETATTR
723   cleanup ();
724 #endif
725 }
726
727 void
728 tty_cleanup_rl_after_signal (void)
729 {
730   if (my_rl_cleanup_after_signal)
731     my_rl_cleanup_after_signal ();
732 }