This commit was generated by cvs2svn to track changes on a CVS vendor
[platform/upstream/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 (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 }