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