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