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