chiark / gitweb /
dirmngr: New option --no-use-tor and internal changes.
[gnupg2.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 char *
568 tty_get( const char *prompt )
569 {
570   if (!batchmode && !no_terminal && my_rl_readline && my_rl_add_history)
571     {
572       char *line;
573       char *buf;
574
575       if (!initialized)
576         init_ttyfp();
577
578       last_prompt_len = 0;
579
580       line = my_rl_readline (prompt?prompt:"");
581
582       /* We need to copy it to memory controlled by our malloc
583          implementations; further we need to convert an EOF to our
584          convention. */
585       buf = xmalloc(line? strlen(line)+1:2);
586       if (line)
587         {
588           strcpy (buf, line);
589           trim_spaces (buf);
590           if (strlen (buf) > 2 )
591             my_rl_add_history (line); /* Note that we test BUF but add LINE. */
592           free (line);
593         }
594       else
595         {
596           buf[0] = CONTROL_D;
597           buf[1] = 0;
598         }
599       return buf;
600     }
601   else
602     return do_get ( prompt, 0 );
603 }
604
605 /* Variable argument version of tty_get.  The prompt is is actually a
606    format string with arguments.  */
607 char *
608 tty_getf (const char *promptfmt, ... )
609 {
610   va_list arg_ptr;
611   char *prompt;
612   char *answer;
613
614   va_start (arg_ptr, promptfmt);
615   if (gpgrt_vasprintf (&prompt, promptfmt, arg_ptr) < 0)
616     log_fatal ("estream_vasprintf failed: %s\n", strerror (errno));
617   va_end (arg_ptr);
618   answer = tty_get (prompt);
619   xfree (prompt);
620   return answer;
621 }
622
623
624
625 char *
626 tty_get_hidden( const char *prompt )
627 {
628     return do_get( prompt, 1 );
629 }
630
631
632 void
633 tty_kill_prompt()
634 {
635     if ( no_terminal )
636         return;
637
638     if( !initialized )
639         init_ttyfp();
640
641     if( batchmode )
642         last_prompt_len = 0;
643     if( !last_prompt_len )
644         return;
645 #ifdef USE_W32_CONSOLE
646     tty_printf("\r%*s\r", last_prompt_len, "");
647 #else
648     {
649         int i;
650         putc('\r', ttyfp);
651         for(i=0; i < last_prompt_len; i ++ )
652             putc(' ', ttyfp);
653         putc('\r', ttyfp);
654         fflush(ttyfp);
655     }
656 #endif
657     last_prompt_len = 0;
658 }
659
660
661 int
662 tty_get_answer_is_yes( const char *prompt )
663 {
664     int yes;
665     char *p = tty_get( prompt );
666     tty_kill_prompt();
667     yes = answer_is_yes(p);
668     xfree(p);
669     return yes;
670 }
671
672
673 /* Called by gnupg_rl_initialize to setup the readline support. */
674 void
675 tty_private_set_rl_hooks (void (*init_stream) (FILE *),
676                           void (*set_completer) (rl_completion_func_t*),
677                           void (*inhibit_completion) (int),
678                           void (*cleanup_after_signal) (void),
679                           char *(*readline_fun) (const char*),
680                           void (*add_history_fun) (const char*))
681 {
682   my_rl_init_stream = init_stream;
683   my_rl_set_completer = set_completer;
684   my_rl_inhibit_completion = inhibit_completion;
685   my_rl_cleanup_after_signal = cleanup_after_signal;
686   my_rl_readline = readline_fun;
687   my_rl_add_history = add_history_fun;
688 }
689
690
691 #ifdef HAVE_LIBREADLINE
692 void
693 tty_enable_completion (rl_completion_func_t *completer)
694 {
695   if (no_terminal || !my_rl_set_completer )
696     return;
697
698   if (!initialized)
699     init_ttyfp();
700
701   my_rl_set_completer (completer);
702 }
703
704 void
705 tty_disable_completion (void)
706 {
707   if (no_terminal || !my_rl_inhibit_completion)
708     return;
709
710   if (!initialized)
711     init_ttyfp();
712
713   my_rl_inhibit_completion (1);
714 }
715 #endif
716
717 void
718 tty_cleanup_after_signal (void)
719 {
720 #ifdef HAVE_TCGETATTR
721   cleanup ();
722 #endif
723 }
724
725 void
726 tty_cleanup_rl_after_signal (void)
727 {
728   if (my_rl_cleanup_after_signal)
729     my_rl_cleanup_after_signal ();
730 }