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