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