import gdb-1999-07-19 snapshot
[deliverable/binutils-gdb.git] / readline / rltty.c
CommitLineData
d60d9f65
SS
1/* rltty.c -- functions to prepare and restore the terminal for readline's
2 use. */
3
4/* Copyright (C) 1992 Free Software Foundation, Inc.
5
6 This file is part of the GNU Readline Library, a library for
7 reading lines of text with interactive input and history editing.
8
9 The GNU Readline Library is free software; you can redistribute it
10 and/or modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 1, or
12 (at your option) any later version.
13
14 The GNU Readline Library is distributed in the hope that it will be
15 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
16 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 The GNU General Public License is often shipped with GNU software, and
20 is generally kept in a file called COPYING or LICENSE. If you do not
21 have a copy of the license, write to the Free Software Foundation,
22 675 Mass Ave, Cambridge, MA 02139, USA. */
23#define READLINE_LIBRARY
24
25#if defined (HAVE_CONFIG_H)
26# include <config.h>
27#endif
28
29#include <sys/types.h>
30#include <signal.h>
31#include <errno.h>
32#include <stdio.h>
33
34#if defined (HAVE_UNISTD_H)
35# include <unistd.h>
36#endif /* HAVE_UNISTD_H */
37
38#include "rldefs.h"
39
40#if !defined (SHELL) && defined (GWINSZ_IN_SYS_IOCTL)
41# include <sys/ioctl.h>
42#endif /* !SHELL && GWINSZ_IN_SYS_IOCTL */
43
44#include "rltty.h"
45#include "readline.h"
46
47#if !defined (errno)
48extern int errno;
49#endif /* !errno */
50
51extern int readline_echoing_p;
52extern int _rl_eof_char;
53
54extern int _rl_enable_keypad, _rl_enable_meta;
55
56extern void _rl_control_keypad ();
57
58#if defined (__GO32__)
59# include <pc.h>
60# undef HANDLE_SIGNALS
61#endif /* __GO32__ */
62
63/* Indirect functions to allow apps control over terminal management. */
64extern void rl_prep_terminal (), rl_deprep_terminal ();
65
66VFunction *rl_prep_term_function = rl_prep_terminal;
67VFunction *rl_deprep_term_function = rl_deprep_terminal;
68
69/* **************************************************************** */
70/* */
71/* Signal Management */
72/* */
73/* **************************************************************** */
74
75#if defined (HAVE_POSIX_SIGNALS)
76static sigset_t sigint_set, sigint_oset;
77#else /* !HAVE_POSIX_SIGNALS */
78# if defined (HAVE_BSD_SIGNALS)
79static int sigint_oldmask;
80# endif /* HAVE_BSD_SIGNALS */
81#endif /* !HAVE_POSIX_SIGNALS */
82
83static int sigint_blocked;
84
85/* Cause SIGINT to not be delivered until the corresponding call to
86 release_sigint(). */
87static void
88block_sigint ()
89{
90 if (sigint_blocked)
91 return;
92
93#if defined (HAVE_POSIX_SIGNALS)
94 sigemptyset (&sigint_set);
95 sigemptyset (&sigint_oset);
96 sigaddset (&sigint_set, SIGINT);
97 sigprocmask (SIG_BLOCK, &sigint_set, &sigint_oset);
98#else /* !HAVE_POSIX_SIGNALS */
99# if defined (HAVE_BSD_SIGNALS)
100 sigint_oldmask = sigblock (sigmask (SIGINT));
101# else /* !HAVE_BSD_SIGNALS */
102# if defined (HAVE_USG_SIGHOLD)
103 sighold (SIGINT);
104# endif /* HAVE_USG_SIGHOLD */
105# endif /* !HAVE_BSD_SIGNALS */
106#endif /* !HAVE_POSIX_SIGNALS */
107 sigint_blocked = 1;
108}
109
110/* Allow SIGINT to be delivered. */
111static void
112release_sigint ()
113{
114 if (!sigint_blocked)
115 return;
116
117#if defined (HAVE_POSIX_SIGNALS)
118 sigprocmask (SIG_SETMASK, &sigint_oset, (sigset_t *)NULL);
119#else
120# if defined (HAVE_BSD_SIGNALS)
121 sigsetmask (sigint_oldmask);
122# else /* !HAVE_BSD_SIGNALS */
123# if defined (HAVE_USG_SIGHOLD)
124 sigrelse (SIGINT);
125# endif /* HAVE_USG_SIGHOLD */
126# endif /* !HAVE_BSD_SIGNALS */
127#endif /* !HAVE_POSIX_SIGNALS */
128
129 sigint_blocked = 0;
130}
131
132/* **************************************************************** */
133/* */
134/* Saving and Restoring the TTY */
135/* */
136/* **************************************************************** */
137
138/* Non-zero means that the terminal is in a prepped state. */
139static int terminal_prepped;
140
141/* If non-zero, means that this process has called tcflow(fd, TCOOFF)
142 and output is suspended. */
143#if defined (__ksr1__)
144static int ksrflow;
145#endif
146
147#if !defined (SHELL) && defined (TIOCGWINSZ)
148/* Dummy call to force a backgrounded readline to stop before it tries
149 to get the tty settings. */
150static void
151set_winsize (tty)
152 int tty;
153{
154 struct winsize w;
155
156 if (ioctl (tty, TIOCGWINSZ, &w) == 0)
157 (void) ioctl (tty, TIOCSWINSZ, &w);
158}
159#else /* SHELL || !TIOCGWINSZ */
160# define set_winsize(tty)
161#endif /* SHELL || !TIOCGWINSZ */
162
163#if defined (NEW_TTY_DRIVER)
164
165/* Values for the `flags' field of a struct bsdtty. This tells which
166 elements of the struct bsdtty have been fetched from the system and
167 are valid. */
168#define SGTTY_SET 0x01
169#define LFLAG_SET 0x02
170#define TCHARS_SET 0x04
171#define LTCHARS_SET 0x08
172
173struct bsdtty {
174 struct sgttyb sgttyb; /* Basic BSD tty driver information. */
175 int lflag; /* Local mode flags, like LPASS8. */
176#if defined (TIOCGETC)
177 struct tchars tchars; /* Terminal special characters, including ^S and ^Q. */
178#endif
179#if defined (TIOCGLTC)
180 struct ltchars ltchars; /* 4.2 BSD editing characters */
181#endif
182 int flags; /* Bitmap saying which parts of the struct are valid. */
183};
184
185#define TIOTYPE struct bsdtty
186
187static TIOTYPE otio;
188
189static int
190get_tty_settings (tty, tiop)
191 int tty;
192 TIOTYPE *tiop;
193{
194 set_winsize (tty);
195
196 tiop->flags = tiop->lflag = 0;
197
198 ioctl (tty, TIOCGETP, &(tiop->sgttyb));
199 tiop->flags |= SGTTY_SET;
200
201#if defined (TIOCLGET)
202 ioctl (tty, TIOCLGET, &(tiop->lflag));
203 tiop->flags |= LFLAG_SET;
204#endif
205
206#if defined (TIOCGETC)
207 ioctl (tty, TIOCGETC, &(tiop->tchars));
208 tiop->flags |= TCHARS_SET;
209#endif
210
211#if defined (TIOCGLTC)
212 ioctl (tty, TIOCGLTC, &(tiop->ltchars));
213 tiop->flags |= LTCHARS_SET;
214#endif
215
216 return 0;
217}
218
219static int
220set_tty_settings (tty, tiop)
221 int tty;
222 TIOTYPE *tiop;
223{
224 if (tiop->flags & SGTTY_SET)
225 {
226 ioctl (tty, TIOCSETN, &(tiop->sgttyb));
227 tiop->flags &= ~SGTTY_SET;
228 }
229 readline_echoing_p = 1;
230
231#if defined (TIOCLSET)
232 if (tiop->flags & LFLAG_SET)
233 {
234 ioctl (tty, TIOCLSET, &(tiop->lflag));
235 tiop->flags &= ~LFLAG_SET;
236 }
237#endif
238
239#if defined (TIOCSETC)
240 if (tiop->flags & TCHARS_SET)
241 {
242 ioctl (tty, TIOCSETC, &(tiop->tchars));
243 tiop->flags &= ~TCHARS_SET;
244 }
245#endif
246
247#if defined (TIOCSLTC)
248 if (tiop->flags & LTCHARS_SET)
249 {
250 ioctl (tty, TIOCSLTC, &(tiop->ltchars));
251 tiop->flags &= ~LTCHARS_SET;
252 }
253#endif
254
255 return 0;
256}
257
258static void
259prepare_terminal_settings (meta_flag, otio, tiop)
260 int meta_flag;
261 TIOTYPE otio, *tiop;
262{
263#if !defined (__GO32__)
264 readline_echoing_p = (otio.sgttyb.sg_flags & ECHO);
265
266 /* Copy the original settings to the structure we're going to use for
267 our settings. */
268 tiop->sgttyb = otio.sgttyb;
269 tiop->lflag = otio.lflag;
270#if defined (TIOCGETC)
271 tiop->tchars = otio.tchars;
272#endif
273#if defined (TIOCGLTC)
274 tiop->ltchars = otio.ltchars;
275#endif
276 tiop->flags = otio.flags;
277
278 /* First, the basic settings to put us into character-at-a-time, no-echo
279 input mode. */
280 tiop->sgttyb.sg_flags &= ~(ECHO | CRMOD);
281 tiop->sgttyb.sg_flags |= CBREAK;
282
283 /* If this terminal doesn't care how the 8th bit is used, then we can
284 use it for the meta-key. If only one of even or odd parity is
285 specified, then the terminal is using parity, and we cannot. */
286#if !defined (ANYP)
287# define ANYP (EVENP | ODDP)
288#endif
289 if (((otio.sgttyb.sg_flags & ANYP) == ANYP) ||
290 ((otio.sgttyb.sg_flags & ANYP) == 0))
291 {
292 tiop->sgttyb.sg_flags |= ANYP;
293
294 /* Hack on local mode flags if we can. */
295#if defined (TIOCLGET)
296# if defined (LPASS8)
297 tiop->lflag |= LPASS8;
298# endif /* LPASS8 */
299#endif /* TIOCLGET */
300 }
301
302#if defined (TIOCGETC)
303# if defined (USE_XON_XOFF)
304 /* Get rid of terminal output start and stop characters. */
305 tiop->tchars.t_stopc = -1; /* C-s */
306 tiop->tchars.t_startc = -1; /* C-q */
307
308 /* If there is an XON character, bind it to restart the output. */
309 if (otio.tchars.t_startc != -1)
310 rl_bind_key (otio.tchars.t_startc, rl_restart_output);
311# endif /* USE_XON_XOFF */
312
313 /* If there is an EOF char, bind _rl_eof_char to it. */
314 if (otio.tchars.t_eofc != -1)
315 _rl_eof_char = otio.tchars.t_eofc;
316
317# if defined (NO_KILL_INTR)
318 /* Get rid of terminal-generated SIGQUIT and SIGINT. */
319 tiop->tchars.t_quitc = -1; /* C-\ */
320 tiop->tchars.t_intrc = -1; /* C-c */
321# endif /* NO_KILL_INTR */
322#endif /* TIOCGETC */
323
324#if defined (TIOCGLTC)
325 /* Make the interrupt keys go away. Just enough to make people happy. */
326 tiop->ltchars.t_dsuspc = -1; /* C-y */
327 tiop->ltchars.t_lnextc = -1; /* C-v */
328#endif /* TIOCGLTC */
329#endif /* !__GO32__ */
330}
331
332#else /* !defined (NEW_TTY_DRIVER) */
333
334#if !defined (VMIN)
335# define VMIN VEOF
336#endif
337
338#if !defined (VTIME)
339# define VTIME VEOL
340#endif
341
342#if defined (TERMIOS_TTY_DRIVER)
343# define TIOTYPE struct termios
344# define DRAIN_OUTPUT(fd) tcdrain (fd)
345# define GETATTR(tty, tiop) (tcgetattr (tty, tiop))
346# ifdef M_UNIX
347# define SETATTR(tty, tiop) (tcsetattr (tty, TCSANOW, tiop))
348# else
349# define SETATTR(tty, tiop) (tcsetattr (tty, TCSADRAIN, tiop))
350# endif /* !M_UNIX */
351#else
352# define TIOTYPE struct termio
353# define DRAIN_OUTPUT(fd)
354# define GETATTR(tty, tiop) (ioctl (tty, TCGETA, tiop))
355# define SETATTR(tty, tiop) (ioctl (tty, TCSETA, tiop))
356#endif /* !TERMIOS_TTY_DRIVER */
357
358static TIOTYPE otio;
359
360#if defined (FLUSHO)
361# define OUTPUT_BEING_FLUSHED(tp) (tp->c_lflag & FLUSHO)
362#else
363# define OUTPUT_BEING_FLUSHED(tp) 0
364#endif
365
366static void
367rltty_warning (msg)
368 char *msg;
369{
370 fprintf (stderr, "readline: warning: %s\n", msg);
371}
372
373#if defined (_AIX)
374void
375setopost(tp)
376TIOTYPE *tp;
377{
378 if ((tp->c_oflag & OPOST) == 0)
379 {
380 rltty_warning ("turning on OPOST for terminal\r");
381 tp->c_oflag |= OPOST|ONLCR;
382 }
383}
384#endif
385
386static int
387get_tty_settings (tty, tiop)
388 int tty;
389 TIOTYPE *tiop;
390{
391 int ioctl_ret;
392 set_winsize (tty);
393
394 while (1)
395 {
396 ioctl_ret = GETATTR (tty, tiop);
397 if (ioctl_ret < 0)
398 {
399 if (errno != EINTR)
400 return -1;
401 else
402 continue;
403 }
404 if (OUTPUT_BEING_FLUSHED (tiop))
405 {
406#if defined (FLUSHO) && defined (_AIX41)
407 rltty_warning ("turning off output flushing");
408 tiop->c_lflag &= ~FLUSHO;
409 break;
410#else
411 continue;
412#endif
413 }
414 break;
415 }
416
417#if defined (_AIX)
418 setopost(tiop);
419#endif
420
421 return 0;
422}
423
424static int
425set_tty_settings (tty, tiop)
426 int tty;
427 TIOTYPE *tiop;
428{
429 while (SETATTR (tty, tiop) < 0)
430 {
431 if (errno != EINTR)
432 return -1;
433 errno = 0;
434 }
435
436#if 0
437
438#if defined (TERMIOS_TTY_DRIVER)
439# if defined (__ksr1__)
440 if (ksrflow)
441 {
442 ksrflow = 0;
443 tcflow (tty, TCOON);
444 }
445# else /* !ksr1 */
446 tcflow (tty, TCOON); /* Simulate a ^Q. */
447# endif /* !ksr1 */
448#else
449 ioctl (tty, TCXONC, 1); /* Simulate a ^Q. */
450#endif /* !TERMIOS_TTY_DRIVER */
451
452#endif
453
454 return 0;
455}
456
457static void
458prepare_terminal_settings (meta_flag, otio, tiop)
459 int meta_flag;
460 TIOTYPE otio, *tiop;
461{
462 readline_echoing_p = (otio.c_lflag & ECHO);
463
464 tiop->c_lflag &= ~(ICANON | ECHO);
465
466 if ((unsigned char) otio.c_cc[VEOF] != (unsigned char) _POSIX_VDISABLE)
467 _rl_eof_char = otio.c_cc[VEOF];
468
469#if defined (USE_XON_XOFF)
470#if defined (IXANY)
471 tiop->c_iflag &= ~(IXON | IXOFF | IXANY);
472#else
473 /* `strict' Posix systems do not define IXANY. */
474 tiop->c_iflag &= ~(IXON | IXOFF);
475#endif /* IXANY */
476#endif /* USE_XON_XOFF */
477
478 /* Only turn this off if we are using all 8 bits. */
479 if (((tiop->c_cflag & CSIZE) == CS8) || meta_flag)
480 tiop->c_iflag &= ~(ISTRIP | INPCK);
481
482 /* Make sure we differentiate between CR and NL on input. */
483 tiop->c_iflag &= ~(ICRNL | INLCR);
484
485#if !defined (HANDLE_SIGNALS)
486 tiop->c_lflag &= ~ISIG;
487#else
488 tiop->c_lflag |= ISIG;
489#endif
490
491 tiop->c_cc[VMIN] = 1;
492 tiop->c_cc[VTIME] = 0;
493
494#if defined (FLUSHO)
495 if (OUTPUT_BEING_FLUSHED (tiop))
496 {
497 tiop->c_lflag &= ~FLUSHO;
498 otio.c_lflag &= ~FLUSHO;
499 }
500#endif
501
502 /* Turn off characters that we need on Posix systems with job control,
503 just to be sure. This includes ^Y and ^V. This should not really
504 be necessary. */
505#if defined (TERMIOS_TTY_DRIVER) && defined (_POSIX_VDISABLE)
506
507#if defined (VLNEXT)
508 tiop->c_cc[VLNEXT] = _POSIX_VDISABLE;
509#endif
510
511#if defined (VDSUSP)
512 tiop->c_cc[VDSUSP] = _POSIX_VDISABLE;
513#endif
514
515#endif /* TERMIOS_TTY_DRIVER && _POSIX_VDISABLE */
516}
517#endif /* NEW_TTY_DRIVER */
518
519/* Put the terminal in CBREAK mode so that we can detect key presses. */
520void
521rl_prep_terminal (meta_flag)
522 int meta_flag;
523{
524#if !defined (__GO32__)
525 int tty;
526 TIOTYPE tio;
527
528 if (terminal_prepped)
529 return;
530
531 /* Try to keep this function from being INTerrupted. */
532 block_sigint ();
533
534 tty = fileno (rl_instream);
535
536 if (get_tty_settings (tty, &tio) < 0)
537 {
538 release_sigint ();
539 return;
540 }
541
542 otio = tio;
543
544 prepare_terminal_settings (meta_flag, otio, &tio);
545
546 if (set_tty_settings (tty, &tio) < 0)
547 {
548 release_sigint ();
549 return;
550 }
551
552 if (_rl_enable_keypad)
553 _rl_control_keypad (1);
554
555 fflush (rl_outstream);
556 terminal_prepped = 1;
557
558 release_sigint ();
559#endif /* !__GO32__ */
560}
561
562/* Restore the terminal's normal settings and modes. */
563void
564rl_deprep_terminal ()
565{
566#if !defined (__GO32__)
567 int tty;
568
569 if (!terminal_prepped)
570 return;
571
572 /* Try to keep this function from being interrupted. */
573 block_sigint ();
574
575 tty = fileno (rl_instream);
576
577 if (_rl_enable_keypad)
578 _rl_control_keypad (0);
579
580 fflush (rl_outstream);
581
582 if (set_tty_settings (tty, &otio) < 0)
583 {
584 release_sigint ();
585 return;
586 }
587
588 terminal_prepped = 0;
589
590 release_sigint ();
591#endif /* !__GO32__ */
592}
593\f
594/* **************************************************************** */
595/* */
596/* Bogus Flow Control */
597/* */
598/* **************************************************************** */
599
600int
601rl_restart_output (count, key)
602 int count, key;
603{
604 int fildes = fileno (rl_outstream);
605#if defined (TIOCSTART)
606#if defined (apollo)
607 ioctl (&fildes, TIOCSTART, 0);
608#else
609 ioctl (fildes, TIOCSTART, 0);
610#endif /* apollo */
611
612#else /* !TIOCSTART */
613# if defined (TERMIOS_TTY_DRIVER)
614# if defined (__ksr1__)
615 if (ksrflow)
616 {
617 ksrflow = 0;
618 tcflow (fildes, TCOON);
619 }
620# else /* !ksr1 */
621 tcflow (fildes, TCOON); /* Simulate a ^Q. */
622# endif /* !ksr1 */
623# else /* !TERMIOS_TTY_DRIVER */
624# if defined (TCXONC)
625 ioctl (fildes, TCXONC, TCOON);
626# endif /* TCXONC */
627# endif /* !TERMIOS_TTY_DRIVER */
628#endif /* !TIOCSTART */
629
630 return 0;
631}
632
633int
634rl_stop_output (count, key)
635 int count, key;
636{
637 int fildes = fileno (rl_instream);
638
639#if defined (TIOCSTOP)
640# if defined (apollo)
641 ioctl (&fildes, TIOCSTOP, 0);
642# else
643 ioctl (fildes, TIOCSTOP, 0);
644# endif /* apollo */
645#else /* !TIOCSTOP */
646# if defined (TERMIOS_TTY_DRIVER)
647# if defined (__ksr1__)
648 ksrflow = 1;
649# endif /* ksr1 */
650 tcflow (fildes, TCOOFF);
651# else
652# if defined (TCXONC)
653 ioctl (fildes, TCXONC, TCOON);
654# endif /* TCXONC */
655# endif /* !TERMIOS_TTY_DRIVER */
656#endif /* !TIOCSTOP */
657
658 return 0;
659}
660
661/* **************************************************************** */
662/* */
663/* Default Key Bindings */
664/* */
665/* **************************************************************** */
666void
667rltty_set_default_bindings (kmap)
668 Keymap kmap;
669{
670 TIOTYPE ttybuff;
671 int tty = fileno (rl_instream);
672
673#if defined (NEW_TTY_DRIVER)
674
675#define SET_SPECIAL(sc, func) \
676 do \
677 { \
678 int ic; \
679 ic = sc; \
680 if (ic != -1 && kmap[ic].type == ISFUNC) \
681 kmap[ic].function = func; \
682 } \
683 while (0)
684
685 if (get_tty_settings (tty, &ttybuff) == 0)
686 {
687 if (ttybuff.flags & SGTTY_SET)
688 {
689 SET_SPECIAL (ttybuff.sgttyb.sg_erase, rl_rubout);
690 SET_SPECIAL (ttybuff.sgttyb.sg_kill, rl_unix_line_discard);
691 }
692
693# if defined (TIOCGLTC)
694 if (ttybuff.flags & LTCHARS_SET)
695 {
696 SET_SPECIAL (ttybuff.ltchars.t_werasc, rl_unix_word_rubout);
697 SET_SPECIAL (ttybuff.ltchars.t_lnextc, rl_quoted_insert);
698 }
699# endif /* TIOCGLTC */
700 }
701
702#else /* !NEW_TTY_DRIVER */
703
704#define SET_SPECIAL(sc, func) \
705 do \
706 { \
707 unsigned char uc; \
708 uc = ttybuff.c_cc[sc]; \
709 if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC) \
710 kmap[uc].function = func; \
711 } \
712 while (0)
713
714 if (get_tty_settings (tty, &ttybuff) == 0)
715 {
716 SET_SPECIAL (VERASE, rl_rubout);
717 SET_SPECIAL (VKILL, rl_unix_line_discard);
718
719# if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER)
720 SET_SPECIAL (VLNEXT, rl_quoted_insert);
721# endif /* VLNEXT && TERMIOS_TTY_DRIVER */
722
723# if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER)
724 SET_SPECIAL (VWERASE, rl_unix_word_rubout);
725# endif /* VWERASE && TERMIOS_TTY_DRIVER */
726 }
727#endif /* !NEW_TTY_DRIVER */
728}
This page took 0.049858 seconds and 4 git commands to generate.