This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.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 (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)
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 (SHELL) && 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 #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
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   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
219 static int
220 set_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
258 static void
259 prepare_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
358 static 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
366 static void
367 rltty_warning (msg)
368      char *msg;
369 {
370   fprintf (stderr, "readline: warning: %s\n", msg);
371 }
372
373 #if defined (_AIX)
374 void
375 setopost(tp)
376 TIOTYPE *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
386 static int
387 get_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
424 static int
425 set_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
457 static void
458 prepare_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. */
520 void
521 rl_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. */
563 void
564 rl_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
600 int
601 rl_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
633 int
634 rl_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 /* **************************************************************** */
666 void
667 rltty_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 }