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