Line data Source code
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 <http://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 0 : 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 0 : 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 0 : s = ctermid (buffer);
129 : # else
130 : s = ctermid (NULL);
131 : # endif
132 0 : if (s)
133 0 : name = strdup (s);
134 0 : got_name = 1;
135 : }
136 : #endif /*HAVE_CTERMID*/
137 : /* Assume the standard tty on memory error or when there is no
138 : ctermid. */
139 0 : return name? name : "/dev/tty";
140 : }
141 :
142 :
143 :
144 : #ifdef HAVE_TCGETATTR
145 : static void
146 0 : cleanup(void)
147 : {
148 0 : if( restore_termios ) {
149 0 : restore_termios = 0; /* do it prios in case it is interrupted again */
150 0 : if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) )
151 0 : log_error("tcsetattr() failed: %s\n", strerror(errno) );
152 : }
153 0 : }
154 : #endif
155 :
156 : static void
157 0 : init_ttyfp(void)
158 : {
159 0 : if( initialized )
160 0 : 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 0 : ttyfp = batchmode? stderr : fopen (tty_get_ttyname (), "r+");
194 0 : if( !ttyfp ) {
195 0 : log_error("cannot open '%s': %s\n", tty_get_ttyname (),
196 0 : strerror(errno) );
197 0 : exit(2);
198 : }
199 0 : if (my_rl_init_stream)
200 0 : my_rl_init_stream (ttyfp);
201 : #endif
202 :
203 :
204 : #ifdef HAVE_TCGETATTR
205 0 : atexit( cleanup );
206 : #endif
207 0 : initialized = 1;
208 : }
209 :
210 :
211 : int
212 1330 : tty_batchmode( int onoff )
213 : {
214 1330 : int old = batchmode;
215 1330 : if( onoff != -1 )
216 1330 : batchmode = onoff;
217 1330 : return old;
218 : }
219 :
220 : int
221 1 : tty_no_terminal(int onoff)
222 : {
223 1 : int old = no_terminal;
224 1 : no_terminal = onoff ? 1 : 0;
225 1 : return old;
226 : }
227 :
228 : void
229 0 : tty_printf( const char *fmt, ... )
230 : {
231 : va_list arg_ptr;
232 :
233 0 : if (no_terminal)
234 0 : return;
235 :
236 0 : if( !initialized )
237 0 : init_ttyfp();
238 :
239 0 : 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 0 : last_prompt_len += vfprintf(ttyfp,fmt,arg_ptr) ;
259 0 : fflush(ttyfp);
260 : #endif
261 0 : 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 351 : tty_fprintf (estream_t fp, const char *fmt, ... )
269 : {
270 : va_list arg_ptr;
271 :
272 351 : if (fp)
273 : {
274 351 : va_start (arg_ptr, fmt) ;
275 351 : es_vfprintf (fp, fmt, arg_ptr );
276 351 : va_end (arg_ptr);
277 702 : return;
278 : }
279 :
280 0 : if (no_terminal)
281 0 : return;
282 :
283 0 : if (!initialized)
284 0 : init_ttyfp ();
285 :
286 0 : 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 0 : last_prompt_len += vfprintf(ttyfp,fmt,arg_ptr) ;
306 0 : fflush(ttyfp);
307 : #endif
308 0 : 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 0 : tty_print_string (estream_t fp, const byte *p, size_t n )
318 : {
319 0 : if (no_terminal && !fp)
320 0 : return;
321 :
322 0 : if( !initialized & !fp)
323 0 : 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 0 : if (fp)
363 : {
364 0 : for( ; n; n--, p++ )
365 : {
366 0 : if (iscntrl (*p))
367 : {
368 0 : es_putc ('\\', fp);
369 0 : if ( *p == '\n' )
370 0 : es_putc ('n', fp);
371 0 : else if ( !*p )
372 0 : es_putc ('0', fp);
373 : else
374 0 : es_fprintf (fp, "x%02x", *p);
375 : }
376 : else
377 0 : es_putc (*p, fp);
378 : }
379 : }
380 : else
381 : {
382 0 : for (; n; n--, p++)
383 : {
384 0 : if (iscntrl (*p))
385 : {
386 0 : putc ('\\', ttyfp);
387 0 : if ( *p == '\n' )
388 0 : putc ('n', ttyfp);
389 0 : else if ( !*p )
390 0 : putc ('0', ttyfp);
391 : else
392 0 : fprintf (ttyfp, "x%02x", *p );
393 : }
394 : else
395 0 : putc (*p, ttyfp);
396 : }
397 : }
398 : #endif
399 : }
400 :
401 : void
402 0 : 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 0 : if (no_terminal && !fp)
408 0 : return;
409 :
410 : /* we can handle plain ascii simpler, so check for it first */
411 0 : for(i=0; i < n; i++ ) {
412 0 : if( p[i] & 0x80 )
413 0 : break;
414 : }
415 0 : if( i < n ) {
416 0 : buf = utf8_to_native( (const char *)p, n, 0 );
417 0 : if( max_n && (strlen( buf ) > max_n )) {
418 0 : buf[max_n] = 0;
419 : }
420 : /*(utf8 conversion already does the control character quoting)*/
421 0 : tty_fprintf (fp, "%s", buf);
422 0 : xfree (buf);
423 : }
424 : else {
425 0 : if( max_n && (n > max_n) ) {
426 0 : n = max_n;
427 : }
428 0 : tty_print_string (fp, p, n );
429 : }
430 : }
431 :
432 :
433 : void
434 0 : tty_print_utf8_string( const byte *p, size_t n )
435 : {
436 0 : tty_print_utf8_string2 (NULL, p, n, 0);
437 0 : }
438 :
439 :
440 : static char *
441 0 : 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 0 : if( batchmode ) {
450 0 : log_error("Sorry, we are in batchmode - can't get input\n");
451 0 : exit(2);
452 : }
453 :
454 0 : if (no_terminal) {
455 0 : log_error("Sorry, no terminal at all requested - can't get input\n");
456 0 : exit(2);
457 : }
458 :
459 0 : if( !initialized )
460 0 : init_ttyfp();
461 :
462 0 : last_prompt_len = 0;
463 0 : tty_printf( "%s", prompt );
464 0 : buf = xmalloc((n=50));
465 0 : 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 0 : if( hidden ) {
551 : #ifdef HAVE_TCGETATTR
552 : struct termios term;
553 :
554 0 : if( tcgetattr(fileno(ttyfp), &termsave) )
555 0 : log_fatal("tcgetattr() failed: %s\n", strerror(errno) );
556 0 : restore_termios = 1;
557 0 : term = termsave;
558 0 : term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
559 0 : if( tcsetattr( fileno(ttyfp), TCSAFLUSH, &term ) )
560 0 : 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 0 : while( read(fileno(ttyfp), cbuf, 1) == 1 && *cbuf != '\n' ) {
567 0 : if( !hidden )
568 0 : last_prompt_len++;
569 0 : c = *cbuf;
570 0 : if( c == CONTROL_D )
571 0 : log_info("control d found\n");
572 0 : if( c == '\t' )
573 0 : c = ' ';
574 0 : else if( c > 0xa0 )
575 : ; /* we don't allow 0xa0, as this is a protected blank which may
576 : * confuse the user */
577 0 : else if( iscntrl(c) )
578 0 : continue;
579 0 : if( !(i < n-1) ) {
580 0 : n += 50;
581 0 : buf = xrealloc (buf, n );
582 : }
583 0 : buf[i++] = c;
584 : }
585 0 : if( *cbuf != '\n' ) {
586 0 : buf[0] = CONTROL_D;
587 0 : i = 1;
588 : }
589 :
590 0 : if( hidden ) {
591 : #ifdef HAVE_TCGETATTR
592 0 : if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) )
593 0 : log_error("tcsetattr() failed: %s\n", strerror(errno) );
594 0 : restore_termios = 0;
595 : #endif
596 : }
597 : #endif /* end unix version */
598 0 : buf[i] = 0;
599 0 : return buf;
600 : }
601 :
602 :
603 : char *
604 0 : tty_get( const char *prompt )
605 : {
606 0 : if (!batchmode && !no_terminal && my_rl_readline && my_rl_add_history)
607 : {
608 : char *line;
609 : char *buf;
610 :
611 0 : if (!initialized)
612 0 : init_ttyfp();
613 :
614 0 : last_prompt_len = 0;
615 :
616 0 : 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 0 : buf = xmalloc(line? strlen(line)+1:2);
622 0 : if (line)
623 : {
624 0 : strcpy (buf, line);
625 0 : trim_spaces (buf);
626 0 : if (strlen (buf) > 2 )
627 0 : my_rl_add_history (line); /* Note that we test BUF but add LINE. */
628 0 : free (line);
629 : }
630 : else
631 : {
632 0 : buf[0] = CONTROL_D;
633 0 : buf[1] = 0;
634 : }
635 0 : return buf;
636 : }
637 : else
638 0 : 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 0 : tty_getf (const char *promptfmt, ... )
645 : {
646 : va_list arg_ptr;
647 : char *prompt;
648 : char *answer;
649 :
650 0 : va_start (arg_ptr, promptfmt);
651 0 : if (gpgrt_vasprintf (&prompt, promptfmt, arg_ptr) < 0)
652 0 : log_fatal ("estream_vasprintf failed: %s\n", strerror (errno));
653 0 : va_end (arg_ptr);
654 0 : answer = tty_get (prompt);
655 0 : xfree (prompt);
656 0 : return answer;
657 : }
658 :
659 :
660 :
661 : char *
662 0 : tty_get_hidden( const char *prompt )
663 : {
664 0 : return do_get( prompt, 1 );
665 : }
666 :
667 :
668 : void
669 0 : tty_kill_prompt()
670 : {
671 0 : if ( no_terminal )
672 0 : return;
673 :
674 0 : if( !initialized )
675 0 : init_ttyfp();
676 :
677 0 : if( batchmode )
678 0 : last_prompt_len = 0;
679 0 : if( !last_prompt_len )
680 0 : return;
681 : #ifdef USE_W32_CONSOLE
682 : tty_printf("\r%*s\r", last_prompt_len, "");
683 : #else
684 : {
685 : int i;
686 0 : putc('\r', ttyfp);
687 0 : for(i=0; i < last_prompt_len; i ++ )
688 0 : putc(' ', ttyfp);
689 0 : putc('\r', ttyfp);
690 0 : fflush(ttyfp);
691 : }
692 : #endif
693 0 : last_prompt_len = 0;
694 : }
695 :
696 :
697 : int
698 0 : tty_get_answer_is_yes( const char *prompt )
699 : {
700 : int yes;
701 0 : char *p = tty_get( prompt );
702 0 : tty_kill_prompt();
703 0 : yes = answer_is_yes(p);
704 0 : xfree(p);
705 0 : return yes;
706 : }
707 :
708 :
709 : /* Called by gnupg_rl_initialize to setup the readline support. */
710 : void
711 1914 : 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 1914 : my_rl_init_stream = init_stream;
719 1914 : my_rl_set_completer = set_completer;
720 1914 : my_rl_inhibit_completion = inhibit_completion;
721 1914 : my_rl_cleanup_after_signal = cleanup_after_signal;
722 1914 : my_rl_readline = readline_fun;
723 1914 : my_rl_add_history = add_history_fun;
724 1914 : }
725 :
726 :
727 : #ifdef HAVE_LIBREADLINE
728 : void
729 0 : tty_enable_completion (rl_completion_func_t *completer)
730 : {
731 0 : if (no_terminal || !my_rl_set_completer )
732 0 : return;
733 :
734 0 : if (!initialized)
735 0 : init_ttyfp();
736 :
737 0 : my_rl_set_completer (completer);
738 : }
739 :
740 : void
741 0 : tty_disable_completion (void)
742 : {
743 0 : if (no_terminal || !my_rl_inhibit_completion)
744 0 : return;
745 :
746 0 : if (!initialized)
747 0 : init_ttyfp();
748 :
749 0 : my_rl_inhibit_completion (1);
750 : }
751 : #endif
752 :
753 : void
754 0 : tty_cleanup_after_signal (void)
755 : {
756 : #ifdef HAVE_TCGETATTR
757 0 : cleanup ();
758 : #endif
759 0 : }
760 :
761 : void
762 0 : tty_cleanup_rl_after_signal (void)
763 : {
764 0 : if (my_rl_cleanup_after_signal)
765 0 : my_rl_cleanup_after_signal ();
766 0 : }
|