a5ef938b5c06e16a118c9a663d3f7aa51056b2f5
[platform/upstream/bash.git] / lib / 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 }