* src/fileio.c:
[bpt/emacs.git] / src / sysdep.c
index 95ad90c..4e9631d 100644 (file)
@@ -1,13 +1,14 @@
 /* Interfaces to system-dependent kernel and library entries.
    Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1999, 2000, 2001,
-                 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+                 2002, 2003, 2004, 2005, 2006, 2007, 2008
+                 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,9 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -33,12 +32,6 @@ Boston, MA 02110-1301, USA.  */
 /* Including stdlib.h isn't necessarily enough to get srandom
    declared, e.g. without __USE_XOPEN_EXTENDED with glibc 2.  */
 #ifdef HAVE_RANDOM
-#if 0 /* It turns out that defining _OSF_SOURCE in osf5-0.h gets
-        random prototyped as returning `int'.  It looks to me as
-        though the best way to DTRT is to prefer the rand48 functions
-        (per libc.info).  -- fx */
-extern long int random P_ ((void));
-#endif
 #if 0 /* Don't prototype srandom; it takes an unsigned argument on
         some systems, and an unsigned long on others, like FreeBSD
         4.1.  */
@@ -46,16 +39,13 @@ extern void srandom P_ ((unsigned int));
 #endif
 #endif
 
-#include "blockinput.h"
-
-#ifdef MAC_OS8
-#include <sys/param.h>
-
-#ifndef subprocesses
-/* Nonzero means delete a process right away if it exits (process.c).  */
-static int delete_exited_processes;
+/* The w32 build defines select stuff in w32.h, which is included by
+   sys/select.h (included below).   */
+#ifndef WINDOWSNT
+#include "sysselect.h"
 #endif
-#endif  /* MAC_OS8 */
+
+#include "blockinput.h"
 
 #ifdef WINDOWSNT
 #define read sys_read
@@ -145,26 +135,16 @@ extern int errno;
 #include "systty.h"
 #include "syswait.h"
 
-#ifdef BROKEN_TIOCGWINSZ
-#undef TIOCGWINSZ
-#undef TIOCSWINSZ
-#endif
-
-#if defined (USG) || defined (DGUX)
+#if defined (USG)
 #include <sys/utsname.h>
-#ifndef MEMORY_IN_STRING_H
 #include <memory.h>
-#endif
-#if defined (TIOCGWINSZ) || defined (ISC4_0)
-#ifdef NEED_SIOCTL
-#include <sys/sioctl.h>
-#endif
+#if defined (TIOCGWINSZ)
 #ifdef NEED_PTEM_H
 #include <sys/stream.h>
 #include <sys/ptem.h>
 #endif
-#endif /* TIOCGWINSZ or ISC4_0 */
-#endif /* USG or DGUX */
+#endif /* TIOCGWINSZ */
+#endif /* USG */
 
 extern int quit_char;
 
@@ -176,13 +156,19 @@ extern int quit_char;
 #include "termopts.h"
 #include "dispextern.h"
 #include "process.h"
+#include "cm.h"  /* for reset_sys_modes */
+
+/* For serial_configure and serial_open.  */
+extern Lisp_Object QCport, QCspeed, QCprocess;
+extern Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven;
+extern Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary;
 
 #ifdef WINDOWSNT
 #include <direct.h>
 /* In process.h which conflicts with the local copy.  */
 #define _P_WAIT 0
-int _CRTAPI1 _spawnlp (int, const char *, const char *, ...);
-int _CRTAPI1 _getpid (void);
+int _cdecl _spawnlp (int, const char *, const char *, ...);
+int _cdecl _getpid (void);
 extern char *getwd (char *);
 #endif
 
@@ -212,10 +198,6 @@ struct utimbuf {
 #define LPASS8 0
 #endif
 
-#ifdef BSD4_1
-#define LNOFLSH 0100000
-#endif
-
 static int baud_convert[] =
 #ifdef BAUD_CONVERT
   BAUD_CONVERT;
@@ -239,18 +221,8 @@ static int baud_convert[] =
 
 int emacs_ospeed;
 
-/* The file descriptor for Emacs's input terminal.
-   Under Unix, this is normally zero except when using X;
-   under VMS, we place the input channel number here.  */
-int input_fd;
-
 void croak P_ ((char *)) NO_RETURN;
 
-#ifdef AIXHFT
-void hft_init ();
-void hft_reset ();
-#endif
-
 /* Temporary used by `sigblock' when defined in terms of signprocmask.  */
 
 SIGMASKTYPE sigprocmask_set;
@@ -331,16 +303,7 @@ get_current_dir_name ()
 #endif
 
 \f
-/* Specify a different file descriptor for further input operations.  */
-
-void
-change_input_fd (fd)
-     int fd;
-{
-  input_fd = fd;
-}
-
-/* Discard pending input on descriptor input_fd.  */
+/* Discard pending input on all input descriptors.  */
 
 void
 discard_tty_input ()
@@ -351,54 +314,49 @@ discard_tty_input ()
   if (noninteractive)
     return;
 
-  /* Discarding input is not safe when the input could contain
-     replies from the X server.  So don't do it.  */
-  if (read_socket_hook)
-    return;
-
 #ifdef VMS
   end_kbd_input ();
-  SYS$QIOW (0, input_fd, IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
+  SYS$QIOW (0, fileno (CURTTY()->input), IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
            &buf.main, 0, 0, terminator_mask, 0, 0);
   queue_kbd_input ();
 #else /* not VMS */
-#ifdef APOLLO
-  {
-    int zero = 0;
-    ioctl (input_fd, TIOCFLUSH, &zero);
-  }
-#else /* not Apollo */
 #ifdef MSDOS    /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
   while (dos_keyread () != -1)
     ;
 #else /* not MSDOS */
-  EMACS_GET_TTY (input_fd, &buf);
-  EMACS_SET_TTY (input_fd, &buf, 0);
+  {
+    struct tty_display_info *tty;
+    for (tty = tty_list; tty; tty = tty->next)
+      {
+        if (tty->input)         /* Is the device suspended? */
+          {
+            EMACS_GET_TTY (fileno (tty->input), &buf);
+            EMACS_SET_TTY (fileno (tty->input), &buf, 0);
+          }
+      }
+  }
 #endif /* not MSDOS */
-#endif /* not Apollo */
 #endif /* not VMS */
 #endif /* not WINDOWSNT */
 }
 
+\f
 #ifdef SIGTSTP
 
 /* Arrange for character C to be read as the next input from
-   the terminal.  */
+   the terminal.
+   XXX What if we have multiple ttys?
+*/
 
 void
-#ifdef PROTOTYPES
 stuff_char (char c)
-#else
-stuff_char (c)
-     char c;
-#endif
 {
-  if (read_socket_hook)
+  if (! FRAME_TERMCAP_P (SELECTED_FRAME ()))
     return;
 
 /* Should perhaps error if in batch mode */
 #ifdef TIOCSTI
-  ioctl (input_fd, TIOCSTI, &c);
+  ioctl (fileno (CURTTY()->input), TIOCSTI, &c);
 #else /* no TIOCSTI */
   error ("Cannot stuff terminal input characters in this version of Unix");
 #endif /* no TIOCSTI */
@@ -407,22 +365,19 @@ stuff_char (c)
 #endif /* SIGTSTP */
 \f
 void
-init_baud_rate ()
+init_baud_rate (int fd)
 {
   if (noninteractive)
     emacs_ospeed = 0;
   else
     {
-#ifdef INIT_BAUD_RATE
-      INIT_BAUD_RATE ();
-#else
 #ifdef DOS_NT
     emacs_ospeed = 15;
 #else  /* not DOS_NT */
 #ifdef VMS
       struct sensemode sg;
 
-      SYS$QIOW (0, input_fd, IO$_SENSEMODE, &sg, 0, 0,
+      SYS$QIOW (0, fd, IO$_SENSEMODE, &sg, 0, 0,
                &sg.class, 12, 0, 0, 0, 0 );
       emacs_ospeed = sg.xmit_baud;
 #else /* not VMS */
@@ -430,36 +385,30 @@ init_baud_rate ()
       struct termios sg;
 
       sg.c_cflag = B9600;
-      tcgetattr (input_fd, &sg);
+      tcgetattr (fd, &sg);
       emacs_ospeed = cfgetospeed (&sg);
-#if defined (USE_GETOBAUD) && defined (getobaud)
-      /* m88k-motorola-sysv3 needs this (ghazi@noc.rutgers.edu) 9/1/94. */
-      if (emacs_ospeed == 0)
-        emacs_ospeed = getobaud (sg.c_cflag);
-#endif
 #else /* neither VMS nor TERMIOS */
 #ifdef HAVE_TERMIO
       struct termio sg;
 
       sg.c_cflag = B9600;
 #ifdef HAVE_TCATTR
-      tcgetattr (input_fd, &sg);
+      tcgetattr (fd, &sg);
 #else
-      ioctl (input_fd, TCGETA, &sg);
+      ioctl (fd, TCGETA, &sg);
 #endif
       emacs_ospeed = sg.c_cflag & CBAUD;
 #else /* neither VMS nor TERMIOS nor TERMIO */
       struct sgttyb sg;
 
       sg.sg_ospeed = B9600;
-      if (ioctl (input_fd, TIOCGETP, &sg) < 0)
+      if (ioctl (fd, TIOCGETP, &sg) < 0)
        abort ();
       emacs_ospeed = sg.sg_ospeed;
 #endif /* not HAVE_TERMIO */
 #endif /* not HAVE_TERMIOS */
 #endif /* not VMS */
 #endif /* not DOS_NT */
-#endif /* not INIT_BAUD_RATE */
     }
 
   baud_rate = (emacs_ospeed < sizeof baud_convert / sizeof baud_convert[0]
@@ -468,6 +417,7 @@ init_baud_rate ()
     baud_rate = 1200;
 }
 
+\f
 /*ARGSUSED*/
 void
 set_exclusive_use (fd)
@@ -516,7 +466,7 @@ wait_for_termination (pid)
       status = SYS$FORCEX (&pid, 0, 0);
       break;
 #else /* not VMS */
-#if defined (BSD_SYSTEM) || (defined (HPUX) && !defined (HPUX_5))
+#if defined (BSD_SYSTEM) || defined (HPUX)
       /* Note that kill returns -1 even if the process is just a zombie now.
         But inevitably a SIGCHLD interrupt should be generated
         and child_sig will do wait3 and make the process go away. */
@@ -536,11 +486,6 @@ wait_for_termination (pid)
       else
        sigpause (SIGEMPTYMASK);
 #else /* not BSD_SYSTEM, and not HPUX version >= 6 */
-#if defined (UNIPLUS)
-      if (0 > kill (pid, 0))
-       break;
-      wait (0);
-#else /* neither BSD_SYSTEM nor UNIPLUS: random sysV */
 #ifdef POSIX_SIGNALS    /* would this work for GNU/Linux as well? */
       sigblock (sigmask (SIGCHLD));
       errno = 0;
@@ -574,23 +519,15 @@ wait_for_termination (pid)
 #endif /* not WINDOWSNT */
 #endif /* not HAVE_SYSV_SIGPAUSE */
 #endif /* not POSIX_SIGNALS */
-#endif /* not UNIPLUS */
 #endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
 #endif /* not VMS */
 #else /* not subprocesses */
 #if __DJGPP__ > 1
       break;
 #else /* not __DJGPP__ > 1 */
-#ifndef BSD4_1
       if (kill (pid, 0) < 0)
        break;
       wait (0);
-#else /* BSD4_1 */
-      int status;
-      status = wait (0);
-      if (status == pid || status == -1)
-       break;
-#endif /* BSD4_1 */
 #endif /* not __DJGPP__ > 1*/
 #endif /* not subprocesses */
     }
@@ -644,8 +581,15 @@ child_setup_tty (out)
   s.main.c_oflag |= OPOST;     /* Enable output postprocessing */
   s.main.c_oflag &= ~ONLCR;    /* Disable map of NL to CR-NL on output */
 #ifdef NLDLY
+  /* http://lists.gnu.org/archive/html/emacs-devel/2008-05/msg00406.html
+     Some versions of GNU Hurd do not have FFDLY?  */
+#ifdef FFDLY
   s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
                                /* No output delays */
+#else
+  s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY);
+                               /* No output delays */
+#endif
 #endif
   s.main.c_lflag &= ~ECHO;     /* Disable echo */
   s.main.c_lflag |= ISIG;      /* Enable signals */
@@ -727,16 +671,6 @@ child_setup_tty (out)
 
   EMACS_SET_TTY (out, &s, 0);
 
-#ifdef BSD4_1
-  if (interrupt_input)
-    reset_sigio ();
-#endif /* BSD4_1 */
-#ifdef RTU
-  {
-    int zero = 0;
-    ioctl (out, FIOASYNC, &zero);
-  }
-#endif /* RTU */
 #endif /* not DOS_NT */
 }
 #endif /* not VMS */
@@ -825,7 +759,6 @@ sys_suspend ()
 
 /* Fork a subshell.  */
 
-#ifndef MAC_OS8
 void
 sys_subshell ()
 {
@@ -961,7 +894,6 @@ sys_subshell ()
   synch_process_alive = 0;
 #endif /* !VMS */
 }
-#endif /* !MAC_OS8 */
 
 static void
 save_signal_handlers (saved_handlers)
@@ -986,118 +918,90 @@ restore_signal_handlers (saved_handlers)
     }
 }
 \f
-#ifdef F_SETFL
-
-int old_fcntl_flags;
-
+#ifndef SIGIO
+/* If SIGIO is broken, don't do anything. */
 void
-init_sigio (fd)
-     int fd;
+init_sigio (int fd)
 {
-#ifdef FASYNC
-  old_fcntl_flags = fcntl (fd, F_GETFL, 0) & ~FASYNC;
-  fcntl (fd, F_SETFL, old_fcntl_flags | FASYNC);
-#endif
-  interrupts_deferred = 0;
 }
 
 void
-reset_sigio ()
+reset_sigio (int fd)
 {
-  unrequest_sigio ();
 }
 
-#ifdef FASYNC          /* F_SETFL does not imply existence of FASYNC */
-
 void
-request_sigio ()
+request_sigio (void)
 {
-  if (noninteractive || read_socket_hook)
-    return;
-
-#ifdef SIGWINCH
-  sigunblock (sigmask (SIGWINCH));
-#endif
-  fcntl (input_fd, F_SETFL, old_fcntl_flags | FASYNC);
-
-  interrupts_deferred = 0;
 }
 
 void
-unrequest_sigio ()
+unrequest_sigio (void)
 {
-  if (noninteractive || read_socket_hook)
-    return;
-
-#ifdef SIGWINCH
-  sigblock (sigmask (SIGWINCH));
-#endif
-  fcntl (input_fd, F_SETFL, old_fcntl_flags);
-  interrupts_deferred = 1;
 }
 
-#else /* no FASYNC */
-#ifdef STRIDE          /* Stride doesn't have FASYNC - use FIOASYNC */
+#else
+#ifdef F_SETFL
+
+int old_fcntl_flags[MAXDESC];
 
 void
-request_sigio ()
+init_sigio (fd)
+     int fd;
 {
-  int on = 1;
-
-  if (noninteractive || read_socket_hook)
-    return;
-
-  ioctl (input_fd, FIOASYNC, &on);
+#ifdef FASYNC
+  old_fcntl_flags[fd] = fcntl (fd, F_GETFL, 0) & ~FASYNC;
+  fcntl (fd, F_SETFL, old_fcntl_flags[fd] | FASYNC);
+#endif
   interrupts_deferred = 0;
 }
 
 void
-unrequest_sigio ()
+reset_sigio (fd)
+     int fd;
 {
-  int off = 0;
-
-  if (noninteractive || read_socket_hook)
-    return;
-
-  ioctl (input_fd, FIOASYNC, &off);
-  interrupts_deferred = 1;
+#ifdef FASYNC
+  fcntl (fd, F_SETFL, old_fcntl_flags[fd]);
+#endif
 }
 
-#else /* not FASYNC, not STRIDE */
-
-#ifdef _CX_UX
-
-#include <termios.h>
+#ifdef FASYNC          /* F_SETFL does not imply existence of FASYNC */
+/* XXX Uhm, FASYNC is not used anymore here. */
+/* XXX Yeah, but you need it for SIGIO, don't you? */
 
 void
 request_sigio ()
 {
-  int on = 1;
-  sigset_t st;
-
-  if (noninteractive || read_socket_hook)
+  if (noninteractive)
     return;
 
-  sigemptyset (&st);
-  sigaddset (&st, SIGIO);
-  ioctl (input_fd, FIOASYNC, &on);
+#ifdef SIGWINCH
+  sigunblock (sigmask (SIGWINCH));
+#endif
+  sigunblock (sigmask (SIGIO));
+
   interrupts_deferred = 0;
-  sigprocmask (SIG_UNBLOCK, &st, (sigset_t *)0);
 }
 
 void
-unrequest_sigio ()
-{
-  int off = 0;
+unrequest_sigio (void)
+{ 
+  if (noninteractive)
+    return;
 
-  if (noninteractive || read_socket_hook)
+#if 0 /* XXX What's wrong with blocking SIGIO under X?  */
+  if (x_display_list)
     return;
+#endif
 
-  ioctl (input_fd, FIOASYNC, &off);
+#ifdef SIGWINCH
+  sigblock (sigmask (SIGWINCH));
+#endif
+  sigblock (sigmask (SIGIO));
   interrupts_deferred = 1;
 }
 
-#else /* ! _CX_UX */
+#else /* no FASYNC */
 #ifndef MSDOS
 
 void
@@ -1119,10 +1023,9 @@ unrequest_sigio ()
 }
 
 #endif /* MSDOS */
-#endif /* _CX_UX */
-#endif /* STRIDE */
 #endif /* FASYNC */
 #endif /* F_SETFL */
+#endif /* SIGIO */
 \f
 /* Saving and restoring the process group of Emacs's terminal.  */
 
@@ -1145,30 +1048,39 @@ unrequest_sigio ()
    the tty's pgroup just like any other terminal setting.  If
    inherited_group was not the tty's pgroup, then we'll get a
    SIGTTmumble when we try to change the tty's pgroup, and a CONT if
-   it goes foreground in the future, which is what should happen.  */
+   it goes foreground in the future, which is what should happen.
+
+   This variable is initialized in emacs.c.  */
 int inherited_pgroup;
 
-/* Split off the foreground process group to Emacs alone.
-   When we are in the foreground, but not started in our own process
-   group, redirect the TTY to point to our own process group.  We need
-   to be in our own process group to receive SIGIO properly.  */
-void
-narrow_foreground_group ()
+/* Split off the foreground process group to Emacs alone.  When we are
+   in the foreground, but not started in our own process group,
+   redirect the tty device handle FD to point to our own process
+   group.  We need to be in our own process group to receive SIGIO
+   properly.  */
+static void
+narrow_foreground_group (int fd)
 {
   int me = getpid ();
 
   setpgrp (0, inherited_pgroup);
+#if 0
+  /* XXX inherited_pgroup should not be zero here, but GTK seems to
+     mess this up. */
+  if (! inherited_pgroup)
+    abort ();                   /* Should not happen. */
+#endif
   if (inherited_pgroup != me)
-    EMACS_SET_TTY_PGRP (input_fd, &me);
+      EMACS_SET_TTY_PGRP (fd, &me); /* XXX This only works on the controlling tty. */
   setpgrp (0, me);
 }
 
 /* Set the tty to our original foreground group.  */
-void
-widen_foreground_group ()
+static void
+widen_foreground_group (int fd)
 {
   if (inherited_pgroup != getpid ())
-    EMACS_SET_TTY_PGRP (input_fd, &inherited_pgroup);
+    EMACS_SET_TTY_PGRP (fd, &inherited_pgroup);
   setpgrp (0, inherited_pgroup);
 }
 
@@ -1326,40 +1238,20 @@ emacs_set_tty (fd, settings, flushp)
 }
 
 \f
-/* The initial tty mode bits */
-struct emacs_tty old_tty;
-
-/* 1 if we have been through init_sys_modes.  */
-int term_initted;
 
-/* 1 if outer tty status has been recorded.  */
-int old_tty_valid;
-
-#ifdef BSD4_1
-/* BSD 4.1 needs to keep track of the lmode bits in order to start
-   sigio.  */
-int lmode;
-#endif
-
-#ifndef F_SETOWN_BUG
 #ifdef F_SETOWN
-int old_fcntl_owner;
+int old_fcntl_owner[MAXDESC];
 #endif /* F_SETOWN */
-#endif /* F_SETOWN_BUG */
 
 /* This may also be defined in stdio,
    but if so, this does no harm,
    and using the same name avoids wasting the other one's space.  */
 
-#ifdef nec_ews_svr4
-extern char *_sobuf ;
-#else
 #if defined (USG) || defined (DGUX)
 unsigned char _sobuf[BUFSIZ+8];
 #else
 char _sobuf[BUFSIZ];
 #endif
-#endif
 
 #ifdef HAVE_LTCHARS
 static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1};
@@ -1368,8 +1260,22 @@ static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1};
 static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
 #endif
 
+/* Initialize the terminal mode on all tty devices that are currently
+   open. */
+
 void
-init_sys_modes ()
+init_all_sys_modes (void)
+{
+  struct tty_display_info *tty;
+  for (tty = tty_list; tty; tty = tty->next)
+    init_sys_modes (tty);
+}
+
+/* Initialize the terminal mode on the given tty device. */
+
+void
+init_sys_modes (tty_out)
+     struct tty_display_info *tty_out;
 {
   struct emacs_tty tty;
 
@@ -1385,6 +1291,9 @@ init_sys_modes ()
   if (noninteractive)
     return;
 
+  if (!tty_out->output)
+    return;                     /* The tty is suspended. */
+  
 #ifdef VMS
   if (!input_ef)
     input_ef = get_kbd_event_flag ();
@@ -1415,269 +1324,256 @@ init_sys_modes ()
 #ifndef VMS4_4
   sys_access_reinit ();
 #endif
-#endif /* not VMS */
+#endif /* VMS */
 
 #ifdef BSD_PGRPS
-  if (! read_socket_hook && EQ (Vwindow_system, Qnil))
-    narrow_foreground_group ();
+#if 0
+  /* read_socket_hook is not global anymore.  I think doing this
+     unconditionally will not cause any problems. */
+  if (! read_socket_hook && EQ (Vinitial_window_system, Qnil))
 #endif
-
-#ifdef HAVE_WINDOW_SYSTEM
-  /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
-     needs the initialization code below.  */
-  if (!read_socket_hook && EQ (Vwindow_system, Qnil))
+    narrow_foreground_group (fileno (tty_out->input));
 #endif
-    {
-      EMACS_GET_TTY (input_fd, &old_tty);
 
-      old_tty_valid = 1;
+  if (! tty_out->old_tty)
+    tty_out->old_tty = (struct emacs_tty *) xmalloc (sizeof (struct emacs_tty));
+      
+  EMACS_GET_TTY (fileno (tty_out->input), tty_out->old_tty);
 
-      tty = old_tty;
+  tty = *tty_out->old_tty;
 
 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
-      XSETINT (Vtty_erase_char, old_tty.main.c_cc[VERASE]);
+  XSETINT (Vtty_erase_char, tty.main.c_cc[VERASE]);
 
-#ifdef DGUX
-      /* This allows meta to be sent on 8th bit.  */
-      tty.main.c_iflag &= ~INPCK;      /* don't check input for parity */
-#endif
-      tty.main.c_iflag |= (IGNBRK);    /* Ignore break condition */
-      tty.main.c_iflag &= ~ICRNL;      /* Disable map of CR to NL on input */
+  tty.main.c_iflag |= (IGNBRK);        /* Ignore break condition */
+  tty.main.c_iflag &= ~ICRNL;  /* Disable map of CR to NL on input */
 #ifdef INLCR  /* I'm just being cautious,
                 since I can't check how widespread INLCR is--rms.  */
-      tty.main.c_iflag &= ~INLCR;      /* Disable map of NL to CR on input */
+  tty.main.c_iflag &= ~INLCR;  /* Disable map of NL to CR on input */
 #endif
 #ifdef ISTRIP
-      tty.main.c_iflag &= ~ISTRIP;     /* don't strip 8th bit on input */
+  tty.main.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */
 #endif
-      tty.main.c_lflag &= ~ECHO;       /* Disable echo */
-      tty.main.c_lflag &= ~ICANON;     /* Disable erase/kill processing */
+  tty.main.c_lflag &= ~ECHO;   /* Disable echo */
+  tty.main.c_lflag &= ~ICANON; /* Disable erase/kill processing */
 #ifdef IEXTEN
-      tty.main.c_lflag &= ~IEXTEN;     /* Disable other editing characters.  */
+  tty.main.c_lflag &= ~IEXTEN; /* Disable other editing characters.  */
 #endif
-      tty.main.c_lflag |= ISIG;        /* Enable signals */
-      if (flow_control)
-       {
-         tty.main.c_iflag |= IXON;     /* Enable start/stop output control */
+  tty.main.c_lflag |= ISIG;    /* Enable signals */
+  if (tty_out->flow_control)
+    {
+      tty.main.c_iflag |= IXON;        /* Enable start/stop output control */
 #ifdef IXANY
-         tty.main.c_iflag &= ~IXANY;
+      tty.main.c_iflag &= ~IXANY;
 #endif /* IXANY */
-       }
-      else
-       tty.main.c_iflag &= ~IXON;      /* Disable start/stop output control */
-      tty.main.c_oflag &= ~ONLCR;      /* Disable map of NL to CR-NL
-                                          on output */
-      tty.main.c_oflag &= ~TAB3;       /* Disable tab expansion */
+    }
+  else
+    tty.main.c_iflag &= ~IXON; /* Disable start/stop output control */
+  tty.main.c_oflag &= ~ONLCR;  /* Disable map of NL to CR-NL
+                                   on output */
+  tty.main.c_oflag &= ~TAB3;   /* Disable tab expansion */
 #ifdef CS8
-      if (meta_key)
-       {
-         tty.main.c_cflag |= CS8;      /* allow 8th bit on input */
-         tty.main.c_cflag &= ~PARENB;/* Don't check parity */
-       }
+  if (tty_out->meta_key)
+    {
+      tty.main.c_cflag |= CS8; /* allow 8th bit on input */
+      tty.main.c_cflag &= ~PARENB;/* Don't check parity */
+    }
 #endif
+  if (tty_out->input == stdin)
+    {
       tty.main.c_cc[VINTR] = quit_char;        /* C-g (usually) gives SIGINT */
       /* Set up C-g for both SIGQUIT and SIGINT.
-        We don't know which we will get, but we handle both alike
-        so which one it really gives us does not matter.  */
+         We don't know which we will get, but we handle both alike
+         so which one it really gives us does not matter.  */
       tty.main.c_cc[VQUIT] = quit_char;
-      tty.main.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */
-      tty.main.c_cc[VTIME] = 0;        /* no matter how long that takes.  */
+    }
+  else
+    {
+      /* We normally don't get interrupt or quit signals from tty
+         devices other than our controlling terminal; therefore,
+         we must handle C-g as normal input.  Unfortunately, this
+         means that the interrupt and quit feature must be
+         disabled on secondary ttys, or we would not even see the
+         keypress.
+         
+         Note that even though emacsclient could have special code
+         to pass SIGINT to Emacs, we should _not_ enable
+         interrupt/quit keys for emacsclient frames.  This means
+         that we can't break out of loops in C code from a
+         secondary tty frame, but we can always decide what
+         display the C-g came from, which is more important from a
+         usability point of view.  (Consider the case when two
+         people work together using the same Emacs instance.)  */
+      tty.main.c_cc[VINTR] = CDISABLE;
+      tty.main.c_cc[VQUIT] = CDISABLE;
+    }
+  tty.main.c_cc[VMIN] = 1;     /* Input should wait for at least 1 char */
+  tty.main.c_cc[VTIME] = 0;    /* no matter how long that takes.  */
 #ifdef VSWTCH
-      tty.main.c_cc[VSWTCH] = CDISABLE;        /* Turn off shell layering use
+  tty.main.c_cc[VSWTCH] = CDISABLE;    /* Turn off shell layering use
                                           of C-z */
 #endif /* VSWTCH */
-
+  
 #if defined (mips) || defined (HAVE_TCATTR)
 #ifdef VSUSP
-      tty.main.c_cc[VSUSP] = CDISABLE; /* Turn off mips handling of C-z.  */
+  tty.main.c_cc[VSUSP] = CDISABLE;     /* Turn off mips handling of C-z.  */
 #endif /* VSUSP */
 #ifdef V_DSUSP
-      tty.main.c_cc[V_DSUSP] = CDISABLE; /* Turn off mips handling of C-y.  */
+  tty.main.c_cc[V_DSUSP] = CDISABLE; /* Turn off mips handling of C-y.  */
 #endif /* V_DSUSP */
 #ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP.  */
-      tty.main.c_cc[VDSUSP] = CDISABLE;
+  tty.main.c_cc[VDSUSP] = CDISABLE;
 #endif /* VDSUSP */
 #ifdef VLNEXT
-      tty.main.c_cc[VLNEXT] = CDISABLE;
+  tty.main.c_cc[VLNEXT] = CDISABLE;
 #endif /* VLNEXT */
 #ifdef VREPRINT
-      tty.main.c_cc[VREPRINT] = CDISABLE;
+  tty.main.c_cc[VREPRINT] = CDISABLE;
 #endif /* VREPRINT */
 #ifdef VWERASE
-      tty.main.c_cc[VWERASE] = CDISABLE;
+  tty.main.c_cc[VWERASE] = CDISABLE;
 #endif /* VWERASE */
 #ifdef VDISCARD
-      tty.main.c_cc[VDISCARD] = CDISABLE;
+  tty.main.c_cc[VDISCARD] = CDISABLE;
 #endif /* VDISCARD */
 
-      if (flow_control)
-       {
+  if (tty_out->flow_control)
+    {
 #ifdef VSTART
-         tty.main.c_cc[VSTART] = '\021';
+      tty.main.c_cc[VSTART] = '\021';
 #endif /* VSTART */
 #ifdef VSTOP
-         tty.main.c_cc[VSTOP] = '\023';
+      tty.main.c_cc[VSTOP] = '\023';
 #endif /* VSTOP */
-       }
-      else
-       {
+    }
+  else
+    {
 #ifdef VSTART
-         tty.main.c_cc[VSTART] = CDISABLE;
+      tty.main.c_cc[VSTART] = CDISABLE;
 #endif /* VSTART */
 #ifdef VSTOP
-         tty.main.c_cc[VSTOP] = CDISABLE;
+      tty.main.c_cc[VSTOP] = CDISABLE;
 #endif /* VSTOP */
-       }
+    }
 #endif /* mips or HAVE_TCATTR */
 
-#ifdef SET_LINE_DISCIPLINE
-      /* Need to explicitly request TERMIODISC line discipline or
-         Ultrix's termios does not work correctly.  */
-      tty.main.c_line = SET_LINE_DISCIPLINE;
-#endif
 #ifdef AIX
 #ifndef IBMR2AIX
-      /* AIX enhanced edit loses NULs, so disable it.  */
-      tty.main.c_line = 0;
-      tty.main.c_iflag &= ~ASCEDIT;
+  /* AIX enhanced edit loses NULs, so disable it.  */
+  tty.main.c_line = 0;
+  tty.main.c_iflag &= ~ASCEDIT;
 #else
-      tty.main.c_cc[VSTRT] = CDISABLE;
-      tty.main.c_cc[VSTOP] = CDISABLE;
-      tty.main.c_cc[VSUSP] = CDISABLE;
-      tty.main.c_cc[VDSUSP] = CDISABLE;
+  tty.main.c_cc[VSTRT] = CDISABLE;
+  tty.main.c_cc[VSTOP] = CDISABLE;
+  tty.main.c_cc[VSUSP] = CDISABLE;
+  tty.main.c_cc[VDSUSP] = CDISABLE;
 #endif /* IBMR2AIX */
-      if (flow_control)
-       {
+  if (tty_out->flow_control)
+    {
 #ifdef VSTART
-         tty.main.c_cc[VSTART] = '\021';
+      tty.main.c_cc[VSTART] = '\021';
 #endif /* VSTART */
 #ifdef VSTOP
-         tty.main.c_cc[VSTOP] = '\023';
+      tty.main.c_cc[VSTOP] = '\023';
 #endif /* VSTOP */
-       }
-      /* Also, PTY overloads NUL and BREAK.
-        don't ignore break, but don't signal either, so it looks like NUL.
-        This really serves a purpose only if running in an XTERM window
-        or via TELNET or the like, but does no harm elsewhere.  */
-      tty.main.c_iflag &= ~IGNBRK;
-      tty.main.c_iflag &= ~BRKINT;
+    }
+  /* Also, PTY overloads NUL and BREAK.
+     don't ignore break, but don't signal either, so it looks like NUL.
+     This really serves a purpose only if running in an XTERM window
+     or via TELNET or the like, but does no harm elsewhere.  */
+  tty.main.c_iflag &= ~IGNBRK;
+  tty.main.c_iflag &= ~BRKINT;
 #endif
 #else /* if not HAVE_TERMIO */
 #ifdef VMS
-      tty.main.tt_char |= TT$M_NOECHO;
-      if (meta_key)
-       tty.main.tt_char |= TT$M_EIGHTBIT;
-      if (flow_control)
-       tty.main.tt_char |= TT$M_TTSYNC;
-      else
-       tty.main.tt_char &= ~TT$M_TTSYNC;
-      tty.main.tt2_char |= TT2$M_PASTHRU | TT2$M_XON;
+  tty.main.tt_char |= TT$M_NOECHO;
+  if (meta_key)
+    tty.main.tt_char |= TT$M_EIGHTBIT;
+  if (tty_out->flow_control)
+    tty.main.tt_char |= TT$M_TTSYNC;
+  else
+    tty.main.tt_char &= ~TT$M_TTSYNC;
+  tty.main.tt2_char |= TT2$M_PASTHRU | TT2$M_XON;
 #else /* not VMS (BSD, that is) */
 #ifndef DOS_NT
-      XSETINT (Vtty_erase_char, tty.main.sg_erase);
-      tty.main.sg_flags &= ~(ECHO | CRMOD | XTABS);
-      if (meta_key)
-       tty.main.sg_flags |= ANYP;
-      tty.main.sg_flags |= interrupt_input ? RAW : CBREAK;
+  XSETINT (Vtty_erase_char, tty.main.sg_erase);
+  tty.main.sg_flags &= ~(ECHO | CRMOD | XTABS);
+  if (meta_key)
+    tty.main.sg_flags |= ANYP;
+  tty.main.sg_flags |= interrupt_input ? RAW : CBREAK;
 #endif /* not DOS_NT */
 #endif /* not VMS (BSD, that is) */
 #endif /* not HAVE_TERMIO */
 
-      /* If going to use CBREAK mode, we must request C-g to interrupt
-        and turn off start and stop chars, etc.  If not going to use
-        CBREAK mode, do this anyway so as to turn off local flow
-        control for user coming over network on 4.2; in this case,
-        only t_stopc and t_startc really matter.  */
+  /* If going to use CBREAK mode, we must request C-g to interrupt
+     and turn off start and stop chars, etc.  If not going to use
+     CBREAK mode, do this anyway so as to turn off local flow
+     control for user coming over network on 4.2; in this case,
+     only t_stopc and t_startc really matter.  */
 #ifndef HAVE_TERMIO
 #ifdef HAVE_TCHARS
-      /* Note: if not using CBREAK mode, it makes no difference how we
-        set this */
-      tty.tchars = new_tchars;
-      tty.tchars.t_intrc = quit_char;
-      if (flow_control)
-       {
-         tty.tchars.t_startc = '\021';
-         tty.tchars.t_stopc = '\023';
-       }
-
-      tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | old_tty.lmode;
-#ifdef ultrix
-      /* Under Ultrix 4.2a, leaving this out doesn't seem to hurt
-        anything, and leaving it in breaks the meta key.  Go figure.  */
-      tty.lmode &= ~LLITOUT;
-#endif
-
-#ifdef BSD4_1
-      lmode = tty.lmode;
-#endif
-
+  /* Note: if not using CBREAK mode, it makes no difference how we
+     set this */
+  tty.tchars = new_tchars;
+  tty.tchars.t_intrc = quit_char;
+  if (tty_out->flow_control)
+    {
+      tty.tchars.t_startc = '\021';
+      tty.tchars.t_stopc = '\023';
+    }
+  
+  tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | tty_out->old_tty.lmode;
+  
 #endif /* HAVE_TCHARS */
 #endif /* not HAVE_TERMIO */
 
 #ifdef HAVE_LTCHARS
-      tty.ltchars = new_ltchars;
+  tty.ltchars = new_ltchars;
 #endif /* HAVE_LTCHARS */
 #ifdef MSDOS   /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
-      if (!term_initted)
-       internal_terminal_init ();
-      dos_ttraw ();
+  if (!tty_out->term_initted)
+    internal_terminal_init ();
+  dos_ttraw ();
 #endif
 
-      EMACS_SET_TTY (input_fd, &tty, 0);
+  EMACS_SET_TTY (fileno (tty_out->input), &tty, 0);
 
-      /* This code added to insure that, if flow-control is not to be used,
-        we have an unlocked terminal at the start. */
+  /* This code added to insure that, if flow-control is not to be used,
+     we have an unlocked terminal at the start. */
 
 #ifdef TCXONC
-      if (!flow_control) ioctl (input_fd, TCXONC, 1);
+  if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TCXONC, 1);
 #endif
-#ifndef APOLLO
 #ifdef TIOCSTART
-      if (!flow_control) ioctl (input_fd, TIOCSTART, 0);
-#endif
+  if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TIOCSTART, 0);
 #endif
 
-#if defined (HAVE_TERMIOS) || defined (HPUX9)
+#if defined (HAVE_TERMIOS) || defined (HPUX)
 #ifdef TCOON
-      if (!flow_control) tcflow (input_fd, TCOON);
+  if (!tty_out->flow_control) tcflow (fileno (tty_out->input), TCOON);
 #endif
 #endif
 
-#ifdef AIXHFT
-      hft_init ();
-#ifdef IBMR2AIX
-      {
-       /* IBM's HFT device usually thinks a ^J should be LF/CR.  We need it
-          to be only LF.  This is the way that is done. */
-       struct termio tty;
-
-       if (ioctl (1, HFTGETID, &tty) != -1)
-         write (1, "\033[20l", 5);
-      }
-#endif
-#endif /* AIXHFT */
-
 #ifdef VMS
 /*  Appears to do nothing when in PASTHRU mode.
-      SYS$QIOW (0, input_fd, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
+      SYS$QIOW (0, fileno (tty_out->input), IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
                interrupt_signal, oob_chars, 0, 0, 0, 0);
 */
-      queue_kbd_input (0);
+  queue_kbd_input (0);
 #endif /* VMS */
-    }
 
 #ifdef F_SETFL
-#ifndef F_SETOWN_BUG
 #ifdef F_GETOWN                /* F_SETFL does not imply existence of F_GETOWN */
-  if (interrupt_input
-      && ! read_socket_hook && EQ (Vwindow_system, Qnil))
+  if (interrupt_input)
     {
-      old_fcntl_owner = fcntl (input_fd, F_GETOWN, 0);
-      fcntl (input_fd, F_SETOWN, getpid ());
-      init_sigio (input_fd);
+      old_fcntl_owner[fileno (tty_out->input)] =
+        fcntl (fileno (tty_out->input), F_GETOWN, 0);
+      fcntl (fileno (tty_out->input), F_SETOWN, getpid ());
+      init_sigio (fileno (tty_out->input));
 #ifdef HAVE_GPM
-      if (term_gpm)
+      if (gpm_tty == tty_out)
        {
+         /* Arrange for mouse events to give us SIGIO signals.  */
          fcntl (gpm_fd, F_SETOWN, getpid ());
          fcntl (gpm_fd, F_SETFL, fcntl (gpm_fd, F_GETFL, 0) | O_NONBLOCK);
          init_sigio (gpm_fd);
@@ -1685,14 +1581,8 @@ init_sys_modes ()
 #endif /* HAVE_GPM */
     }
 #endif /* F_GETOWN */
-#endif /* F_SETOWN_BUG */
 #endif /* F_SETFL */
 
-#ifdef BSD4_1
-  if (interrupt_input)
-    init_sigio (input_fd);
-#endif
-
 #ifdef VMS  /* VMS sometimes has this symbol but lacks setvbuf.  */
 #undef _IOFBF
 #endif
@@ -1700,53 +1590,57 @@ init_sys_modes ()
   /* This symbol is defined on recent USG systems.
      Someone says without this call USG won't really buffer the file
      even with a call to setbuf. */
-  setvbuf (stdout, (char *) _sobuf, _IOFBF, sizeof _sobuf);
+  setvbuf (tty_out->output, (char *) _sobuf, _IOFBF, sizeof _sobuf);
 #else
-  setbuf (stdout, (char *) _sobuf);
-#endif
-#ifdef HAVE_WINDOW_SYSTEM
-  /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
-     needs the initialization code below.  */
-  if (EQ (Vwindow_system, Qnil)
-#ifndef WINDOWSNT
-      /* When running in tty mode on NT/Win95, we have a read_socket
-        hook, but still need the rest of the initialization code below.  */
-      && (! read_socket_hook)
+  setbuf (tty_out->output, (char *) _sobuf);
 #endif
-      )
-#endif
-    set_terminal_modes ();
 
-  if (!term_initted
-      && FRAMEP (Vterminal_frame)
-      && FRAME_TERMCAP_P (XFRAME (Vterminal_frame)))
-    init_frame_faces (XFRAME (Vterminal_frame));
+  if (tty_out->terminal->set_terminal_modes_hook)
+    tty_out->terminal->set_terminal_modes_hook (tty_out->terminal);
+
+  if (!tty_out->term_initted)
+    {
+      Lisp_Object tail, frame;
+      FOR_EACH_FRAME (tail, frame)
+        {
+          /* XXX This needs to be revised. */
+          if (FRAME_TERMCAP_P (XFRAME (frame))
+              && FRAME_TTY (XFRAME (frame)) == tty_out)
+            init_frame_faces (XFRAME (frame));
+        }
+    }
 
-  if (term_initted && no_redraw_on_reenter)
+  if (tty_out->term_initted && no_redraw_on_reenter)
     {
+      /* XXX This seems wrong on multi-tty. */
       if (display_completed)
        direct_output_forward_char (0);
     }
   else
     {
+      Lisp_Object tail, frame;
       frame_garbaged = 1;
-      if (FRAMEP (Vterminal_frame))
-       FRAME_GARBAGED_P (XFRAME (Vterminal_frame)) = 1;
+      FOR_EACH_FRAME (tail, frame)
+        {
+          if (FRAME_TERMCAP_P (XFRAME (frame))
+              && FRAME_TTY (XFRAME (frame)) == tty_out)
+            FRAME_GARBAGED_P (XFRAME (frame)) = 1;
+        }
     }
 
-  term_initted = 1;
+  tty_out->term_initted = 1;
 }
 
 /* Return nonzero if safe to use tabs in output.
    At the time this is called, init_sys_modes has not been done yet.  */
 
 int
-tabs_safe_p ()
+tabs_safe_p (int fd)
 {
-  struct emacs_tty tty;
+  struct emacs_tty etty;
 
-  EMACS_GET_TTY (input_fd, &tty);
-  return EMACS_TTY_TABS_OK (&tty);
+  EMACS_GET_TTY (fd, &etty);
+  return EMACS_TTY_TABS_OK (&etty);
 }
 \f
 /* Get terminal size from system.
@@ -1754,8 +1648,7 @@ tabs_safe_p ()
    We store 0 if there's no valid information.  */
 
 void
-get_frame_size (widthp, heightp)
-     int *widthp, *heightp;
+get_tty_size (int fd, int *widthp, int *heightp)
 {
 
 #ifdef TIOCGWINSZ
@@ -1763,7 +1656,7 @@ get_frame_size (widthp, heightp)
   /* BSD-style.  */
   struct winsize size;
 
-  if (ioctl (input_fd, TIOCGWINSZ, &size) == -1)
+  if (ioctl (fd, TIOCGWINSZ, &size) == -1)
     *widthp = *heightp = 0;
   else
     {
@@ -1777,7 +1670,7 @@ get_frame_size (widthp, heightp)
   /* SunOS - style.  */
   struct ttysize size;
 
-  if (ioctl (input_fd, TIOCGSIZE, &size) == -1)
+  if (ioctl (fd, TIOCGSIZE, &size) == -1)
     *widthp = *heightp = 0;
   else
     {
@@ -1809,7 +1702,6 @@ get_frame_size (widthp, heightp)
   *widthp = 0;
   *heightp = 0;
 #endif
-
 #endif /* not VMS */
 #endif /* not SunOS-style */
 #endif /* not BSD-style */
@@ -1853,97 +1745,92 @@ set_window_size (fd, height, width)
 }
 
 \f
-/* Prepare the terminal for exiting Emacs; move the cursor to the
-   bottom of the frame, turn off interrupt-driven I/O, etc.  */
+
+/* Prepare all terminal devices for exiting Emacs. */
+
 void
-reset_sys_modes ()
+reset_all_sys_modes (void)
 {
-  struct frame *sf;
+  struct tty_display_info *tty;
+  for (tty = tty_list; tty; tty = tty->next)
+    reset_sys_modes (tty);
+}
 
+/* Prepare the terminal for closing it; move the cursor to the
+   bottom of the frame, turn off interrupt-driven I/O, etc.  */
+
+void
+reset_sys_modes (tty_out)
+     struct tty_display_info *tty_out;
+{
   if (noninteractive)
     {
       fflush (stdout);
       return;
     }
-  if (!term_initted)
+  if (!tty_out->term_initted)
     return;
-#ifdef HAVE_WINDOW_SYSTEM
-  /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
-     needs the clean-up code below.  */
-  if (!EQ (Vwindow_system, Qnil)
-#ifndef WINDOWSNT
-      /* When running in tty mode on NT/Win95, we have a read_socket
-        hook, but still need the rest of the clean-up code below.  */
-      || read_socket_hook
-#endif
-      )
-    return;
-#endif
-  sf = SELECTED_FRAME ();
-  cursor_to (FRAME_LINES (sf) - 1, 0);
-  clear_end_of_line (FRAME_COLS (sf));
-  /* clear_end_of_line may move the cursor */
-  cursor_to (FRAME_LINES (sf) - 1, 0);
-#if defined (IBMR2AIX) && defined (AIXHFT)
-  {
-    /* HFT devices normally use ^J as a LF/CR.  We forced it to
-       do the LF only.  Now, we need to reset it. */
-    struct termio tty;
 
-    if (ioctl (1, HFTGETID, &tty) != -1)
-      write (1, "\033[20h", 5);
-  }
-#endif
+  if (!tty_out->output)
+    return;                     /* The tty is suspended. */
+  
+  /* Go to and clear the last line of the terminal. */
+
+  cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
+  
+  /* Code adapted from tty_clear_end_of_line. */
+  if (tty_out->TS_clr_line)
+    {
+      emacs_tputs (tty_out, tty_out->TS_clr_line, 1, cmputc);
+    }
+  else
+    {                  /* have to do it the hard way */
+      int i;
+      tty_turn_off_insert (tty_out);
+      
+      for (i = curX (tty_out); i < FrameCols (tty_out) - 1; i++)
+        {
+          fputc (' ', tty_out->output);
+        }
+    }
+  
+  cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
+  fflush (tty_out->output);
+  
+  if (tty_out->terminal->reset_terminal_modes_hook)
+    tty_out->terminal->reset_terminal_modes_hook (tty_out->terminal);
 
-  reset_terminal_modes ();
-  fflush (stdout);
 #ifdef BSD_SYSTEM
-#ifndef BSD4_1
   /* Avoid possible loss of output when changing terminal modes.  */
-  fsync (fileno (stdout));
-#endif
+  fsync (fileno (tty_out->output));
 #endif
 
 #ifdef F_SETFL
-#ifndef F_SETOWN_BUG
 #ifdef F_SETOWN                /* F_SETFL does not imply existence of F_SETOWN */
   if (interrupt_input)
     {
-      reset_sigio ();
-      fcntl (input_fd, F_SETOWN, old_fcntl_owner);
+      reset_sigio (fileno (tty_out->input));
+      fcntl (fileno (tty_out->input), F_SETOWN,
+             old_fcntl_owner[fileno (tty_out->input)]);
     }
 #endif /* F_SETOWN */
-#endif /* F_SETOWN_BUG */
 #ifdef O_NDELAY
-  fcntl (input_fd, F_SETFL, fcntl (input_fd, F_GETFL, 0) & ~O_NDELAY);
+  fcntl (fileno (tty_out->input), F_SETFL,
+         fcntl (fileno (tty_out->input), F_GETFL, 0) & ~O_NDELAY);
 #endif
 #endif /* F_SETFL */
-#ifdef BSD4_1
-  if (interrupt_input)
-    reset_sigio ();
-#endif /* BSD4_1 */
 
-  if (old_tty_valid)
-    while (EMACS_SET_TTY (input_fd, &old_tty, 0) < 0 && errno == EINTR)
+  if (tty_out->old_tty)
+    while (EMACS_SET_TTY (fileno (tty_out->input),
+                          tty_out->old_tty, 0) < 0 && errno == EINTR)
       ;
 
 #ifdef MSDOS   /* Demacs 1.1.2 91/10/20 Manabu Higashida */
   dos_ttcooked ();
 #endif
 
-#ifdef SET_LINE_DISCIPLINE
-  /* Ultrix's termios *ignores* any line discipline except TERMIODISC.
-     A different old line discipline is therefore not restored, yet.
-     Restore the old line discipline by hand.  */
-  ioctl (0, TIOCSETD, &old_tty.main.c_line);
-#endif
-
-#ifdef AIXHFT
-  hft_reset ();
-#endif
-
 #ifdef BSD_PGRPS
-  widen_foreground_group ();
+  widen_foreground_group (fileno (tty_out->input));
 #endif
 }
 \f
@@ -1986,14 +1873,6 @@ setup_pty (fd)
   }
 #endif
 #endif
-#ifdef IBMRTAIX
-  /* On AIX, the parent gets SIGHUP when a pty attached child dies.  So, we */
-  /* ignore SIGHUP once we've started a child on a pty.  Note that this may */
-  /* cause EMACS not to die when it should, i.e., when its own controlling  */
-  /* tty goes away.  I've complained to the AIX developers, and they may    */
-  /* change this behavior, but I'm not going to hold my breath.             */
-  signal (SIGHUP, SIG_IGN);
-#endif
 }
 #endif /* HAVE_PTYS */
 \f
@@ -2008,9 +1887,9 @@ init_vms_input ()
 {
   int status;
 
-  if (input_fd == 0)
+  if (fileno (CURTTY ()->input)) == 0)
     {
-      status = SYS$ASSIGN (&input_dsc, &input_fd, 0, 0);
+      status = SYS$ASSIGN (&input_dsc, &fileno (CURTTY ()->input)), 0, 0);
       if (! (status & 1))
        LIB$STOP (status);
     }
@@ -2021,7 +1900,7 @@ init_vms_input ()
 void
 stop_vms_input ()
 {
-  return SYS$DASSGN (input_fd);
+  return SYS$DASSGN (fileno (CURTTY ()->input)));
 }
 
 short input_buffer;
@@ -2037,7 +1916,7 @@ queue_kbd_input ()
 
   waiting_for_ast = 0;
   stop_input = 0;
-  status = SYS$QIO (0, input_fd, IO$_READVBLK,
+  status = SYS$QIO (0, fileno (CURTTY()->input), IO$_READVBLK,
                    &input_iosb, kbd_input_ast, 1,
                    &input_buffer, 1, 0, terminator_mask, 0, 0);
 }
@@ -2154,7 +2033,7 @@ end_kbd_input ()
 #endif
   if (LIB$AST_IN_PROG ())  /* Don't wait if suspending from kbd_buffer_store_event! */
     {
-      SYS$CANCEL (input_fd);
+      SYS$CANCEL (fileno (CURTTY()->input));
       return;
     }
 
@@ -2163,7 +2042,7 @@ end_kbd_input ()
   SYS$CLREF (input_ef);
   waiting_for_ast = 1;
   stop_input = 1;
-  SYS$CANCEL (input_fd);
+  SYS$CANCEL (fileno (CURTTY()->input));
   SYS$SETAST (1);
   SYS$WAITFR (input_ef);
   waiting_for_ast = 0;
@@ -2225,7 +2104,8 @@ init_sigio (fd)
   request_sigio ();
 }
 
-reset_sigio ()
+reset_sigio (fd)
+     int fd;
 {
   unrequest_sigio ();
 }
@@ -2277,13 +2157,8 @@ start_of_text ()
 #ifdef TEXT_START
   return ((char *) TEXT_START);
 #else
-#ifdef GOULD
-  extern csrt ();
-  return ((char *) csrt);
-#else /* not GOULD */
   extern int _start ();
   return ((char *) _start);
-#endif /* GOULD */
 #endif /* TEXT_START */
 }
 #endif /* not HAVE_TEXT_START */
@@ -2344,20 +2219,14 @@ start_of_data ()
 /* init_system_name sets up the string for the Lisp function
    system-name to return. */
 
-#ifdef BSD4_1
-#include <whoami.h>
-#endif
-
 extern Lisp_Object Vsystem_name;
 
-#ifndef BSD4_1
 #ifndef VMS
 #ifdef HAVE_SOCKETS
 #include <sys/socket.h>
 #include <netdb.h>
 #endif /* HAVE_SOCKETS */
 #endif /* not VMS */
-#endif /* not BSD4_1 */
 
 #ifdef TRY_AGAIN
 #ifndef HAVE_H_ERRNO
@@ -2368,9 +2237,6 @@ extern int h_errno;
 void
 init_system_name ()
 {
-#ifdef BSD4_1
-  Vsystem_name = build_string (sysname);
-#else
 #ifdef VMS
   char *sp, *end;
   if ((sp = egetenv ("SYS$NODE")) == 0)
@@ -2413,10 +2279,50 @@ init_system_name ()
 #endif /* not CANNOT_DUMP */
     if (! index (hostname, '.'))
       {
-       struct hostent *hp;
        int count;
+#ifdef HAVE_GETADDRINFO
+        struct addrinfo *res;
+        struct addrinfo hints;
+        int ret;
+
+        memset (&hints, 0, sizeof(hints));
+        hints.ai_socktype = SOCK_STREAM;
+        hints.ai_flags = AI_CANONNAME;
+
+       for (count = 0;; count++)
+         {
+            if ((ret = getaddrinfo (hostname, NULL, &hints, &res)) == 0
+                || ret != EAI_AGAIN)
+              break;
+
+            if (count >= 5)
+             break;
+           Fsleep_for (make_number (1), Qnil);
+         }
+
+        if (ret == 0)
+          {
+            struct addrinfo *it = res;
+            while (it)
+              {
+                char *fqdn = it->ai_canonname;
+                if (fqdn && index (fqdn, '.')
+                    && strcmp (fqdn, "localhost.localdomain") != 0)
+                  break;
+                it = it->ai_next;
+              }
+            if (it)
+              {
+                hostname = alloca (strlen (it->ai_canonname) + 1);
+                strcpy (hostname, it->ai_canonname);
+              }
+            freeaddrinfo (res);
+          }
+#else /* !HAVE_GETADDRINFO */
+        struct hostent *hp;
        for (count = 0;; count++)
          {
+
 #ifdef TRY_AGAIN
            h_errno = 0;
 #endif
@@ -2424,11 +2330,14 @@ init_system_name ()
 #ifdef TRY_AGAIN
            if (! (hp == 0 && h_errno == TRY_AGAIN))
 #endif
+
              break;
+
            if (count >= 5)
              break;
            Fsleep_for (make_number (1), Qnil);
          }
+
        if (hp)
          {
            char *fqdn = (char *) hp->h_name;
@@ -2462,6 +2371,7 @@ init_system_name ()
              }
 #endif
          }
+#endif /* !HAVE_GETADDRINFO */
       }
 #endif /* HAVE_SOCKETS */
   /* We used to try using getdomainname here,
@@ -2507,7 +2417,6 @@ init_system_name ()
   Vsystem_name = build_string (hostname);
 #endif /* HAVE_GETHOSTNAME */
 #endif /* VMS */
-#endif /* BSD4_1 */
   {
     unsigned char *p;
     for (p = SDATA (Vsystem_name); *p; p++)
@@ -2518,7 +2427,7 @@ init_system_name ()
 \f
 #ifndef MSDOS
 #ifndef VMS
-#if !defined (HAVE_SELECT) || defined (BROKEN_SELECT_NON_X)
+#if !defined (HAVE_SELECT)
 
 #include "sysselect.h"
 #undef select
@@ -2549,11 +2458,7 @@ SIGTYPE
 select_alarm ()
 {
   select_alarmed = 1;
-#ifdef BSD4_1
-  sigrelse (SIGALRM);
-#else /* not BSD4_1 */
   signal (SIGALRM, SIG_IGN);
-#endif /* not BSD4_1 */
   SIGNAL_THREAD_CHECK (SIGALRM);
   if (read_alarm_should_throw)
     longjmp (read_alarm_throw, 1);
@@ -2567,7 +2472,9 @@ sys_select (nfds, rfds, wfds, efds, timeout)
      SELECT_TYPE *rfds, *wfds, *efds;
      EMACS_TIME *timeout;
 {
-  int ravail = 0;
+  /* XXX This needs to be updated for multi-tty support.  Is there
+     anybody who needs to emulate select these days?  */ 
+ int ravail = 0;
   SELECT_TYPE orfds;
   int timeoutval;
   int *local_timeout;
@@ -2582,7 +2489,7 @@ sys_select (nfds, rfds, wfds, efds, timeout)
 #if defined (HAVE_SELECT) && defined (HAVE_X_WINDOWS)
   /* If we're using X, then the native select will work; we only need the
      emulation for non-X usage.  */
-  if (!NILP (Vwindow_system))
+  if (!NILP (Vinitial_window_system))
     return select (nfds, rfds, wfds, efds, timeout);
 #endif
   timeoutval = timeout ? EMACS_SECS (*timeout) : 100000;
@@ -2699,6 +2606,8 @@ sys_select (nfds, rfds, wfds, efds, timeout)
 void
 read_input_waiting ()
 {
+  /* XXX This needs to be updated for multi-tty support.  Is there
+     anybody who needs to emulate select these days?  */
   int nread, i;
   extern int quit_char;
 
@@ -2752,96 +2661,14 @@ read_input_waiting ()
     }
 }
 
+#if !defined (HAVE_SELECT)
+#define select sys_select
+#endif
+
 #endif /* not HAVE_SELECT */
 #endif /* not VMS */
 #endif /* not MSDOS */
 \f
-#ifdef BSD4_1
-void
-init_sigio (fd)
-     int fd;
-{
-  if (noninteractive)
-    return;
-  lmode = LINTRUP | lmode;
-  ioctl (fd, TIOCLSET, &lmode);
-}
-
-void
-reset_sigio ()
-{
-  if (noninteractive)
-    return;
-  lmode = ~LINTRUP & lmode;
-  ioctl (0, TIOCLSET, &lmode);
-}
-
-void
-request_sigio ()
-{
-  if (noninteractive)
-    return;
-  sigrelse (SIGTINT);
-
-  interrupts_deferred = 0;
-}
-
-void
-unrequest_sigio ()
-{
-  if (noninteractive)
-    return;
-  sighold (SIGTINT);
-
-  interrupts_deferred = 1;
-}
-
-/* still inside #ifdef BSD4_1 */
-#ifdef subprocesses
-
-int sigheld; /* Mask of held signals */
-
-void
-sigholdx (signum)
-     int signum;
-{
-  sigheld |= sigbit (signum);
-  sighold (signum);
-}
-
-void
-sigisheld (signum)
-     int signum;
-{
-  sigheld |= sigbit (signum);
-}
-
-void
-sigunhold (signum)
-     int signum;
-{
-  sigheld &= ~sigbit (signum);
-  sigrelse (signum);
-}
-
-void
-sigfree ()    /* Free all held signals */
-{
-  int i;
-  for (i = 0; i < NSIG; i++)
-    if (sigheld & sigbit (i))
-      sigrelse (i);
-  sigheld = 0;
-}
-
-int
-sigbit (i)
-{
-  return 1 << (i - 1);
-}
-#endif /* subprocesses */
-#endif /* BSD4_1 */
-\f
 /* POSIX signals support - DJB */
 /* Anyone with POSIX signals should have ANSI C declarations */
 
@@ -3171,16 +2998,6 @@ get_random ()
   return val & ((1L << VALBITS) - 1);
 }
 \f
-#ifdef WRONG_NAME_INSQUE
-
-insque (q,p)
-     caddr_t q,p;
-{
-  _insque (q,p);
-}
-
-#endif
-\f
 #ifdef VMS
 
 #ifdef getenv
@@ -3229,7 +3046,7 @@ sys_getenv (name)
 #undef abort
 sys_abort ()
 {
-  reset_sys_modes ();
+  reset_all_sys_modes ();
   LIB$SIGNAL (SS$_DEBUG);
 }
 #endif /* abort */
@@ -3310,11 +3127,6 @@ emacs_open (path, oflag, mode)
 {
   register int rtnval;
 
-#ifdef BSD4_1
-  if (oflag & O_CREAT)
-    return creat (path, mode);
-#endif
-
   while ((rtnval = open (path, oflag, mode)) == -1
         && (errno == EINTR))
     QUIT;
@@ -3328,6 +3140,15 @@ emacs_close (fd)
   int did_retry = 0;
   register int rtnval;
 
+#if defined (MAC_OSX) && defined (HAVE_CARBON)
+  {
+    extern int mac_try_close_socket P_ ((int));
+
+    if (mac_try_close_socket (fd))
+      return 0;
+  }
+#endif
+
   while ((rtnval = close (fd)) == -1
         && (errno == EINTR))
     did_retry = 1;
@@ -3378,6 +3199,8 @@ emacs_write (fildes, buf, nbyte)
                 be truncated if you hit C-g in the middle of it.  --Stef  */
              if (interrupt_input_pending)
                handle_async_input ();
+              if (pending_atimers)
+                do_pending_atimers ();
 #endif
              continue;
            }
@@ -3556,7 +3379,7 @@ croak (badfunc)
      char *badfunc;
 {
   printf ("%s not yet implemented\r\n", badfunc);
-  reset_sys_modes ();
+  reset_all_sys_modes ();
   exit (1);
 }
 
@@ -5143,7 +4966,7 @@ croak (badfunc)
      char *badfunc;
 {
   printf ("%s not yet implemented\r\n", badfunc);
-  reset_sys_modes ();
+  reset_all_sys_modes ();
   exit (1);
 }
 
@@ -5161,128 +4984,6 @@ srandom (seed)
 }
 #endif /* VMS */
 \f
-#ifdef AIXHFT
-
-/* Called from init_sys_modes.  */
-void
-hft_init ()
-{
-  int junk;
-
-  /* If we're not on an HFT we shouldn't do any of this.  We determine
-     if we are on an HFT by trying to get an HFT error code.  If this
-     call fails, we're not on an HFT. */
-#ifdef IBMR2AIX
-  if (ioctl (0, HFQERROR, &junk) < 0)
-    return;
-#else /* not IBMR2AIX */
-  if (ioctl (0, HFQEIO, 0) < 0)
-    return;
-#endif /* not IBMR2AIX */
-
-  /* On AIX the default hft keyboard mapping uses backspace rather than delete
-     as the rubout key's ASCII code.  Here this is changed.  The bug is that
-     there's no way to determine the old mapping, so in reset_sys_modes
-     we need to assume that the normal map had been present.  Of course, this
-     code also doesn't help if on a terminal emulator which doesn't understand
-     HFT VTD's.  */
-  {
-    struct hfbuf buf;
-    struct hfkeymap keymap;
-
-    buf.hf_bufp = (char *)&keymap;
-    buf.hf_buflen = sizeof (keymap);
-    keymap.hf_nkeys = 2;
-    keymap.hfkey[0].hf_kpos = 15;
-    keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
-#ifdef IBMR2AIX
-    keymap.hfkey[0].hf_keyidh = '<';
-#else /* not IBMR2AIX */
-    keymap.hfkey[0].hf_page = '<';
-#endif /* not IBMR2AIX */
-    keymap.hfkey[0].hf_char = 127;
-    keymap.hfkey[1].hf_kpos = 15;
-    keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
-#ifdef IBMR2AIX
-    keymap.hfkey[1].hf_keyidh = '<';
-#else /* not IBMR2AIX */
-    keymap.hfkey[1].hf_page = '<';
-#endif /* not IBMR2AIX */
-    keymap.hfkey[1].hf_char = 127;
-    hftctl (0, HFSKBD, &buf);
-  }
-  /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
-     at times.  */
-  line_ins_del_ok = char_ins_del_ok = 0;
-}
-
-/* Reset the rubout key to backspace.  */
-
-void
-hft_reset ()
-{
-  struct hfbuf buf;
-  struct hfkeymap keymap;
-  int junk;
-
-#ifdef IBMR2AIX
-  if (ioctl (0, HFQERROR, &junk) < 0)
-    return;
-#else /* not IBMR2AIX */
-  if (ioctl (0, HFQEIO, 0) < 0)
-    return;
-#endif /* not IBMR2AIX */
-
-  buf.hf_bufp = (char *)&keymap;
-  buf.hf_buflen = sizeof (keymap);
-  keymap.hf_nkeys = 2;
-  keymap.hfkey[0].hf_kpos = 15;
-  keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
-#ifdef IBMR2AIX
-  keymap.hfkey[0].hf_keyidh = '<';
-#else /* not IBMR2AIX */
-  keymap.hfkey[0].hf_page = '<';
-#endif /* not IBMR2AIX */
-  keymap.hfkey[0].hf_char = 8;
-  keymap.hfkey[1].hf_kpos = 15;
-  keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
-#ifdef IBMR2AIX
-  keymap.hfkey[1].hf_keyidh = '<';
-#else /* not IBMR2AIX */
-  keymap.hfkey[1].hf_page = '<';
-#endif /* not IBMR2AIX */
-  keymap.hfkey[1].hf_char = 8;
-  hftctl (0, HFSKBD, &buf);
-}
-
-#endif /* AIXHFT */
-
-#ifdef USE_DL_STUBS
-
-/* These are included on Sunos 4.1 when we do not use shared libraries.
-   X11 libraries may refer to these functions but (we hope) do not
-   actually call them.  */
-
-void *
-dlopen ()
-{
-  return 0;
-}
-
-void *
-dlsym ()
-{
-  return 0;
-}
-
-int
-dlclose ()
-{
-  return -1;
-}
-
-#endif /* USE_DL_STUBS */
-\f
 #ifndef BSTRING
 
 #ifndef bzero
@@ -5384,6 +5085,223 @@ strsignal (code)
   return signame;
 }
 #endif /* HAVE_STRSIGNAL */
+\f
+#ifdef HAVE_TERMIOS
+/* For make-serial-process  */
+int serial_open (char *port)
+{
+  int fd = -1;
+
+  fd = emacs_open ((char*) port,
+                  O_RDWR
+#ifdef O_NONBLOCK
+                  | O_NONBLOCK
+#else
+                  | O_NDELAY
+#endif
+#ifdef O_NOCTTY
+                  | O_NOCTTY
+#endif
+                  , 0);
+  if (fd < 0)
+    {
+      error ("Could not open %s: %s",
+            port, emacs_strerror (errno));
+    }
+#ifdef TIOCEXCL
+  ioctl (fd, TIOCEXCL, (char *) 0);
+#endif
+
+  return fd;
+}
+#endif /* TERMIOS  */
+
+#ifdef HAVE_TERMIOS
+
+#if !defined (HAVE_CFMAKERAW)
+/* Workaround for targets which are missing cfmakeraw.  */
+/* Pasted from man page.  */
+static void cfmakeraw (struct termios *termios_p)
+{
+    termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+    termios_p->c_oflag &= ~OPOST;
+    termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+    termios_p->c_cflag &= ~(CSIZE|PARENB);
+    termios_p->c_cflag |= CS8;
+}
+#endif /* !defined (HAVE_CFMAKERAW */
+
+#if !defined (HAVE_CFSETSPEED)
+/* Workaround for targets which are missing cfsetspeed.  */
+static int cfsetspeed (struct termios *termios_p, speed_t vitesse)
+{
+  return (cfsetispeed (termios_p, vitesse)
+         + cfsetospeed (termios_p, vitesse));
+}
+#endif
+
+/* For serial-process-configure  */
+void
+serial_configure (struct Lisp_Process *p,
+                     Lisp_Object contact)
+{
+  Lisp_Object childp2 = Qnil;
+  Lisp_Object tem = Qnil;
+  struct termios attr;
+  int err = -1;
+  char summary[4] = "???"; /* This usually becomes "8N1".  */
+
+  childp2 = Fcopy_sequence (p->childp);
+
+  /* Read port attributes and prepare default configuration.  */
+  err = tcgetattr (p->outfd, &attr);
+  if (err != 0)
+    error ("tcgetattr() failed: %s", emacs_strerror (errno));
+  cfmakeraw (&attr);
+#if defined (CLOCAL)
+  attr.c_cflag |= CLOCAL;
+#endif
+#if defined (CREAD)
+  attr.c_cflag | CREAD;
+#endif
+
+  /* Configure speed.  */
+  if (!NILP (Fplist_member (contact, QCspeed)))
+    tem = Fplist_get (contact, QCspeed);
+  else
+    tem = Fplist_get (p->childp, QCspeed);
+  CHECK_NUMBER (tem);
+  err = cfsetspeed (&attr, XINT (tem));
+  if (err != 0)
+    error ("cfsetspeed(%d) failed: %s", XINT (tem), emacs_strerror (errno));
+  childp2 = Fplist_put (childp2, QCspeed, tem);
+
+  /* Configure bytesize.  */
+  if (!NILP (Fplist_member (contact, QCbytesize)))
+    tem = Fplist_get (contact, QCbytesize);
+  else
+    tem = Fplist_get (p->childp, QCbytesize);
+  if (NILP (tem))
+    tem = make_number (8);
+  CHECK_NUMBER (tem);
+  if (XINT (tem) != 7 && XINT (tem) != 8)
+    error (":bytesize must be nil (8), 7, or 8");
+  summary[0] = XINT(tem) + '0';
+#if defined (CSIZE) && defined (CS7) && defined (CS8)
+  attr.c_cflag &= ~CSIZE;
+  attr.c_cflag |= ((XINT (tem) == 7) ? CS7 : CS8);
+#else
+  /* Don't error on bytesize 8, which should be set by cfmakeraw.  */
+  if (XINT (tem) != 8)
+    error ("Bytesize cannot be changed");
+#endif
+  childp2 = Fplist_put (childp2, QCbytesize, tem);
+
+  /* Configure parity.  */
+  if (!NILP (Fplist_member (contact, QCparity)))
+    tem = Fplist_get (contact, QCparity);
+  else
+    tem = Fplist_get (p->childp, QCparity);
+  if (!NILP (tem) && !EQ (tem, Qeven) && !EQ (tem, Qodd))
+    error (":parity must be nil (no parity), `even', or `odd'");
+#if defined (PARENB) && defined (PARODD) && defined (IGNPAR) && defined (INPCK)
+  attr.c_cflag &= ~(PARENB | PARODD);
+  attr.c_iflag &= ~(IGNPAR | INPCK);
+  if (NILP (tem))
+    {
+      summary[1] = 'N';
+    }
+  else if (EQ (tem, Qeven))
+    {
+      summary[1] = 'E';
+      attr.c_cflag |= PARENB;
+      attr.c_iflag |= (IGNPAR | INPCK);
+    }
+  else if (EQ (tem, Qodd))
+    {
+      summary[1] = 'O';
+      attr.c_cflag |= (PARENB | PARODD);
+      attr.c_iflag |= (IGNPAR | INPCK);
+    }
+#else
+  /* Don't error on no parity, which should be set by cfmakeraw.  */
+  if (!NILP (tem))
+    error ("Parity cannot be configured");
+#endif
+  childp2 = Fplist_put (childp2, QCparity, tem);
+
+  /* Configure stopbits.  */
+  if (!NILP (Fplist_member (contact, QCstopbits)))
+    tem = Fplist_get (contact, QCstopbits);
+  else
+    tem = Fplist_get (p->childp, QCstopbits);
+  if (NILP (tem))
+    tem = make_number (1);
+  CHECK_NUMBER (tem);
+  if (XINT (tem) != 1 && XINT (tem) != 2)
+    error (":stopbits must be nil (1 stopbit), 1, or 2");
+  summary[2] = XINT (tem) + '0';
+#if defined (CSTOPB)
+  attr.c_cflag &= ~CSTOPB;
+  if (XINT (tem) == 2)
+    attr.c_cflag |= CSTOPB;
+#else
+  /* Don't error on 1 stopbit, which should be set by cfmakeraw.  */
+  if (XINT (tem) != 1)
+    error ("Stopbits cannot be configured");
+#endif
+  childp2 = Fplist_put (childp2, QCstopbits, tem);
+
+  /* Configure flowcontrol.  */
+  if (!NILP (Fplist_member (contact, QCflowcontrol)))
+    tem = Fplist_get (contact, QCflowcontrol);
+  else
+    tem = Fplist_get (p->childp, QCflowcontrol);
+  if (!NILP (tem) && !EQ (tem, Qhw) && !EQ (tem, Qsw))
+    error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
+#if defined (CRTSCTS)
+  attr.c_cflag &= ~CRTSCTS;
+#endif
+#if defined (CNEW_RTSCTS)
+  attr.c_cflag &= ~CNEW_RTSCTS;
+#endif
+#if defined (IXON) && defined (IXOFF)
+  attr.c_iflag &= ~(IXON | IXOFF);
+#endif
+  if (NILP (tem))
+    {
+      /* Already configured.  */
+    }
+  else if (EQ (tem, Qhw))
+    {
+#if defined (CRTSCTS)
+      attr.c_cflag |= CRTSCTS;
+#elif defined (CNEW_RTSCTS)
+      attr.c_cflag |= CNEW_RTSCTS;
+#else
+      error ("Hardware flowcontrol (RTS/CTS) not supported");
+#endif
+    }
+  else if (EQ (tem, Qsw))
+    {
+#if defined (IXON) && defined (IXOFF)
+      attr.c_iflag |= (IXON | IXOFF);
+#else
+      error ("Software flowcontrol (XON/XOFF) not supported");
+#endif
+    }
+  childp2 = Fplist_put (childp2, QCflowcontrol, tem);
+
+  /* Activate configuration.  */
+  err = tcsetattr (p->outfd, TCSANOW, &attr);
+  if (err != 0)
+    error ("tcsetattr() failed: %s", emacs_strerror (errno));
+
+  childp2 = Fplist_put (childp2, QCsummary, build_string (summary));
+  p->childp = childp2;
+
+}
+#endif /* TERMIOS  */
 
 /* arch-tag: edb43589-4e09-4544-b325-978b5b121dcf
    (do not change this comment) */