(DBL_MIN_REPLACEMENT): New macro.
[bpt/emacs.git] / src / sysdep.c
index bcc50e3..e8e1db8 100644 (file)
@@ -1,5 +1,5 @@
 /* Interfaces to system-dependent kernel and library entries.
-   Copyright (C) 1985, 86, 87, 88, 93, 94 Free Software Foundation, Inc.
+   Copyright (C) 1985, 86, 87, 88, 93, 94, 95 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -15,7 +15,8 @@ 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 
 #include <signal.h>
@@ -40,6 +41,13 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #undef read
 #undef write
 
+#ifdef WINDOWSNT
+#define read _read
+#define write _write
+#include <windows.h>
+extern int errno;
+#endif /* not WINDOWSNT */
+
 #ifndef close
 #define sys_close close
 #else 
@@ -59,16 +67,35 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #undef fwrite
 #endif
 
+#ifndef HAVE_H_ERRNO
+extern int h_errno;
+#endif
+
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <errno.h>
 
+/* Get _POSIX_VDISABLE, if it is available.  */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/* Get SI_SRPC_DOMAIN, if it is available.  */
+#ifdef HAVE_SYS_SYSTEMINFO_H
+#include <sys/systeminfo.h>
+#endif
+
 #ifdef MSDOS   /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
 #include <dos.h>
 #include "dosfns.h"
 #include "msdos.h"
 #include <sys/param.h>
+
+#if __DJGPP__ > 1
+extern int etext;
+extern unsigned start __asm__ ("start");
+#endif
 #endif
 
 extern int errno;
@@ -93,11 +120,11 @@ extern int errno;
 #ifndef RAB$C_BID
 #include <rab.h>
 #endif
-#define        MAXIOSIZE ( 32 * PAGESIZE )     /* Don't I/O more than 32 blocks at a time */
+#define MAXIOSIZE (32 * PAGESIZE) /* Don't I/O more than 32 blocks at a time */
 #endif /* VMS */
 
 #ifndef BSD4_1
-#ifdef BSD /* this is done this way to avoid defined (BSD) || defined (USG)
+#ifdef BSD_SYSTEM /* avoid writing defined (BSD_SYSTEM) || defined (USG)
              because the vms compiler doesn't grok `defined' */
 #include <fcntl.h>
 #endif
@@ -108,18 +135,10 @@ extern int errno;
 #endif
 #endif /* not 4.1 bsd */
 
-#ifdef BROKEN_FASYNC
-/* On some systems (DGUX comes to mind real fast) FASYNC causes
-   background writes to the terminal to stop all processes in the
-   process group when invoked under the csh (and probably any shell
-   with job control). This stops Emacs dead in its tracks when coming
-   up under X11. */
-#undef FASYNC
-#endif
-
 #ifndef MSDOS
 #include <sys/ioctl.h>
 #endif
+
 #include "systty.h"
 #include "syswait.h"
 
@@ -155,12 +174,38 @@ extern int quit_char;
 #include "dispextern.h"
 #include "process.h"
 
+#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);
+#endif
+
 #ifdef NONSYSTEM_DIR_LIBRARY
 #include "ndir.h"
 #endif /* NONSYSTEM_DIR_LIBRARY */
 
 #include "syssignal.h"
 #include "systime.h"
+#ifdef HAVE_UTIME_H
+#include <utime.h>
+#endif
+
+#ifndef HAVE_UTIMES
+#ifndef HAVE_STRUCT_UTIMBUF
+/* We want to use utime rather than utimes, but we couldn't find the
+   structure declaration.  We'll use the traditional one.  */
+struct utimbuf {
+  long actime;
+  long modtime;
+};
+#endif
+#endif
+
+#ifndef VFORK_RETURN_TYPE
+#define VFORK_RETURN_TYPE int
+#endif
 
 /* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits.  */
 #ifndef LPASS8
@@ -181,13 +226,23 @@ static int baud_convert[] =
   };
 #endif
 
+#if defined (HAVE_LIBNCURSES) && ! defined (NCURSES_OSPEED_T)
+extern short ospeed;
+#else
+#if defined (HAVE_TERMIOS_H) && defined (LINUX)
+#include <termios.h>
+/* HJL's version of libc is said to need this on the Alpha.
+   On the other hand, DEC OSF1 on the Alpha needs ospeed to be a short.  */
+extern speed_t ospeed;
+#else
 extern short ospeed;
+#endif
+#endif
 
 /* The file descriptor for Emacs's input terminal.
-   Under Unix, this is normaly zero except when using X;
-   under VMS, we place the input channel number here.
-   This allows us to write more code that works for both VMS and Unix.  */
-static int input_fd;
+   Under Unix, this is normally zero except when using X;
+   under VMS, we place the input channel number here.  */
+int input_fd;
 \f
 /* Specify a different file descriptor for further input operations.  */
 
@@ -202,6 +257,7 @@ change_input_fd (fd)
 
 discard_tty_input ()
 {
+#ifndef WINDOWSNT
   struct emacs_tty buf;
 
   if (noninteractive)
@@ -224,15 +280,16 @@ discard_tty_input ()
     ioctl (input_fd, TIOCFLUSH, &zero);
   }
 #else /* not Apollo */
-#ifdef MSDOS   /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
+#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);
 #endif /* not MSDOS */
 #endif /* not Apollo */
 #endif /* not VMS */
+#endif /* not WINDOWSNT */
 }
 
 #ifdef SIGTSTP
@@ -243,6 +300,9 @@ discard_tty_input ()
 stuff_char (c)
      char c;
 {
+  if (read_socket_hook)
+    return;
+
 /* Should perhaps error if in batch mode */
 #ifdef TIOCSTI
   ioctl (input_fd, TIOCSTI, &c);
@@ -259,9 +319,12 @@ init_baud_rate ()
     ospeed = 0;
   else
     {
-#ifdef MSDOS
-    ospeed = 15;
+#ifdef INIT_BAUD_RATE
+      INIT_BAUD_RATE ();
 #else
+#ifdef DOS_NT
+    ospeed = 15;
+#else  /* not DOS_NT */
 #ifdef VMS
       struct sensemode sg;
 
@@ -275,6 +338,11 @@ init_baud_rate ()
       sg.c_cflag = B9600;
       tcgetattr (input_fd, &sg);
       ospeed = cfgetospeed (&sg);
+#if defined (USE_GETOBAUD) && defined (getobaud)
+      /* m88k-motorola-sysv3 needs this (ghazi@noc.rutgers.edu) 9/1/94. */
+      if (ospeed == 0)
+        ospeed = getobaud (sg.c_cflag);
+#endif
 #else /* neither VMS nor TERMIOS */
 #ifdef HAVE_TERMIO
       struct termio sg;
@@ -296,11 +364,12 @@ init_baud_rate ()
 #endif /* not HAVE_TERMIO */
 #endif /* not HAVE_TERMIOS */
 #endif /* not VMS */
-#endif /* not MSDOS */
+#endif /* not DOS_NT */
+#endif /* not INIT_BAUD_RATE */
     }
    
   baud_rate = (ospeed < sizeof baud_convert / sizeof baud_convert[0]
-              ? baud_convert[ospeed] : 9600);
+              ? baud_convert[ospeed] : 9600);
   if (baud_rate == 0)
     baud_rate = 1200;
 }
@@ -319,7 +388,7 @@ set_exclusive_use (fd)
 
 wait_without_blocking ()
 {
-#ifdef BSD
+#ifdef BSD_SYSTEM
   wait3 (0, WNOHANG | WUNTRACED, 0);
 #else
   croak ("wait_without_blocking");
@@ -330,7 +399,7 @@ wait_without_blocking ()
 #endif /* not subprocesses */
 
 int wait_debugging;   /* Set nonzero to make following function work under dbx
-                        (at least for bsd).  */
+                        (at least for bsd).  */
 
 SIGTYPE
 wait_for_termination_signal ()
@@ -351,7 +420,7 @@ wait_for_termination (pid)
       status = SYS$FORCEX (&pid, 0, 0);
       break;
 #else /* not VMS */
-#if defined (BSD) || (defined (HPUX) && !defined (HPUX_5))
+#if defined (BSD_SYSTEM) || (defined (HPUX) && !defined (HPUX_5))
       /* 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. */
@@ -361,7 +430,7 @@ wait_for_termination (pid)
         if that causes the problem to go away or get worse.  */
       sigsetmask (sigmask (SIGCHLD));
       if (0 > kill (pid, 0))
-        {
+       {
          sigsetmask (SIGEMPTYMASK);
          kill (getpid (), SIGCHLD);
          break;
@@ -370,13 +439,13 @@ wait_for_termination (pid)
        sleep (1);
       else
        sigpause (SIGEMPTYMASK);
-#else /* not BSD, and not HPUX version >= 6 */
+#else /* not BSD_SYSTEM, and not HPUX version >= 6 */
 #if defined (UNIPLUS)
       if (0 > kill (pid, 0))
        break;
       wait (0);
-#else /* neither BSD nor UNIPLUS: random sysV */
-#ifdef POSIX_SIGNALS   /* would this work for LINUX as well? */
+#else /* neither BSD_SYSTEM nor UNIPLUS: random sysV */
+#ifdef POSIX_SIGNALS    /* would this work for LINUX as well? */
       sigblock (sigmask (SIGCHLD));
       if (0 > kill (pid, 0))
        {
@@ -394,18 +463,26 @@ wait_for_termination (pid)
        }
       sigpause (SIGCHLD);
 #else /* not HAVE_SYSV_SIGPAUSE */
+#ifdef WINDOWSNT
+      wait (0);
+      break;
+#else /* not WINDOWSNT */
       if (0 > kill (pid, 0))
        break;
       /* Using sleep instead of pause avoids timing error.
         If the inferior dies just before the sleep,
         we lose just one second.  */
       sleep (1);
+#endif /* not WINDOWSNT */
 #endif /* not HAVE_SYSV_SIGPAUSE */
 #endif /* not POSIX_SIGNALS */
 #endif /* not UNIPLUS */
-#endif /* not BSD, and not HPUX version >= 6 */
+#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;
@@ -416,6 +493,7 @@ wait_for_termination (pid)
       if (status == pid || status == -1)
        break;
 #endif /* BSD4_1 */
+#endif /* not __DJGPP__ > 1*/
 #endif /* not subprocesses */
     }
 }
@@ -457,7 +535,7 @@ flush_pending_output (channel)
 child_setup_tty (out)
      int out;
 {
-#ifndef MSDOS
+#ifndef DOS_NT
   struct emacs_tty s;
 
   EMACS_GET_TTY (out, &s);
@@ -474,9 +552,13 @@ child_setup_tty (out)
 #ifdef IUCLC
   s.main.c_iflag &= ~IUCLC;    /* Disable downcasing on input.  */
 #endif
+#ifdef ISTRIP
+  s.main.c_iflag &= ~ISTRIP;   /* don't strip 8th bit on input */
+#endif
 #ifdef OLCUC
   s.main.c_oflag &= ~OLCUC;    /* Disable upcasing on output.  */
 #endif
+  s.main.c_oflag &= ~TAB3;     /* Disable tab expansion */
   s.main.c_cflag = (s.main.c_cflag & ~CSIZE) | CS8; /* Don't strip 8th bit */
 #if 0
   /* Said to be unnecessary:  */
@@ -486,8 +568,8 @@ child_setup_tty (out)
 
   s.main.c_lflag |= ICANON;    /* Enable erase/kill and eof processing */
   s.main.c_cc[VEOF] = 04;      /* insure that EOF is Control-D */
-  s.main.c_cc[VERASE] = 0377;  /* disable erase processing */
-  s.main.c_cc[VKILL] = 0377;   /* disable kill processing */
+  s.main.c_cc[VERASE] = CDISABLE;      /* disable erase processing */
+  s.main.c_cc[VKILL] = CDISABLE;       /* disable kill processing */
 
 #ifdef HPUX
   s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
@@ -545,18 +627,11 @@ child_setup_tty (out)
     ioctl (out, FIOASYNC, &zero);
   }
 #endif /* RTU */
-#endif /* not MSDOS */
+#endif /* not DOS_NT */
 }
 #endif /* not VMS */
 
 #endif /* subprocesses */
-
-/*ARGSUSED*/
-setpgrp_of_tty (pid)
-     int pid;
-{
-  EMACS_SET_TTY_PGRP (input_fd, &pid);
-}
 \f
 /* Record a signal code and the handler for it.  */
 struct save_signal
@@ -639,12 +714,15 @@ sys_suspend ()
 sys_subshell ()
 {
 #ifndef VMS
-#ifdef MSDOS   /* Demacs 1.1.2 91/10/20 Manabu Higashida */
+#ifdef DOS_NT  /* Demacs 1.1.2 91/10/20 Manabu Higashida */
   int st;
   char oldwd[MAXPATHLEN+1]; /* Fixed length is safe on MSDOS.  */
 #endif
-  int pid = fork ();
+  int pid;
   struct save_signal saved_handlers[5];
+  Lisp_Object dir;
+  unsigned char *str = 0;
+  int len;
 
   saved_handlers[0].code = SIGINT;
   saved_handlers[1].code = SIGQUIT;
@@ -656,44 +734,54 @@ sys_subshell ()
   saved_handlers[3].code = 0;
 #endif
 
+  /* Mentioning current_buffer->buffer would mean including buffer.h,
+     which somehow wedges the hp compiler.  So instead...  */
+
+  dir = intern ("default-directory");
+  if (NILP (Fboundp (dir)))
+    goto xyzzy;
+  dir = Fsymbol_value (dir);
+  if (!STRINGP (dir))
+    goto xyzzy;
+
+  dir = expand_and_dir_to_file (Funhandled_file_name_directory (dir), Qnil);
+  str = (unsigned char *) alloca (XSTRING (dir)->size + 2);
+  len = XSTRING (dir)->size;
+  bcopy (XSTRING (dir)->data, str, len);
+  if (str[len - 1] != '/') str[len++] = '/';
+  str[len] = 0;
+ xyzzy:
+
+#ifdef DOS_NT
+  pid = 0;
+#if __DJGPP__ > 1
+  save_signal_handlers (saved_handlers);
+  synch_process_alive = 1;
+#endif /* __DJGPP__ > 1 */
+#else  
+  pid = vfork ();
   if (pid == -1)
     error ("Can't spawn subshell");
+#endif
+
   if (pid == 0)
     {
-      char *sh;
+      char *sh = 0;
 
-#ifdef MSDOS   /* MW, Aug 1993 */
+#ifdef DOS_NT    /* MW, Aug 1993 */
       getwd (oldwd);
+      if (sh == 0)
+       sh = (char *) egetenv ("SUSPEND");      /* KFS, 1994-12-14 */
 #endif
-      sh = (char *) egetenv ("SHELL");
+      if (sh == 0)
+       sh = (char *) egetenv ("SHELL");
       if (sh == 0)
        sh = "sh";
 
       /* Use our buffer's default directory for the subshell.  */
-      {
-       Lisp_Object dir;
-       unsigned char *str;
-       int len;
-
-       /* mentioning current_buffer->buffer would mean including buffer.h,
-          which somehow wedges the hp compiler.  So instead... */
-
-       dir = intern ("default-directory");
-       /* Can't use NILP */
-       if (XFASTINT (Fboundp (dir)) == XFASTINT (Qnil))
-         goto xyzzy;
-       dir = Fsymbol_value (dir);
-       if (XTYPE (dir) != Lisp_String)
-         goto xyzzy;
-
-       str = (unsigned char *) alloca (XSTRING (dir)->size + 2);
-       len = XSTRING (dir)->size;
-       bcopy (XSTRING (dir)->data, str, len);
-       if (str[len - 1] != '/') str[len++] = '/';
-       str[len] = 0;
+      if (str)
        chdir (str);
-      }
-    xyzzy:
+
 #ifdef subprocesses
       close_process_descs ();  /* Close Emacs's pipes/ptys */
 #endif
@@ -707,22 +795,39 @@ sys_subshell ()
       }
 #endif
 
-#ifdef MSDOS   /* Demacs 1.1.2 91/10/20 Manabu Higashida */
+#ifdef MSDOS    /* Demacs 1.1.2 91/10/20 Manabu Higashida */
       st = system (sh);
       chdir (oldwd);
+#if 0  /* This is also reported if last command executed in subshell failed, KFS */
       if (st)
-        report_file_error ("Can't execute subshell", Fcons (build_string (sh), Qnil));
+       report_file_error ("Can't execute subshell", Fcons (build_string (sh), Qnil));
+#endif
 #else /* not MSDOS */
+#ifdef  WINDOWSNT
+      /* Waits for process completion */
+      pid = _spawnlp (_P_WAIT, sh, sh, NULL);
+      chdir (oldwd);
+      if (pid == -1)
+       write (1, "Can't execute subshell", 22);
+#else   /* not WINDOWSNT */
       execlp (sh, sh, 0);
       write (1, "Can't execute subshell", 22);
       _exit (1);
+#endif  /* not WINDOWSNT */
 #endif /* not MSDOS */
     }
 
+  /* Do this now if we did not do it before.  */
+#if !defined (MSDOS) || __DJGPP__ == 1
   save_signal_handlers (saved_handlers);
   synch_process_alive = 1;
+#endif
+
+#ifndef DOS_NT
   wait_for_termination (pid);
+#endif
   restore_signal_handlers (saved_handlers);
+  synch_process_alive = 0;
 #endif /* !VMS */
 }
 
@@ -751,12 +856,14 @@ restore_signal_handlers (saved_handlers)
 
 int old_fcntl_flags;
 
-init_sigio ()
+init_sigio (fd)
+     int fd;
 {
 #ifdef FASYNC
-  old_fcntl_flags = fcntl (input_fd, F_GETFL, 0) & ~FASYNC;
+  old_fcntl_flags = fcntl (fd, F_GETFL, 0) & ~FASYNC;
+  fcntl (fd, F_SETFL, old_fcntl_flags | FASYNC);
 #endif
-  request_sigio ();
+  interrupts_deferred = 0;
 }
 
 reset_sigio ()
@@ -768,6 +875,9 @@ reset_sigio ()
 
 request_sigio ()
 {
+  if (read_socket_hook)
+    return;
+
 #ifdef SIGWINCH
   sigunblock (sigmask (SIGWINCH));
 #endif
@@ -778,6 +888,9 @@ request_sigio ()
 
 unrequest_sigio ()
 {
+  if (read_socket_hook)
+    return;
+
 #ifdef SIGWINCH
   sigblock (sigmask (SIGWINCH));
 #endif
@@ -791,6 +904,10 @@ unrequest_sigio ()
 request_sigio ()
 {
   int on = 1;
+
+  if (read_socket_hook)
+    return;
+
   ioctl (input_fd, FIOASYNC, &on);
   interrupts_deferred = 0;
 }
@@ -799,6 +916,9 @@ unrequest_sigio ()
 {
   int off = 0;
 
+  if (read_socket_hook)
+    return;
+
   ioctl (input_fd, FIOASYNC, &off);
   interrupts_deferred = 1;
 }
@@ -814,6 +934,9 @@ request_sigio ()
   int on = 1;
   sigset_t st;
 
+  if (read_socket_hook)
+    return;
+
   sigemptyset(&st);
   sigaddset(&st, SIGIO);
   ioctl (input_fd, FIOASYNC, &on);
@@ -825,6 +948,9 @@ unrequest_sigio ()
 {
   int off = 0;
 
+  if (read_socket_hook)
+    return;
+
   ioctl (input_fd, FIOASYNC, &off);
   interrupts_deferred = 1;
 }
@@ -833,11 +959,17 @@ unrequest_sigio ()
 
 request_sigio ()
 {
+  if (read_socket_hook)
+    return;
+
   croak ("request_sigio");
 }
  
 unrequest_sigio ()
 {
+  if (read_socket_hook)
+    return;
+
   croak ("unrequest_sigio");
 }
  
@@ -925,11 +1057,11 @@ emacs_get_tty (fd, settings)
     return -1;
 
 #else
-#ifndef MSDOS
+#ifndef DOS_NT
   /* I give up - I hope you have the BSD ioctls.  */
   if (ioctl (fd, TIOCGETP, &settings->main) < 0)
     return -1;
-#endif /* not MSDOS */
+#endif /* not DOS_NT */
 #endif
 #endif
 #endif
@@ -953,15 +1085,14 @@ emacs_get_tty (fd, settings)
 
 
 /* Set the parameters of the tty on FD according to the contents of
-   *SETTINGS.  If WAITP is non-zero, we wait for all queued output to
-   be written before making the change; otherwise, we forget any
-   queued input and make the change immediately.
+   *SETTINGS.  If FLUSHP is non-zero, we discard input.
    Return 0 if all went well, and -1 if anything failed.  */
+
 int
-emacs_set_tty (fd, settings, waitp)
+emacs_set_tty (fd, settings, flushp)
      int fd;
      struct emacs_tty *settings;
-     int waitp;
+     int flushp;
 {
   /* Set the primary parameters - baud rate, character size, etcetera.  */
 #ifdef HAVE_TCATTR
@@ -975,7 +1106,7 @@ emacs_set_tty (fd, settings, waitp)
      AIX requires this to keep tty from hanging occasionally."  */
   /* This make sure that we don't loop indefinitely in here.  */
   for (i = 0 ; i < 10 ; i++)
-    if (tcsetattr (fd, waitp ? TCSAFLUSH : TCSADRAIN, &settings->main) < 0)
+    if (tcsetattr (fd, flushp ? TCSAFLUSH : TCSADRAIN, &settings->main) < 0)
       {
        if (errno == EINTR)
          continue;
@@ -1005,7 +1136,7 @@ emacs_set_tty (fd, settings, waitp)
 #else
 #ifdef HAVE_TERMIO
   /* The SYSV-style interface?  */
-  if (ioctl (fd, waitp ? TCSETAW : TCSETAF, &settings->main) < 0)
+  if (ioctl (fd, flushp ? TCSETAF : TCSETAW, &settings->main) < 0)
     return -1;
 
 #else
@@ -1017,11 +1148,11 @@ emacs_set_tty (fd, settings, waitp)
     return -1;
 
 #else
-#ifndef MSDOS
+#ifndef DOS_NT
   /* I give up - I hope you have the BSD ioctls.  */
-  if (ioctl (fd, (waitp) ? TIOCSETP : TIOCSETN, &settings->main) < 0)
+  if (ioctl (fd, (flushp) ? TIOCSETP : TIOCSETN, &settings->main) < 0)
     return -1;
-#endif /* not MSDOS */
+#endif /* not DOS_NT */
 
 #endif
 #endif
@@ -1048,7 +1179,11 @@ emacs_set_tty (fd, settings, waitp)
 /* The initial tty mode bits */
 struct emacs_tty old_tty;
 
-int term_initted;              /* 1 if outer tty status has been recorded */
+/* 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
@@ -1076,7 +1211,7 @@ char _sobuf[BUFSIZ];
 static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1};
 #endif
 #ifdef HAVE_TCHARS
-  static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
+static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
 #endif 
 
 init_sys_modes ()
@@ -1090,6 +1225,8 @@ init_sys_modes ()
 #endif
 #endif
 
+  Vtty_erase_char = Qnil;
+
   if (noninteractive)
     return;
 
@@ -1130,15 +1267,31 @@ init_sys_modes ()
     narrow_foreground_group ();
 #endif
 
-  EMACS_GET_TTY (input_fd, &old_tty);
-
+#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))
+#endif
     {
+      EMACS_GET_TTY (input_fd, &old_tty);
+
+      old_tty_valid = 1;
+
       tty = old_tty;
 
 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
+      XSETINT (Vtty_erase_char, old_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 */
+#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 */
+#endif
 #ifdef ISTRIP
       tty.main.c_iflag &= ~ISTRIP;     /* don't strip 8th bit on input */
 #endif
@@ -1178,6 +1331,7 @@ init_sys_modes ()
       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.  */
@@ -1200,10 +1354,35 @@ init_sys_modes ()
 #ifdef VDISCARD
       tty.main.c_cc[VDISCARD] = CDISABLE;
 #endif /* VDISCARD */
+
+      if (flow_control)
+       {
+#ifdef VSTART
+         tty.main.c_cc[VSTART] = '\021';
+#endif /* VSTART */
+#ifdef VSTOP
+         tty.main.c_cc[VSTOP] = '\023';
+#endif /* VSTOP */
+       }
+      else
+       {
+#ifdef VSTART
+         tty.main.c_cc[VSTART] = CDISABLE;
+#endif /* VSTART */
+#ifdef VSTOP
+         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 */
+      /* AIX enhanced edit loses NULs, so disable it */
       tty.main.c_line = 0;
       tty.main.c_iflag &= ~ASCEDIT;
 #else
@@ -1212,6 +1391,15 @@ init_sys_modes ()
       tty.main.c_cc[VSUSP] = 255;
       tty.main.c_cc[VDSUSP] = 255;
 #endif /* IBMR2AIX */
+      if (flow_control)
+       {
+#ifdef VSTART
+         tty.main.c_cc[VSTART] = '\021';
+#endif /* VSTART */
+#ifdef VSTOP
+         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
@@ -1230,12 +1418,13 @@ init_sys_modes ()
        tty.main.tt_char &= ~TT$M_TTSYNC;
       tty.main.tt2_char |= TT2$M_PASTHRU | TT2$M_XON;
 #else /* not VMS (BSD, that is) */
-#ifndef MSDOS
+#ifndef DOS_NT
+      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
+#endif /* not DOS_NT */
 #endif /* not VMS (BSD, that is) */
 #endif /* not HAVE_TERMIO */
 
@@ -1274,7 +1463,8 @@ init_sys_modes ()
       tty.ltchars = new_ltchars;
 #endif /* HAVE_LTCHARS */
 #ifdef MSDOS   /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
-      internal_terminal_init ();
+      if (!term_initted)
+       internal_terminal_init ();
       dos_ttraw ();
 #endif
 
@@ -1292,7 +1482,13 @@ init_sys_modes ()
 #endif
 #endif
 
-#ifdef AIX
+#if defined (HAVE_TERMIOS) || defined (HPUX9)
+#ifdef TCOON
+      if (!flow_control) tcflow (input_fd, TCOON);
+#endif
+#endif
+
+#ifdef AIXHFT
       hft_init ();
 #ifdef IBMR2AIX
       {
@@ -1304,7 +1500,7 @@ init_sys_modes ()
          write (1, "\033[20l", 5);
       }
 #endif
-#endif
+#endif /* AIXHFT */
 
 #ifdef VMS
 /*  Appears to do nothing when in PASTHRU mode.
@@ -1323,7 +1519,7 @@ init_sys_modes ()
     {
       old_fcntl_owner = fcntl (input_fd, F_GETOWN, 0);
       fcntl (input_fd, F_SETOWN, getpid ());
-      init_sigio ();
+      init_sigio (input_fd);
     }
 #endif /* F_GETOWN */
 #endif /* F_SETOWN_BUG */
@@ -1331,7 +1527,7 @@ init_sys_modes ()
 
 #ifdef BSD4_1
   if (interrupt_input)
-    init_sigio ();
+    init_sigio (input_fd);
 #endif
 
 #ifdef VMS  /* VMS sometimes has this symbol but lacks setvbuf.  */
@@ -1345,7 +1541,17 @@ init_sys_modes ()
 #else
   setbuf (stdout, _sobuf);
 #endif
-  if (! read_socket_hook && EQ (Vwindow_system, Qnil))
+#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)
+#endif
+      )
+#endif
     set_terminal_modes ();
 
   if (term_initted && no_redraw_on_reenter)
@@ -1356,10 +1562,8 @@ init_sys_modes ()
   else
     {
       frame_garbaged = 1;
-#ifdef MULTI_FRAME
       if (FRAMEP (Vterminal_frame))
        FRAME_GARBAGED_P (XFRAME (Vterminal_frame)) = 1;
-#endif
     }
 
   term_initted = 1;
@@ -1484,13 +1688,23 @@ reset_sys_modes ()
     }
   if (!term_initted)
     return;
-  if (read_socket_hook || !EQ (Vwindow_system, Qnil))
+#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
   cursor_to (FRAME_HEIGHT (selected_frame) - 1, 0);
   clear_end_of_line (FRAME_WIDTH (selected_frame));
   /* clear_end_of_line may move the cursor */
   cursor_to (FRAME_HEIGHT (selected_frame) - 1, 0);
-#ifdef IBMR2AIX
+#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. */
@@ -1503,7 +1717,7 @@ reset_sys_modes ()
 
   reset_terminal_modes ();
   fflush (stdout);
-#ifdef BSD
+#ifdef BSD_SYSTEM
 #ifndef BSD4_1
   /* Avoid possible loss of output when changing terminal modes.  */
   fsync (fileno (stdout));
@@ -1529,14 +1743,22 @@ reset_sys_modes ()
     reset_sigio ();
 #endif /* BSD4_1 */
 
-  while (EMACS_SET_TTY (input_fd, &old_tty, 0) < 0 && errno == EINTR)
-    ;
+  if (old_tty_valid)
+    while (EMACS_SET_TTY (input_fd, &old_tty, 0) < 0 && errno == EINTR)
+      ;
 
 #ifdef MSDOS   /* Demacs 1.1.2 91/10/20 Manabu Higashida */
   dos_ttcooked ();
 #endif
 
-#ifdef AIX
+#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
 
@@ -1677,12 +1899,8 @@ kbd_input_ast ()
     {
       struct input_event e;
       e.kind = ascii_keystroke;
-      XSET (e.code, Lisp_Int, c);
-#ifdef MULTI_FRAME
-      XSET(e.frame_or_window, Lisp_Frame, selected_frame);
-#else
-      e.frame_or_window = Qnil;
-#endif
+      XSETINT (e.code, c);
+      XSETFRAME (e.frame_or_window, selected_frame);
       kbd_buffer_store_event (&e);
     }
   if (input_available_clear_time)
@@ -1810,7 +2028,8 @@ sys_sleep (timeval)
     SYS$WAITFR (timer_ef);       /* Wait for timer expiry only */
 }
 
-init_sigio ()
+init_sigio (fd)
+     int fd;
 {
   request_sigio ();
 }
@@ -1853,7 +2072,7 @@ unrequest_sigio ()
  *
  */
 
-#if !defined (CANNOT_UNEXEC) && !defined (HAVE_TEXT_START)
+#ifndef HAVE_TEXT_START
 char *
 start_of_text ()
 {
@@ -1869,7 +2088,7 @@ start_of_text ()
 #endif /* GOULD */
 #endif /* TEXT_START */
 }
-#endif /* not CANNOT_UNEXEC and not HAVE_TEXT_START */
+#endif /* not HAVE_TEXT_START */
 
 /*
  *     Return the address of the start of the data segment prior to
@@ -1892,7 +2111,7 @@ start_of_text ()
  *     at least on UniPlus, is temacs will have to be made unshared so
  *     that text and data are contiguous.  Then once loadup is complete,
  *     unexec will produce a shared executable where the data can be
- *     at the normal shared text boundry and the startofdata variable
+ *     at the normal shared text boundary and the startofdata variable
  *     will be patched by unexec to the correct value.
  *
  */
@@ -1996,7 +2215,7 @@ init_system_name ()
   uname (&uts);
   Vsystem_name = build_string (uts.nodename);
 #else /* HAVE_GETHOSTNAME */
-  int hostname_size = 256;
+  unsigned int hostname_size = 256;
   char *hostname = (char *) alloca (hostname_size);
 
   /* Try to get the host name; if the buffer is too short, try
@@ -2023,10 +2242,25 @@ init_system_name ()
   if (initialized)
 #endif /* not CANNOT_DUMP */
     {
-      struct hostent *hp = gethostbyname (hostname);
+      struct hostent *hp;
+      int count;
+      for (count = 0;; count++)
+       {
+#ifdef TRY_AGAIN
+         h_errno = 0;
+#endif
+         hp = gethostbyname (hostname);
+#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 = hp->h_name;
+         char *fqdn = (char *) hp->h_name;
          char *p;
 
          if (!index (fqdn, '.'))
@@ -2055,6 +2289,43 @@ init_system_name ()
        }
     }
 #endif /* HAVE_SOCKETS */
+  /* We used to try using getdomainname as an alternative
+     to sysinfo, here, but NIIBE Yutaka <gniibe@etl.go.jp> says that
+     getdomainname gets the NIS/YP domain which often is not the same
+     as in Internet domain name.  */
+#if (HAVE_SYSINFO && defined (SI_SRPC_DOMAIN))
+  if (! index (hostname, '.'))
+    {
+      /* The hostname is not fully qualified.  Append the domain name.  */
+
+      int hostlen = strlen (hostname);
+      int domain_size = 256;
+
+      for (;;)
+       {
+         char *domain = (char *) alloca (domain_size + 1);
+         char *fqdn = (char *) alloca (hostlen + 1 + domain_size + 1);
+         int sys_domain_size = sysinfo (SI_SRPC_DOMAIN, domain, domain_size);
+         if (sys_domain_size <= 0)
+           break;
+         if (domain_size < sys_domain_size)
+           {
+             domain_size = sys_domain_size;
+             continue;
+           }
+         strcpy (fqdn, hostname);
+         if (domain[0] == '.')
+           strcpy (fqdn + hostlen, domain);
+         else if (domain[0] != 0)
+           {
+             fqdn[hostlen] = '.';
+             strcpy (fqdn + hostlen + 1, domain);
+           }
+         hostname = fqdn;
+         break;
+       }
+    }
+#endif /* HAVE_SYSINFO && defined (SI_SRPC_DOMAIN) */
   Vsystem_name = build_string (hostname);
 #endif /* HAVE_GETHOSTNAME */
 #endif /* VMS */
@@ -2067,10 +2338,14 @@ init_system_name ()
   }
 }
 \f
+#ifndef MSDOS
 #ifndef VMS
-#ifndef HAVE_SELECT
+#if !defined (HAVE_SELECT) || defined (BROKEN_SELECT_NON_X)
+
+#include "sysselect.h"
+#undef select
 
-#ifdef HAVE_X_WINDOWS
+#if defined (HAVE_X_WINDOWS) && !defined (HAVE_SELECT)
 /* Cause explanatory error message at compile time,
    since the select emulation is not good enough for X.  */
 int *x = &x_windows_lose_if_no_select_system_call;
@@ -2105,15 +2380,18 @@ select_alarm ()
     longjmp (read_alarm_throw, 1);
 }
 
+#ifndef WINDOWSNT
 /* Only rfds are checked.  */
 int
-select (nfds, rfds, wfds, efds, timeout)
+sys_select (nfds, rfds, wfds, efds, timeout)
      int nfds;
-     int *rfds, *wfds, *efds, *timeout;
+     SELECT_TYPE *rfds, *wfds, *efds;
+     EMACS_TIME *timeout;
 {
-  int ravail = 0, orfds = 0, old_alarm;
-  int timeoutval = timeout ? *timeout : 100000;
-  int *local_timeout = &timeoutval;
+  int ravail = 0, old_alarm;
+  SELECT_TYPE orfds;
+  int timeoutval;
+  int *local_timeout;
   extern int proc_buffered_char[];
 #ifndef subprocesses
   int process_tick = 0, update_tick = 0;
@@ -2123,52 +2401,64 @@ select (nfds, rfds, wfds, efds, timeout)
   SIGTYPE (*old_trap) ();
   unsigned char buf;
 
+#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))
+    return select (nfds, rfds, wfds, efds, timeout);
+#endif
+  timeoutval = timeout ? EMACS_SECS (*timeout) : 100000;
+  local_timeout = &timeoutval;
+  FD_ZERO (&orfds);
   if (rfds)
     {
       orfds = *rfds;
-      *rfds = 0;
+      FD_ZERO (rfds);
     }
   if (wfds)
-    *wfds = 0;
+    FD_ZERO (wfds);
   if (efds)
-    *efds = 0;
+    FD_ZERO (efds);
 
   /* If we are looking only for the terminal, with no timeout,
      just read it and wait -- that's more efficient.  */
-  if (orfds == 1 && *local_timeout == 100000 && process_tick == update_tick)
+  if (*local_timeout == 100000 && process_tick == update_tick
+      && FD_ISSET (0, &orfds))
     {
+      int fd;
+      for (fd = 1; fd < nfds; ++fd)
+       if (FD_ISSET (fd, &orfds))
+         goto hardway;
       if (! detect_input_pending ())
        read_input_waiting ();
-      *rfds = 1;
+      FD_SET (0, rfds);
       return 1;
     }
 
+ hardway:
   /* Once a second, till the timer expires, check all the flagged read
    * descriptors to see if any input is available.  If there is some then
    * set the corresponding bit in the return copy of rfds.
    */ 
   while (1)
     {
-      register int to_check, bit, fd;
+      register int to_check, fd;
 
       if (rfds)
        {
-         for (to_check = nfds, bit = 1, fd = 0; --to_check >= 0; bit <<= 1, fd++)
+         for (to_check = nfds, fd = 0; --to_check >= 0; fd++)
            {
-             if (orfds & bit)
+             if (FD_ISSET (fd, &orfds))
                {
                  int avail = 0, status = 0;
 
-                 if (bit == 1)
+                 if (fd == 0)
                    avail = detect_input_pending (); /* Special keyboard handler */
                  else
                    {
 #ifdef FIONREAD
                      status = ioctl (fd, FIONREAD, &avail);
 #else /* no FIONREAD */
-#ifdef MSDOS
-                     abort (); /* I don't think we need it.  */
-#else /* not MSDOS */
                      /* Hoping it will return -1 if nothing available
                         or 0 if all 0 chars requested are read.  */
                      if (proc_buffered_char[fd] >= 0)
@@ -2179,12 +2469,11 @@ select (nfds, rfds, wfds, efds, timeout)
                          if (avail > 0)
                            proc_buffered_char[fd] = buf;
                        }
-#endif /* not MSDOS */
 #endif /* no FIONREAD */
                    }
                  if (status >= 0 && avail > 0)
                    {
-                     (*rfds) |= bit;
+                     FD_SET (fd, rfds);
                      ravail++;
                    }
                }
@@ -2200,14 +2489,10 @@ select (nfds, rfds, wfds, efds, timeout)
       while (select_alarmed == 0 && *local_timeout != 0
             && process_tick == update_tick)
        {
-#ifdef MSDOS
-         sleep_or_kbd_hit (SELECT_PAUSE, (orfds & 1) != 0);
-         select_alarm ();
-#else /* not MSDOS */
          /* If we are interested in terminal input,
             wait by reading the terminal.
             That makes instant wakeup for terminal input at least.  */
-         if (orfds & 1)
+         if (FD_ISSET (0, &orfds))
            {
              read_input_waiting ();
              if (detect_input_pending ())
@@ -2215,7 +2500,6 @@ select (nfds, rfds, wfds, efds, timeout)
            }
          else
            pause ();
-#endif /* not MSDOS */
        }
       (*local_timeout) -= SELECT_PAUSE;
       /* Reset the old alarm if there was one */
@@ -2235,12 +2519,13 @@ select (nfds, rfds, wfds, efds, timeout)
     }
   return ravail;
 }
+#endif /* not WINDOWSNT */
 
 /* Read keyboard input into the standard buffer,
    waiting for at least one character.  */
 
-/* Make all keyboard buffers much bigger when using X windows.  */
-#ifdef HAVE_X_WINDOWS
+/* Make all keyboard buffers much bigger when using a window system.  */
+#ifdef HAVE_WINDOW_SYSTEM
 #define BUFFER_SIZE_FACTOR 16
 #else
 #define BUFFER_SIZE_FACTOR 1
@@ -2269,7 +2554,7 @@ read_input_waiting ()
          /* Don't look at input that follows a C-g too closely.
             This reduces lossage due to autorepeat on C-g.  */
          if (buf[i].kind == ascii_keystroke
-             && XINT(buf[i].code) == quit_char)
+             && buf[i].code == quit_char)
            break;
        }
     }
@@ -2280,7 +2565,7 @@ read_input_waiting ()
 
       /* Scan the chars for C-g and store them in kbd_buffer.  */
       e.kind = ascii_keystroke;
-      e.frame_or_window = selected_frame;
+      XSETFRAME (e.frame_or_window, selected_frame);
       e.modifiers = 0;
       for (i = 0; i < nread; i++)
        {
@@ -2295,7 +2580,7 @@ read_input_waiting ()
                buf[i] &= ~0x80;
            }
 
-         XSET (e.code, Lisp_Int, buf[i]);
+         XSETINT (e.code, buf[i]);
          kbd_buffer_store_event (&e);
          /* Don't look at input that follows a C-g too closely.
             This reduces lossage due to autorepeat on C-g.  */
@@ -2307,6 +2592,7 @@ read_input_waiting ()
 
 #endif /* not HAVE_SELECT */
 #endif /* not VMS */
+#endif /* not MSDOS */
 \f
 #ifdef BSD4_1
 /*
@@ -2328,12 +2614,13 @@ sys_open (path, oflag, mode)
     return open (path, oflag);
 }
 
-init_sigio ()
+init_sigio (fd)
+     int fd;
 {
   if (noninteractive)
     return;
   lmode = LINTRUP | lmode;
-  ioctl (0, TIOCLSET, &lmode);
+  ioctl (fd, TIOCLSET, &lmode);
 }
 
 reset_sigio ()
@@ -2416,11 +2703,6 @@ init_signals ()
 signal_handler_t
 sys_signal (int signal_number, signal_handler_t action)
 {
-#ifdef DGUX
-  /* This gets us restartable system calls for efficiency.
-     The "else" code will works as well. */
-  return (berk_signal (signal_number, action));
-#else
   sigemptyset (&new_action.sa_mask);
   new_action.sa_handler = action;
 #ifdef SA_RESTART
@@ -2433,7 +2715,6 @@ sys_signal (int signal_number, signal_handler_t action)
 #endif
   sigaction (signal_number, &new_action, &old_action);
   return (old_action.sa_handler);
-#endif /* DGUX */
 }
 
 #ifndef __GNUC__
@@ -2488,122 +2769,80 @@ sys_sigsetmask (sigset_t new_mask)
 
 #endif /* POSIX_SIGNALS */
 \f
-#ifndef BSTRING
+#ifndef HAVE_RANDOM
+#ifdef random
+#define HAVE_RANDOM
+#endif
+#endif
 
-#ifndef bzero
+/* Figure out how many bits the system's random number generator uses.
+   `random' and `lrand48' are assumed to return 31 usable bits.
+   BSD `rand' returns a 31 bit value but the low order bits are unusable;
+   so we'll shift it and treat it like the 15-bit USG `rand'.  */
+
+#ifndef RAND_BITS
+# ifdef HAVE_RANDOM
+#  define RAND_BITS 31
+# else /* !HAVE_RANDOM */
+#  ifdef HAVE_LRAND48
+#   define RAND_BITS 31
+#   define random lrand48
+#  else /* !HAVE_LRAND48 */
+#   define RAND_BITS 15
+#   if RAND_MAX == 32767
+#    define random rand
+#   else /* RAND_MAX != 32767 */
+#    if RAND_MAX == 2147483647
+#     define random() (rand () >> 16)
+#    else /* RAND_MAX != 2147483647 */
+#     ifdef USG
+#      define random rand
+#     else
+#      define random() (rand () >> 16)
+#     endif /* !USG */
+#    endif /* RAND_MAX != 2147483647 */
+#   endif /* RAND_MAX != 32767 */
+#  endif /* !HAVE_LRAND48 */
+# endif /* !HAVE_RANDOM */
+#endif /* !RAND_BITS */
 
 void
-bzero (b, length)
-     register char *b;
-     register int length;
-{
-#ifdef VMS
-  short zero = 0;
-  long max_str = 65535;
-
-  while (length > max_str) {
-    (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
-    length -= max_str;
-    b += max_str;
-  }
-  max_str = length;
-  (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
-#else
-  while (length-- > 0)
-    *b++ = 0;
-#endif /* not VMS */
-}
-
-#endif /* no bzero */
-
-#ifndef bcopy
-/* Saying `void' requires a declaration, above, where bcopy is used
-   and that declaration causes pain for systems where bcopy is a macro.  */
-bcopy (b1, b2, length)
-     register char *b1;
-     register char *b2;
-     register int length;
+seed_random (arg)
+     long arg;
 {
-#ifdef VMS
-  long max_str = 65535;
-
-  while (length > max_str) {
-    (void) LIB$MOVC3 (&max_str, b1, b2);
-    length -= max_str;
-    b1 += max_str;
-    b2 += max_str;
-  }
-  max_str = length;
-  (void) LIB$MOVC3 (&length, b1, b2);
+#ifdef HAVE_RANDOM
+  srandom ((unsigned int)arg);
 #else
-  while (length-- > 0)
-    *b2++ = *b1++;
-#endif /* not VMS */
-}
-#endif /* no bcopy */
-
-#ifndef bcmp
-int
-bcmp (b1, b2, length)  /* This could be a macro! */
-     register char *b1;
-     register char *b2;
-     register int length;
-{
-#ifdef VMS
-  struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1};
-  struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2};
-
-  return STR$COMPARE (&src1, &src2);
-#else
-  while (length-- > 0)
-    if (*b1++ != *b2++)
-      return 1;
-
-  return 0;
-#endif /* not VMS */
+# ifdef HAVE_LRAND48
+  srand48 (arg);
+# else
+  srand ((unsigned int)arg);
+# endif
+#endif
 }
-#endif /* no bcmp */
 
-#endif /* not BSTRING */
-\f
-#ifndef HAVE_RANDOM
-#ifdef USG
 /*
- *     The BSD random returns numbers in the range of
- *     0 to 2e31 - 1.  The USG rand returns numbers in the
- *     range of 0 to 2e15 - 1.  This is probably not significant
- *     in this usage.
+ * Build a full Emacs-sized word out of whatever we've got.
+ * This suffices even for a 64-bit architecture with a 15-bit rand.
  */
-  
 long
-random ()
-{
-  /* Arrange to return a range centered on zero.  */
-  return (rand () << 15) + rand () - (1 << 29);
+get_random ()
+{
+  long val = random ();
+#if VALBITS > RAND_BITS
+  val = (val << RAND_BITS) ^ random ();
+#if VALBITS > 2*RAND_BITS
+  val = (val << RAND_BITS) ^ random ();
+#if VALBITS > 3*RAND_BITS
+  val = (val << RAND_BITS) ^ random ();
+#if VALBITS > 4*RAND_BITS
+  val = (val << RAND_BITS) ^ random ();
+#endif /* need at least 5 */
+#endif /* need at least 4 */
+#endif /* need at least 3 */
+#endif /* need at least 2 */
+  return val & ((1L << VALBITS) - 1);
 }
-
-srandom (arg)
-     int arg;
-{
-  srand (arg);
-}
-
-#endif /* USG */
-
-#ifdef BSD4_1
-long random ()
-{
-  /* Arrange to return a range centered on zero.  */
-  return (rand () << 15) + rand () - (1 << 29);
-}
-
-srandom (arg)
-     int arg;
-{
-  srand (arg);
-}
-#endif /* BSD4_1 */
-#endif
 \f
 #ifdef WRONG_NAME_INSQUE
 
@@ -2671,7 +2910,7 @@ sys_abort ()
 \f
 #ifdef VMS
 #ifdef LINK_CRTL_SHARE
-#ifdef SHAREABLE_LIB_BUG
+#ifdef SHARABLE_LIB_BUG
 /* Variables declared noshare and initialized in sharable libraries
    cannot be shared.  The VMS linker incorrectly forces you to use a private
    version which is uninitialized... If not for this "feature", we
@@ -2717,11 +2956,12 @@ char *sys_errlist[] =
     "I/O stream empty",
     "vax/vms specific error code nontranslatable error"
   };
-#endif /* SHAREABLE_LIB_BUG */
+#endif /* SHARABLE_LIB_BUG */
 #endif /* LINK_CRTL_SHARE */
 #endif /* VMS */
 
 #ifndef HAVE_STRERROR
+#ifndef WINDOWSNT
 char *
 strerror (errnum)
      int errnum;
@@ -2733,7 +2973,7 @@ strerror (errnum)
     return sys_errlist[errnum];
   return (char *) "Unknown error";
 }
-
+#endif /* not WINDOWSNT */
 #endif /* ! HAVE_STRERROR */
 \f
 #ifdef INTERRUPTIBLE_OPEN
@@ -2758,10 +2998,19 @@ sys_open (path, oflag, mode)
 sys_close (fd)
      int fd;
 {
+  int did_retry = 0;
   register int rtnval;
 
   while ((rtnval = close (fd)) == -1
-        && (errno == EINTR));
+        && (errno == EINTR))
+    did_retry = 1;
+
+  /* If close is interrupted SunOS 4.1 may or may not have closed the
+     file descriptor.  If it did the second close will fail with
+     errno = EBADF.  That means we have succeeded.  */
+  if (rtnval == -1 && did_retry && errno == EBADF)
+    return 0;
+
   return rtnval;
 }
 
@@ -2814,16 +3063,17 @@ sys_write (fildes, buf, nbyte)
 #endif /* INTERRUPTIBLE_IO */
 \f
 #ifndef HAVE_VFORK
-
+#ifndef WINDOWSNT
 /*
- *     Substitute fork for vfork on USG flavors.
+ *      Substitute fork for vfork on USG flavors.
  */
 
+VFORK_RETURN_TYPE
 vfork ()
 {
   return (fork ());
 }
-
+#endif /* not WINDOWSNT */
 #endif /* not HAVE_VFORK */
 \f
 #ifdef USG
@@ -2875,10 +3125,12 @@ char *sys_siglist[NSIG + 1] =
   "LAN I/O interrupt",                 /* 25 SIGAIO */
   "PTY I/O interrupt",                 /* 26 SIGPTY */
   "I/O intervention required",         /* 27 SIGIOINT */
+#ifdef AIXHFT
   "HFT grant",                         /* 28 SIGGRANT */
   "HFT retract",                       /* 29 SIGRETRACT */
   "HFT sound done",                    /* 30 SIGSOUND */
   "HFT input ready",                   /* 31 SIGMSG */
+#endif
 #else /* not AIX */
   "bogus signal",                      /* 0 */
   "hangup",                            /* 1  SIGHUP */
@@ -2903,7 +3155,7 @@ char *sys_siglist[NSIG + 1] =
 #ifdef sun
   "window size change",                            /* 20 SIGWINCH */
   "urgent socket condition",               /* 21 SIGURG */
-  "pollable event occured",                /* 22 SIGPOLL */
+  "pollable event occurred",               /* 22 SIGPOLL */
   "stop (cannot be caught or ignored)", /*  23 SIGSTOP */
   "user stop requested from tty",          /* 24 SIGTSTP */
   "stopped process has been continued",        /* 25 SIGCONT */
@@ -2986,37 +3238,6 @@ rename (from, to)
 
 #endif
 
-#ifdef MISSING_UTIMES
-
-/* HPUX (among others) sets HAVE_TIMEVAL but does not implement utimes.  */
-
-utimes ()
-{
-}
-#endif
-
-#ifdef IRIS_UTIME
-
-/* The IRIS (3.5) has timevals, but uses sys V utime, and doesn't have the
-   utimbuf structure defined anywhere but in the man page. */
-
-struct utimbuf
- {
-   long actime;
-   long modtime;
- };
-
-utimes (name, tvp)
-     char *name;
-     struct timeval tvp[];
-{
-  struct utimbuf utb;
-  utb.actime  = tvp[0].tv_sec;
-  utb.modtime = tvp[1].tv_sec;
-  utime (name, &utb);
-}
-#endif /* IRIS_UTIME */
-
 
 #ifdef HPUX
 #ifndef HAVE_PERROR
@@ -3356,6 +3577,24 @@ readdirver (dirp)
 #endif /* NONSYSTEM_DIR_LIBRARY */
 
 \f
+int
+set_file_times (filename, atime, mtime)
+     char *filename;
+     EMACS_TIME atime, mtime;
+{
+#ifdef HAVE_UTIMES
+  struct timeval tv[2];
+  tv[0] = atime;
+  tv[1] = mtime;
+  return utimes (filename, tv);
+#else /* not HAVE_UTIMES */
+  struct utimbuf utb;
+  utb.actime = EMACS_SECS (atime);
+  utb.modtime = EMACS_SECS (mtime);
+  return utime (filename, &utb);
+#endif /* not HAVE_UTIMES */
+}
+\f
 /* mkdir and rmdir functions, for systems which don't have them.  */
 
 #ifndef HAVE_MKDIR
@@ -3468,17 +3707,17 @@ rmdir (dpath)
          dup2 (fd, 1);
          dup2 (fd, 2);
         }
-      wait_for_termination (cpid);
-  if (synch_process_death != 0 || synch_process_retcode != 0)
-      return -1;               /* /bin/rmdir failed */
+      execl ("/bin/rmdir", "rmdir", dpath, (char *) 0);
+      _exit (-1);              /* Can't exec /bin/rmdir */
+
     default:                   /* Parent process */
-      while (cpid != wait (&status));  /* Wait for kid to finish */
+      wait_for_termination (cpid);
     }
 
-  if (WIFSIGNALED (status) || WEXITSTATUS (status) != 0)
+  if (synch_process_death != 0 || synch_process_retcode != 0)
     {
       errno = EIO;             /* We don't know why, but */
-      return -1;               /* /bin/mkdir failed */
+      return -1;               /* /bin/rmdir failed */
     }
 
   return 0;
@@ -3596,8 +3835,8 @@ sys_access (path, mode)
 #else /* not VMS4_4 */
 
 #include <prvdef.h>
-#define        ACE$M_WRITE     2
-#define        ACE$C_KEYID     1
+#define ACE$M_WRITE     2
+#define ACE$C_KEYID     1
 
 static unsigned short memid, grpid;
 static unsigned int uic;
@@ -3630,13 +3869,13 @@ sys_access (filename, type)
       grpid = uic >> 16;
     }
 
-  if (type != 2)               /* not checking write access */
+  if (type != 2)                /* not checking write access */
     return access (filename, type);
 
   /* Check write protection. */
     
-#define        CHECKPRIV(bit)    (prvmask.bit)
-#define        WRITEABLE(field)  (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
+#define CHECKPRIV(bit)    (prvmask.bit)
+#define WRITABLE(field)  (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
 
   /* Find privilege bits */
   status = SYS$SETPRV (0, 0, 0, prvmask);
@@ -3657,7 +3896,7 @@ sys_access (filename, type)
     return -1;
   SYS$CLOSE (&fab, 0, 0);
   /* Check system access */
-  if (CHECKPRIV (PRV$V_SYSPRV) && WRITEABLE (XAB$V_SYS))
+  if (CHECKPRIV (PRV$V_SYSPRV) && WRITABLE (XAB$V_SYS))
     return 0;
   /* Check ACL entries, if any */
   acl_controlled = 0;
@@ -3683,16 +3922,16 @@ sys_access (filename, type)
        return -1;
     }
   /* No ACL entries specified, check normal protection */
-  if (WRITEABLE (XAB$V_WLD))   /* World writeable */
+  if (WRITABLE (XAB$V_WLD))    /* World writable */
     return 0;
-  if (WRITEABLE (XAB$V_GRP) &&
+  if (WRITABLE (XAB$V_GRP) &&
       (unsigned short) (xab.xab$l_uic >> 16) == grpid)
-    return 0;                  /* Group writeable */
-  if (WRITEABLE (XAB$V_OWN) &&
+    return 0;                  /* Group writable */
+  if (WRITABLE (XAB$V_OWN) &&
       (xab.xab$l_uic & 0xFFFF) == memid)
-    return 0;                  /* Owner writeable */
+    return 0;                  /* Owner writable */
 
-  return -1;   /* Not writeable */
+  return -1;   /* Not writable */
 }
 #endif /* not VMS4_4 */
 #endif /* access */
@@ -4375,7 +4614,7 @@ cnv_uaf_pw (up)
   retpw.pw_uid = up->uaf$w_mem;
   retpw.pw_gid = up->uaf$w_grp;
 
-  /* I suppose this is not the best sytle, to possibly overwrite one
+  /* I suppose this is not the best style, to possibly overwrite one
      byte beyond the end of the field, but what the heck... */
   ptr = &up->uaf$t_username[UAF$S_USERNAME];
   while (ptr[-1] == ' ')
@@ -4741,7 +4980,7 @@ srandom (seed)
 }
 #endif /* VMS */
 \f
-#ifdef AIX
+#ifdef AIXHFT
 
 /* Called from init_sys_modes.  */
 hft_init ()
@@ -4833,4 +5072,111 @@ hft_reset ()
   hftctl (0, HFSKBD, &buf);
 }
 
-#endif /* AIX */
+#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
+
+void
+bzero (b, length)
+     register char *b;
+     register int length;
+{
+#ifdef VMS
+  short zero = 0;
+  long max_str = 65535;
+
+  while (length > max_str) {
+    (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
+    length -= max_str;
+    b += max_str;
+  }
+  max_str = length;
+  (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
+#else
+  while (length-- > 0)
+    *b++ = 0;
+#endif /* not VMS */
+}
+
+#endif /* no bzero */
+#endif /* BSTRING */
+
+#if (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY)
+#undef bcopy
+
+/* Saying `void' requires a declaration, above, where bcopy is used
+   and that declaration causes pain for systems where bcopy is a macro.  */
+bcopy (b1, b2, length)
+     register char *b1;
+     register char *b2;
+     register int length;
+{
+#ifdef VMS
+  long max_str = 65535;
+
+  while (length > max_str) {
+    (void) LIB$MOVC3 (&max_str, b1, b2);
+    length -= max_str;
+    b1 += max_str;
+    b2 += max_str;
+  }
+  max_str = length;
+  (void) LIB$MOVC3 (&length, b1, b2);
+#else
+  while (length-- > 0)
+    *b2++ = *b1++;
+#endif /* not VMS */
+}
+#endif /* (defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY) */
+
+#ifndef BSTRING
+#ifndef bcmp
+int
+bcmp (b1, b2, length)  /* This could be a macro! */
+     register char *b1;
+     register char *b2;
+     register int length;
+{
+#ifdef VMS
+  struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1};
+  struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2};
+
+  return STR$COMPARE (&src1, &src2);
+#else
+  while (length-- > 0)
+    if (*b1++ != *b2++)
+      return 1;
+
+  return 0;
+#endif /* not VMS */
+}
+#endif /* no bcmp */
+#endif /* not BSTRING */