]> code.delx.au - gnu-emacs/blobdiff - src/sysdep.c
(random, srandom): Check HAVE_LRAND48, not HAVE_RAND48.
[gnu-emacs] / src / sysdep.c
index 45226ed6159a2980f145228c61d3e51618a57d1c..004a0b95676cfda9d2e80053b0a530bf593d3f2d 100644 (file)
@@ -1,11 +1,11 @@
 /* Interfaces to system-dependent kernel and library entries.
-   Copyright (C) 1985, 1986, 1987, 1988, 1992 Free Software Foundation, Inc.
+   Copyright (C) 1985, 86, 87, 88, 93, 94 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 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 1, or (at your option)
+the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -21,7 +21,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <signal.h>
 #include <setjmp.h>
 
-#include "config.h"
+#include <config.h>
 #include "lisp.h"
 #include "blockinput.h"
 #undef NULL
@@ -59,16 +59,24 @@ 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>
 
-extern int errno;
-#ifndef VMS
-extern char *sys_errlist[];
+#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>
 #endif
 
+extern int errno;
+
 #ifdef VMS
 #include <rms.h>
 #include <ttdef.h>
@@ -104,24 +112,24 @@ extern char *sys_errlist[];
 #endif
 #endif /* not 4.1 bsd */
 
-/* Get DGUX definition for FASYNC - DJB */
-#ifdef DGUX
-#include <sys/file.h>
-#endif /* DGUX */
+#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"
-
-#ifdef BSD
-#ifdef BSD4_1
-#include <wait.h>
-#else /* not 4.1 */
-#include <sys/wait.h>
-#endif /* not 4.1 */
-#endif /* BSD */
+#include "syswait.h"
 
 #ifdef BROKEN_TIOCGWINSZ
 #undef TIOCGWINSZ
+#undef TIOCSWINSZ
 #endif
 
 #ifdef USG
@@ -130,7 +138,7 @@ extern char *sys_errlist[];
 #ifndef MEMORY_IN_STRING_H
 #include <memory.h>
 #endif
-#ifdef TIOCGWINSZ
+#if defined (TIOCGWINSZ) || defined (ISC4_0)
 #ifdef NEED_SIOCTL
 #include <sys/sioctl.h>
 #endif
@@ -138,7 +146,7 @@ extern char *sys_errlist[];
 #include <sys/stream.h>
 #include <sys/ptem.h>
 #endif
-#endif /* TIOCGWINSZ */
+#endif /* TIOCGWINSZ or ISC4_0 */
 #endif /* USG */
 
 extern int quit_char;
@@ -158,6 +166,15 @@ extern int quit_char;
 #include "syssignal.h"
 #include "systime.h"
 
+/* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits.  */
+#ifndef LPASS8
+#define LPASS8 0
+#endif
+
+#ifdef BSD4_1
+#define LNOFLSH 0100000
+#endif
+
 static int baud_convert[] =
 #ifdef BAUD_CONVERT
   BAUD_CONVERT;
@@ -171,10 +188,21 @@ static int baud_convert[] =
 extern short ospeed;
 
 /* The file descriptor for Emacs's input terminal.
-   Under Unix, this is always left zero;
+   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;
+\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_tty_input ()
 {
@@ -197,36 +225,47 @@ discard_tty_input ()
 #ifdef APOLLO
   {
     int zero = 0;
-    ioctl (0, TIOCFLUSH, &zero);
+    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);
+#endif /* not MSDOS */
 #endif /* not Apollo */
 #endif /* not VMS */
 }
 
 #ifdef SIGTSTP
 
+/* Arrange for character C to be read as the next input from
+   the terminal.  */
+
 stuff_char (c)
      char c;
 {
 /* Should perhaps error if in batch mode */
 #ifdef TIOCSTI
-  ioctl (0, TIOCSTI, &c);
+  ioctl (input_fd, TIOCSTI, &c);
 #else /* no TIOCSTI */
-  error ("Cannot stuff terminal input characters in this version of Unix.");
+  error ("Cannot stuff terminal input characters in this version of Unix");
 #endif /* no TIOCSTI */
 }
 
 #endif /* SIGTSTP */
-
+\f
 init_baud_rate ()
 {
   if (noninteractive)
     ospeed = 0;
   else
     {
+#ifdef MSDOS
+    ospeed = 15;
+#else
 #ifdef VMS
       struct sensemode sg;
 
@@ -237,16 +276,21 @@ init_baud_rate ()
 #ifdef HAVE_TERMIOS
       struct termios sg;
 
-      sg.c_cflag = (sg.c_cflag & ~CBAUD) | B9600;
-      tcgetattr (0, &sg);
-      ospeed = sg.c_cflag & CBAUD;
+      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;
 
-      sg.c_cflag = (sg.c_cflag & ~CBAUD) | B9600;
+      sg.c_cflag = B9600;
 #ifdef HAVE_TCATTR
-      tcgetattr (0, &sg);
+      tcgetattr (input_fd, &sg);
 #else
       ioctl (input_fd, TCGETA, &sg);
 #endif
@@ -255,11 +299,13 @@ init_baud_rate ()
       struct sgttyb sg;
       
       sg.sg_ospeed = B9600;
-      ioctl (0, TIOCGETP, &sg);
+      if (ioctl (input_fd, TIOCGETP, &sg) < 0)
+       abort ();
       ospeed = sg.sg_ospeed;
 #endif /* not HAVE_TERMIO */
 #endif /* not HAVE_TERMIOS */
 #endif /* not VMS */
+#endif /* not MSDOS */
     }
    
   baud_rate = (ospeed < sizeof baud_convert / sizeof baud_convert[0]
@@ -277,7 +323,7 @@ set_exclusive_use (fd)
 #endif
   /* Ok to do nothing if this feature does not exist */
 }
-
+\f
 #ifndef subprocesses
 
 wait_without_blocking ()
@@ -314,16 +360,59 @@ wait_for_termination (pid)
       status = SYS$FORCEX (&pid, 0, 0);
       break;
 #else /* not VMS */
-
-      /* Exit if the process has terminated.  */
-      if (!synch_process_alive)
+#if defined (BSD) || (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. */
+      /* There is some indication that there is a bug involved with
+        termination of subprocesses, perhaps involving a kernel bug too,
+        but no idea what it is.  Just as a hunch we signal SIGCHLD to see
+        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;
+       }
+      if (wait_debugging)
+       sleep (1);
+      else
+       sigpause (SIGEMPTYMASK);
+#else /* not BSD, and not HPUX version >= 6 */
+#if defined (UNIPLUS)
+      if (0 > kill (pid, 0))
        break;
-      /* Otherwise wait 1 second or until a signal comes in.  */
-      signal (SIGALRM, wait_for_termination_signal);
-      alarm (1);
-      pause ();
-      alarm (0);
-      signal (SIGALRM, SIG_IGN);
+      wait (0);
+#else /* neither BSD nor UNIPLUS: random sysV */
+#ifdef POSIX_SIGNALS   /* would this work for LINUX as well? */
+      sigblock (sigmask (SIGCHLD));
+      if (0 > kill (pid, 0))
+       {
+         sigunblock (sigmask (SIGCHLD));
+         break;
+       }
+      sigpause (SIGEMPTYMASK);
+#else /* not POSIX_SIGNALS */
+#ifdef HAVE_SYSV_SIGPAUSE
+      sighold (SIGCHLD);
+      if (0 > kill (pid, 0))
+       {
+         sigrelse (SIGCHLD);
+         break;
+       }
+      sigpause (SIGCHLD);
+#else /* not HAVE_SYSV_SIGPAUSE */
+      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 HAVE_SYSV_SIGPAUSE */
+#endif /* not POSIX_SIGNALS */
+#endif /* not UNIPLUS */
+#endif /* not BSD, and not HPUX version >= 6 */
 #endif /* not VMS */
 #else /* not subprocesses */
 #ifndef BSD4_1
@@ -367,7 +456,7 @@ flush_pending_output (channel)
 #endif
 #endif
 }
-
+\f
 #ifndef VMS
 /*  Set up the terminal at the other end of a pseudo-terminal that
     we will be controlling an inferior through.
@@ -377,6 +466,7 @@ flush_pending_output (channel)
 child_setup_tty (out)
      int out;
 {
+#ifndef MSDOS
   struct emacs_tty s;
 
   EMACS_GET_TTY (out, &s);
@@ -384,16 +474,21 @@ child_setup_tty (out)
 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
   s.main.c_oflag |= OPOST;     /* Enable output postprocessing */
   s.main.c_oflag &= ~ONLCR;    /* Disable map of NL to CR-NL on output */
+#ifdef NLDLY
   s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
                                /* No output delays */
+#endif
   s.main.c_lflag &= ~ECHO;     /* Disable echo */
   s.main.c_lflag |= ISIG;      /* Enable signals */
-  s.main.c_iflag &= ~IUCLC;    /* Disable map of upper case to lower on
-                                  input */
-  s.main.c_oflag &= ~OLCUC;    /* Disable map of lower case to upper on
-                                  output */
+#ifdef IUCLC
+  s.main.c_iflag &= ~IUCLC;    /* Disable downcasing on input.  */
+#endif
+#ifdef OLCUC
+  s.main.c_oflag &= ~OLCUC;    /* Disable upcasing on output.  */
+#endif
+  s.main.c_cflag = (s.main.c_cflag & ~CSIZE) | CS8; /* Don't strip 8th bit */
 #if 0
-  /* Said to be unnecesary:  */
+  /* Said to be unnecessary:  */
   s.main.c_cc[VMIN] = 1;       /* minimum number of characters to accept  */
   s.main.c_cc[VTIME] = 0;      /* wait forever for at least 1 character  */
 #endif
@@ -417,11 +512,22 @@ child_setup_tty (out)
      don't ignore break, but don't signal either, so it looks like NUL.  */
   s.main.c_iflag &= ~IGNBRK;
   s.main.c_iflag &= ~BRKINT;
+  /* QUIT and INTR work better as signals, so disable character forms */
+  s.main.c_cc[VINTR] = 0377;
+#ifdef SIGNALS_VIA_CHARACTERS
+  /* the QUIT and INTR character are used in process_send_signal
+     so set them here to something useful.  */
+  if (s.main.c_cc[VQUIT] == 0377)
+    s.main.c_cc[VQUIT] = '\\'&037;     /* Control-\ */
+  if (s.main.c_cc[VINTR] == 0377)
+    s.main.c_cc[VINTR] = 'C'&037;      /* Control-C */
+#else /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
   /* QUIT and INTR work better as signals, so disable character forms */
   s.main.c_cc[VQUIT] = 0377;
   s.main.c_cc[VINTR] = 0377;
-  s.main.c_cc[VEOL] = 0377;
   s.main.c_lflag &= ~ISIG;
+#endif /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
+  s.main.c_cc[VEOL] = 0377;
   s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
 #endif /* AIX */
 
@@ -429,8 +535,10 @@ child_setup_tty (out)
 
   s.main.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE
                       | CBREAK | TANDEM);
+  s.main.sg_flags |= LPASS8;
   s.main.sg_erase = 0377;
   s.main.sg_kill = 0377;
+  s.lmode = LLITOUT | s.lmode;        /* Don't strip 8th bit */
 
 #endif /* not HAVE_TERMIO */
 
@@ -446,6 +554,7 @@ child_setup_tty (out)
     ioctl (out, FIOASYNC, &zero);
   }
 #endif /* RTU */
+#endif /* not MSDOS */
 }
 #endif /* not VMS */
 
@@ -457,7 +566,7 @@ setpgrp_of_tty (pid)
 {
   EMACS_SET_TTY_PGRP (input_fd, &pid);
 }
-
+\f
 /* Record a signal code and the handler for it.  */
 struct save_signal
 {
@@ -510,9 +619,12 @@ sys_suspend ()
     }
   return -1;
 #else
-#ifdef SIGTSTP
+#if defined(SIGTSTP) && !defined(MSDOS)
 
-  EMACS_KILLPG (getpgrp (0), SIGTSTP);
+  {
+    int pgrp = EMACS_GETPGRP (0);
+    EMACS_KILLPG (pgrp, SIGTSTP);
+  }
 
 #else /* No SIGTSTP */
 #ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */
@@ -524,8 +636,27 @@ sys_suspend ()
 /* On a system where suspending is not implemented,
    instead fork a subshell and let it talk directly to the terminal
    while we wait.  */
-  int pid = fork ();
+  sys_subshell ();
+
+#endif /* no USG_JOBCTRL */
+#endif /* no SIGTSTP */
+#endif /* not VMS */
+}
+
+/* Fork a subshell.  */
+
+sys_subshell ()
+{
+#ifndef VMS
+#ifdef MSDOS   /* Demacs 1.1.2 91/10/20 Manabu Higashida */
+  int st;
+  char oldwd[MAXPATHLEN+1]; /* Fixed length is safe on MSDOS.  */
+#endif
+  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;
@@ -537,65 +668,74 @@ sys_suspend ()
   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");
+  /* Can't use NILP */
+  if (XFASTINT (Fboundp (dir)) == XFASTINT (Qnil))
+    goto xyzzy;
+  dir = Fsymbol_value (dir);
+  if (XTYPE (dir) != Lisp_String)
+    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:
+
+  pid = vfork ();
+
   if (pid == -1)
     error ("Can't spawn subshell");
   if (pid == 0)
     {
       char *sh;
 
+#ifdef MSDOS   /* MW, Aug 1993 */
+      getwd (oldwd);
+#endif
       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 NULL */
-       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
 
-#ifdef PRIO_PROCESS
+#ifdef SET_EMACS_PRIORITY
       {
        extern int emacs_priority;
 
-       if (emacs_priority)
+       if (emacs_priority < 0)
          nice (-emacs_priority);
       }
 #endif
 
+#ifdef MSDOS   /* Demacs 1.1.2 91/10/20 Manabu Higashida */
+      st = system (sh);
+      chdir (oldwd);
+      if (st)
+        report_file_error ("Can't execute subshell", Fcons (build_string (sh), Qnil));
+#else /* not MSDOS */
       execlp (sh, sh, 0);
       write (1, "Can't execute subshell", 22);
       _exit (1);
+#endif /* not MSDOS */
     }
 
   save_signal_handlers (saved_handlers);
+  synch_process_alive = 1;
   wait_for_termination (pid);
   restore_signal_handlers (saved_handlers);
-
-#endif /* no USG_JOBCTRL */
-#endif /* no SIGTSTP */
-#endif /* not VMS */
+#endif /* !VMS */
 }
 
 save_signal_handlers (saved_handlers)
@@ -626,7 +766,7 @@ int old_fcntl_flags;
 init_sigio ()
 {
 #ifdef FASYNC
-  old_fcntl_flags = fcntl (0, F_GETFL, 0) & ~FASYNC;
+  old_fcntl_flags = fcntl (input_fd, F_GETFL, 0) & ~FASYNC;
 #endif
   request_sigio ();
 }
@@ -636,14 +776,14 @@ reset_sigio ()
   unrequest_sigio ();
 }
 
-#ifdef FASYNC          /* F_SETFL does not imply existance of FASYNC */
+#ifdef FASYNC          /* F_SETFL does not imply existence of FASYNC */
 
 request_sigio ()
 {
 #ifdef SIGWINCH
   sigunblock (sigmask (SIGWINCH));
 #endif
-  fcntl (0, F_SETFL, old_fcntl_flags | FASYNC);
+  fcntl (input_fd, F_SETFL, old_fcntl_flags | FASYNC);
 
   interrupts_deferred = 0;
 }
@@ -653,7 +793,7 @@ unrequest_sigio ()
 #ifdef SIGWINCH
   sigblock (sigmask (SIGWINCH));
 #endif
-  fcntl (0, F_SETFL, old_fcntl_flags);
+  fcntl (input_fd, F_SETFL, old_fcntl_flags);
   interrupts_deferred = 1;
 }
 
@@ -663,7 +803,7 @@ unrequest_sigio ()
 request_sigio ()
 {
   int on = 1;
-  ioctl (0, FIOASYNC, &on);
+  ioctl (input_fd, FIOASYNC, &on);
   interrupts_deferred = 0;
 }
 
@@ -671,12 +811,38 @@ unrequest_sigio ()
 {
   int off = 0;
 
-  ioctl (0, FIOASYNC, &off);
+  ioctl (input_fd, FIOASYNC, &off);
   interrupts_deferred = 1;
 }
 
 #else /* not FASYNC, not STRIDE */
  
+#ifdef _CX_UX
+
+#include <termios.h>
+
+request_sigio ()
+{
+  int on = 1;
+  sigset_t st;
+
+  sigemptyset(&st);
+  sigaddset(&st, SIGIO);
+  ioctl (input_fd, FIOASYNC, &on);
+  interrupts_deferred = 0;
+  sigprocmask(SIG_UNBLOCK, &st, (sigset_t *)0);
+}
+
+unrequest_sigio ()
+{
+  int off = 0;
+
+  ioctl (input_fd, FIOASYNC, &off);
+  interrupts_deferred = 1;
+}
+
+#else /* ! _CX_UX */
+
 request_sigio ()
 {
   croak ("request_sigio");
@@ -687,9 +853,209 @@ unrequest_sigio ()
   croak ("unrequest_sigio");
 }
  
+#endif /* _CX_UX */
 #endif /* STRIDE */
 #endif /* FASYNC */
 #endif /* F_SETFL */
+\f
+/* Saving and restoring the process group of Emacs's terminal.  */
+
+#ifdef BSD_PGRPS
+
+/* The process group of which Emacs was a member when it initially
+   started.
+
+   If Emacs was in its own process group (i.e. inherited_pgroup ==
+   getpid ()), then we know we're running under a shell with job
+   control (Emacs would never be run as part of a pipeline).
+   Everything is fine.
+
+   If Emacs was not in its own process group, then we know we're
+   running under a shell (or a caller) that doesn't know how to
+   separate itself from Emacs (like sh).  Emacs must be in its own
+   process group in order to receive SIGIO correctly.  In this
+   situation, we put ourselves in our own pgroup, forcibly set the
+   tty's pgroup to our pgroup, and make sure to restore and reinstate
+   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.  */
+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.  */
+narrow_foreground_group ()
+{
+  int me = getpid ();
+
+  setpgrp (0, inherited_pgroup);
+  if (inherited_pgroup != me)
+    EMACS_SET_TTY_PGRP (input_fd, &me);
+  setpgrp (0, me);
+}
+
+/* Set the tty to our original foreground group.  */
+widen_foreground_group ()
+{
+  if (inherited_pgroup != getpid ())
+    EMACS_SET_TTY_PGRP (input_fd, &inherited_pgroup);
+  setpgrp (0, inherited_pgroup);
+}
+
+#endif /* BSD_PGRPS */
+\f
+/* Getting and setting emacs_tty structures.  */
+
+/* Set *TC to the parameters associated with the terminal FD.
+   Return zero if all's well, or -1 if we ran into an error we
+   couldn't deal with.  */
+int
+emacs_get_tty (fd, settings)
+     int fd;
+     struct emacs_tty *settings;
+{
+  /* Retrieve the primary parameters - baud rate, character size, etcetera.  */
+#ifdef HAVE_TCATTR
+  /* We have those nifty POSIX tcmumbleattr functions.  */
+  if (tcgetattr (fd, &settings->main) < 0)
+    return -1;
+
+#else
+#ifdef HAVE_TERMIO
+  /* The SYSV-style interface?  */
+  if (ioctl (fd, TCGETA, &settings->main) < 0)
+    return -1;
+
+#else
+#ifdef VMS
+  /* Vehemently Monstrous System?  :-)  */
+  if (! (SYS$QIOW (0, fd, IO$_SENSEMODE, settings, 0, 0,
+                  &settings->main.class, 12, 0, 0, 0, 0)
+        & 1))
+    return -1;
+
+#else
+#ifndef MSDOS
+  /* I give up - I hope you have the BSD ioctls.  */
+  if (ioctl (fd, TIOCGETP, &settings->main) < 0)
+    return -1;
+#endif /* not MSDOS */
+#endif
+#endif
+#endif
+
+  /* Suivant - Do we have to get struct ltchars data?  */
+#ifdef HAVE_LTCHARS
+  if (ioctl (fd, TIOCGLTC, &settings->ltchars) < 0)
+    return -1;
+#endif
+
+  /* How about a struct tchars and a wordful of lmode bits?  */
+#ifdef HAVE_TCHARS
+  if (ioctl (fd, TIOCGETC, &settings->tchars) < 0
+      || ioctl (fd, TIOCLGET, &settings->lmode) < 0)
+    return -1;
+#endif
+
+  /* We have survived the tempest.  */
+  return 0;
+}
+
+
+/* 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.
+   Return 0 if all went well, and -1 if anything failed.  */
+int
+emacs_set_tty (fd, settings, waitp)
+     int fd;
+     struct emacs_tty *settings;
+     int waitp;
+{
+  /* Set the primary parameters - baud rate, character size, etcetera.  */
+#ifdef HAVE_TCATTR
+  int i;
+  /* We have those nifty POSIX tcmumbleattr functions.
+     William J. Smith <wjs@wiis.wang.com> writes:
+     "POSIX 1003.1 defines tcsetattr() to return success if it was
+     able to perform any of the requested actions, even if some
+     of the requested actions could not be performed.
+     We must read settings back to ensure tty setup properly.
+     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 (errno == EINTR)
+         continue;
+       else
+         return -1;
+      }
+    else
+      {
+       struct termios new;
+
+       /* Get the current settings, and see if they're what we asked for.  */
+       tcgetattr (fd, &new);
+       /* We cannot use memcmp on the whole structure here because under
+        * aix386 the termios structure has some reserved field that may
+        * not be filled in.
+        */
+       if (   new.c_iflag == settings->main.c_iflag
+           && new.c_oflag == settings->main.c_oflag
+           && new.c_cflag == settings->main.c_cflag
+           && new.c_lflag == settings->main.c_lflag
+           && memcmp(new.c_cc, settings->main.c_cc, NCCS) == 0)
+         break;
+       else
+         continue;
+      }
+
+#else
+#ifdef HAVE_TERMIO
+  /* The SYSV-style interface?  */
+  if (ioctl (fd, waitp ? TCSETAW : TCSETAF, &settings->main) < 0)
+    return -1;
+
+#else
+#ifdef VMS
+  /* Vehemently Monstrous System?  :-)  */
+  if (! (SYS$QIOW (0, fd, IO$_SETMODE, &input_iosb, 0, 0,
+                  &settings->main.class, 12, 0, 0, 0, 0)
+        & 1))
+    return -1;
+
+#else
+#ifndef MSDOS
+  /* I give up - I hope you have the BSD ioctls.  */
+  if (ioctl (fd, (waitp) ? TIOCSETP : TIOCSETN, &settings->main) < 0)
+    return -1;
+#endif /* not MSDOS */
+
+#endif
+#endif
+#endif
+
+  /* Suivant - Do we have to get struct ltchars data?  */
+#ifdef HAVE_LTCHARS
+  if (ioctl (fd, TIOCSLTC, &settings->ltchars) < 0)
+    return -1;
+#endif
+
+  /* How about a struct tchars and a wordful of lmode bits?  */
+#ifdef HAVE_TCHARS
+  if (ioctl (fd, TIOCSETC, &settings->tchars) < 0
+      || ioctl (fd, TIOCLSET, &settings->lmode) < 0)
+    return -1;
+#endif
+  
+  /* We have survived the tempest.  */
+  return 0;
+}
+
 \f
 /* The initial tty mode bits */
 struct emacs_tty old_tty;
@@ -702,9 +1068,11 @@ int term_initted;         /* 1 if outer tty status has been recorded */
 int lmode;
 #endif
 
+#ifndef F_SETOWN_BUG
 #ifdef F_SETOWN
 int old_fcntl_owner;
 #endif /* F_SETOWN */
+#endif /* F_SETOWN_BUG */
 
 /* This may also be defined in stdio,
    but if so, this does no harm,
@@ -716,10 +1084,10 @@ unsigned char _sobuf[BUFSIZ+8];
 char _sobuf[BUFSIZ];
 #endif
  
-#ifdef TIOCGLTC
+#ifdef HAVE_LTCHARS
 static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1};
 #endif
-#ifdef TIOCGETC
+#ifdef HAVE_TCHARS
   static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
 #endif 
 
@@ -769,6 +1137,11 @@ init_sys_modes ()
 #endif
 #endif /* not VMS */
 
+#ifdef BSD_PGRPS
+  if (! read_socket_hook && EQ (Vwindow_system, Qnil))
+    narrow_foreground_group ();
+#endif
+
   EMACS_GET_TTY (input_fd, &old_tty);
 
   if (!read_socket_hook && EQ (Vwindow_system, Qnil))
@@ -776,6 +1149,10 @@ init_sys_modes ()
       tty = old_tty;
 
 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
+#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 ISTRIP
@@ -784,7 +1161,7 @@ init_sys_modes ()
       tty.main.c_lflag &= ~ECHO;       /* Disable echo */
       tty.main.c_lflag &= ~ICANON;     /* Disable erase/kill processing */
 #ifdef IEXTEN
-      tty.main.c_iflag &= ~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)
@@ -827,6 +1204,24 @@ init_sys_modes ()
 #ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP.  */
       tty.main.c_cc[VDSUSP] = CDISABLE;
 #endif /* VDSUSP */
+#ifdef VLNEXT
+      tty.main.c_cc[VLNEXT] = CDISABLE;
+#endif /* VLNEXT */
+#ifdef VREPRINT
+      tty.main.c_cc[VREPRINT] = CDISABLE;
+#endif /* VREPRINT */
+#ifdef VWERASE
+      tty.main.c_cc[VWERASE] = CDISABLE;
+#endif /* VWERASE */
+#ifdef VDISCARD
+      tty.main.c_cc[VDISCARD] = CDISABLE;
+#endif /* VDISCARD */
+#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 AIX
 #ifndef IBMR2AIX
@@ -857,10 +1252,12 @@ 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
       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 VMS (BSD, that is) */
 #endif /* not HAVE_TERMIO */
 
@@ -870,7 +1267,7 @@ init_sys_modes ()
         control for user coming over network on 4.2; in this case,
         only t_stopc and t_startc really matter.  */
 #ifndef HAVE_TERMIO
-#ifdef TIOCGETC
+#ifdef HAVE_TCHARS
       /* Note: if not using CBREAK mode, it makes no difference how we
         set this */
       tty.tchars = new_tchars;
@@ -881,27 +1278,27 @@ init_sys_modes ()
          tty.tchars.t_stopc = '\023';
        }
 
-/* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits.  */
-#ifndef LPASS8
-#define LPASS8 0
-#endif
-
-#ifdef BSD4_1
-#define LNOFLSH 0100000
-#endif
-
       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
 
-#endif /* TIOCGETC */
+#endif /* HAVE_TCHARS */
 #endif /* not HAVE_TERMIO */
 
-#ifdef TIOCGLTC
+#ifdef HAVE_LTCHARS
       tty.ltchars = new_ltchars;
-#endif /* TIOCGLTC */
+#endif /* HAVE_LTCHARS */
+#ifdef MSDOS   /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
+      internal_terminal_init ();
+      dos_ttraw ();
+#endif
 
       EMACS_SET_TTY (input_fd, &tty, 0);
 
@@ -909,11 +1306,11 @@ init_sys_modes ()
         we have an unlocked terminal at the start. */
 
 #ifdef TCXONC
-      if (!flow_control) ioctl (0, TCXONC, 1);
+      if (!flow_control) ioctl (input_fd, TCXONC, 1);
 #endif
 #ifndef APOLLO
 #ifdef TIOCSTART
-      if (!flow_control) ioctl (0, TIOCSTART, 0);
+      if (!flow_control) ioctl (input_fd, TIOCSTART, 0);
 #endif
 #endif
 
@@ -941,14 +1338,17 @@ init_sys_modes ()
     }
 
 #ifdef F_SETFL
-#ifdef F_GETOWN                /* F_SETFL does not imply existance of F_GETOWN */
-  if (interrupt_input)
+#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))
     {
-      old_fcntl_owner = fcntl (0, F_GETOWN, 0);
-      fcntl (0, F_SETOWN, getpid ());
+      old_fcntl_owner = fcntl (input_fd, F_GETOWN, 0);
+      fcntl (input_fd, F_SETOWN, getpid ());
       init_sigio ();
     }
 #endif /* F_GETOWN */
+#endif /* F_SETOWN_BUG */
 #endif /* F_SETFL */
 
 #ifdef BSD4_1
@@ -967,7 +1367,9 @@ init_sys_modes ()
 #else
   setbuf (stdout, _sobuf);
 #endif
-  set_terminal_modes ();
+  if (! read_socket_hook && EQ (Vwindow_system, Qnil))
+    set_terminal_modes ();
+
   if (term_initted && no_redraw_on_reenter)
     {
       if (display_completed)
@@ -995,10 +1397,10 @@ tabs_safe_p ()
   EMACS_GET_TTY (input_fd, &tty);
   return EMACS_TTY_TABS_OK (&tty);
 }
-
+\f
 /* Get terminal size from system.
-   Store number of lines into *heightp and width into *widthp.
-   If zero or a negative number is stored, the value is not valid.  */
+   Store number of lines into *HEIGHTP and width into *WIDTHP.
+   We store 0 if there's no valid information.  */
 
 get_frame_size (widthp, heightp)
      int *widthp, *heightp;
@@ -1041,16 +1443,57 @@ get_frame_size (widthp, heightp)
   *widthp = tty.scr_wid;
   *heightp = tty.scr_len;
 
+#else
+#ifdef MSDOS
+  *widthp = ScreenCols ();
+  *heightp = ScreenRows ();
 #else /* system doesn't know size */
-
   *widthp = 0;
   *heightp = 0;
+#endif
 
 #endif /* not VMS */
 #endif /* not SunOS-style */
 #endif /* not BSD-style */
 }
 
+/* Set the logical window size associated with descriptor FD
+   to HEIGHT and WIDTH.  This is used mainly with ptys.  */
+
+int
+set_window_size (fd, height, width)
+     int fd, height, width;
+{
+#ifdef TIOCSWINSZ
+
+  /* BSD-style.  */
+  struct winsize size;
+  size.ws_row = height;
+  size.ws_col = width;
+
+  if (ioctl (fd, TIOCSWINSZ, &size) == -1)
+    return 0; /* error */
+  else
+    return 1;
+
+#else
+#ifdef TIOCSSIZE
+
+  /* SunOS - style.  */
+  struct ttysize size;  
+  size.ts_lines = height;
+  size.ts_cols = width;
+
+  if (ioctl (fd, TIOCGSIZE, &size) == -1)
+    return 0;
+  else
+    return 1;
+#else
+  return -1;
+#endif /* not SunOS-style */
+#endif /* not BSD-style */
+}
+
 \f
 /* Prepare the terminal for exiting Emacs; move the cursor to the
    bottom of the frame, turn off interrupt-driven I/O, etc.  */
@@ -1090,25 +1533,38 @@ reset_sys_modes ()
 #endif
 
 #ifdef F_SETFL
-#ifdef F_SETOWN                /* F_SETFL does not imply existance of F_SETOWN */
+#ifndef F_SETOWN_BUG
+#ifdef F_SETOWN                /* F_SETFL does not imply existence of F_SETOWN */
   if (interrupt_input)
     {
       reset_sigio ();
-      fcntl (0, F_SETOWN, old_fcntl_owner);
+      fcntl (input_fd, F_SETOWN, old_fcntl_owner);
     }
 #endif /* F_SETOWN */
+#endif /* F_SETOWN_BUG */
+#ifdef O_NDELAY
+  fcntl (input_fd, F_SETFL, fcntl (input_fd, F_GETFL, 0) & ~O_NDELAY);
+#endif
 #endif /* F_SETFL */
 #ifdef BSD4_1
   if (interrupt_input)
     reset_sigio ();
 #endif /* BSD4_1 */
 
-  while (! EMACS_SET_TTY (input_fd, &old_tty, 0) && errno == EINTR)
+  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
   hft_reset ();
 #endif
+
+#ifdef BSD_PGRPS
+  widen_foreground_group ();
+#endif
 }
 \f
 #ifdef HAVE_PTYS
@@ -1290,6 +1746,7 @@ wait_for_kbd_input ()
          if (dsp)
            {
              update_mode_lines++;
+             prepare_menu_bars ();
              redisplay_preserve_echo_area ();
            }
        }
@@ -1418,7 +1875,7 @@ unrequest_sigio ()
  *
  */
 
-#ifndef CANNOT_UNEXEC
+#if !defined (CANNOT_UNEXEC) && !defined (HAVE_TEXT_START)
 char *
 start_of_text ()
 {
@@ -1434,7 +1891,7 @@ start_of_text ()
 #endif /* GOULD */
 #endif /* TEXT_START */
 }
-#endif /* not CANNOT_UNEXEC */
+#endif /* not CANNOT_UNEXEC and not HAVE_TEXT_START */
 
 /*
  *     Return the address of the start of the data segment prior to
@@ -1523,77 +1980,127 @@ end_of_data ()
 
 #endif /* not CANNOT_DUMP */
 \f
-/* Get_system_name returns as its value
a string for the Lisp function system-name to return. */
+/* init_system_name sets up the string for the Lisp function
  system-name to return. */
 
 #ifdef BSD4_1
 #include <whoami.h>
 #endif
 
-/* Can't have this within the function since `static' is #defined to 
-   nothing for some USG systems.  */
-#ifdef USG
-#ifdef HAVE_GETHOSTNAME
-static char get_system_name_name[256];
-#else /* not HAVE_GETHOSTNAME */
-static struct utsname get_system_name_name;
-#endif /* not HAVE_GETHOSTNAME */
-#endif /* USG */
+extern Lisp_Object Vsystem_name;
 
-char *
-get_system_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 */
+
+void
+init_system_name ()
 {
-#ifdef USG
-#ifdef HAVE_GETHOSTNAME
-  gethostname (get_system_name_name, sizeof (get_system_name_name));
-  return get_system_name_name;
-#else /* not HAVE_GETHOSTNAME */
-  uname (&get_system_name_name);
-  return (get_system_name_name.nodename);
-#endif /* not HAVE_GETHOSTNAME */
-#else /* Not USG */
 #ifdef BSD4_1
-  return sysname;
-#else /* not USG, not 4.1 */
-  static char system_name_saved[32];
+  Vsystem_name = build_string (sysname);
+#else
 #ifdef VMS
-  char *sp;
+  char *sp, *end;
   if ((sp = egetenv ("SYS$NODE")) == 0)
-    sp = "vax-vms";
+    Vsystem_name = build_string ("vax-vms");
+  else if ((end = index (sp, ':')) == 0)
+    Vsystem_name = build_string (sp);
   else
+    Vsystem_name = make_string (sp, end - sp);
+#else
+#ifndef HAVE_GETHOSTNAME
+  struct utsname uts;
+  uname (&uts);
+  Vsystem_name = build_string (uts.nodename);
+#else /* HAVE_GETHOSTNAME */
+  int hostname_size = 256;
+  char *hostname = (char *) alloca (hostname_size);
+
+  /* Try to get the host name; if the buffer is too short, try
+     again.  Apparently, the only indication gethostname gives of
+     whether the buffer was large enough is the presence or absence
+     of a '\0' in the string.  Eech.  */
+  for (;;)
     {
-      char *end;
+      gethostname (hostname, hostname_size - 1);
+      hostname[hostname_size - 1] = '\0';
 
-      if ((end = index (sp, ':')) != 0)
-       *end = '\0';
+      /* Was the buffer large enough for the '\0'?  */
+      if (strlen (hostname) < hostname_size - 1)
+       break;
+
+      hostname_size <<= 1;
+      hostname = (char *) alloca (hostname_size);
     }
-  strcpy (system_name_saved, sp);
-#else /* not VMS */
-  gethostname (system_name_saved, sizeof (system_name_saved));
-#endif /* not VMS */
-  return system_name_saved;
-#endif /* not USG, not 4.1 */
-#endif /* not USG */
-}
+#ifdef HAVE_SOCKETS
+  /* Turn the hostname into the official, fully-qualified hostname.
+     Don't do this if we're going to dump; this can confuse system
+     libraries on some machines and make the dumped emacs core dump. */
+#ifndef CANNOT_DUMP
+  if (initialized)
+#endif /* not CANNOT_DUMP */
+    {
+      struct hostent *hp;
+      int count;
+      for (count = 0; count < 10; count++)
+       {
+#ifdef TRY_AGAIN
+         h_errno = 0;
+#endif
+         hp = gethostbyname (hostname);
+#ifdef TRY_AGAIN
+         if (! (hp == 0 && h_errno == TRY_AGAIN))
+#endif
+           break;
+         Fsleep_for (make_number (1), Qnil);
+       }
+      if (hp)
+       {
+         char *fqdn = hp->h_name;
+         char *p;
 
-#ifdef VMS
-#ifndef HAVE_GETHOSTNAME
-void gethostname(buf, len)
-    char *buf;
-    int len;
-{
-    char *s;
-    s = getenv ("SYS$NODE");
-    if (s == NULL)
-        buf[0] = '\0';
-    else {
-        strncpy (buf, s, len - 2);
-        buf[len - 1] = '\0';
-    } /* else */
-} /* static void gethostname */
-#endif /* ! HAVE_GETHOSTNAME */
+         if (!index (fqdn, '.'))
+           {
+             /* We still don't have a fully qualified domain name.
+                Try to find one in the list of alternate names */
+             char **alias = hp->h_aliases;
+             while (*alias && !index (*alias, '.'))
+               alias++;
+             if (*alias)
+               fqdn = *alias;
+           }
+         hostname = fqdn;
+#if 0
+         /* Convert the host name to lower case.  */
+         /* Using ctype.h here would introduce a possible locale
+            dependence that is probably wrong for hostnames.  */
+         p = hostname;
+         while (*p)
+           {
+             if (*p >= 'A' && *p <= 'Z')
+               *p += 'a' - 'A';
+             p++;
+           }
+#endif
+       }
+    }
+#endif /* HAVE_SOCKETS */
+  Vsystem_name = build_string (hostname);
+#endif /* HAVE_GETHOSTNAME */
 #endif /* VMS */
-
+#endif /* BSD4_1 */
+  {
+    unsigned char *p;
+    for (p = XSTRING (Vsystem_name)->data; *p; p++)
+      if (*p == ' ' || *p == '\t')
+       *p = '-';
+  }
+}
 \f
 #ifndef VMS
 #ifndef HAVE_SELECT
@@ -1694,6 +2201,9 @@ select (nfds, rfds, wfds, efds, timeout)
 #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)
@@ -1704,6 +2214,7 @@ 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)
@@ -1724,6 +2235,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.  */
@@ -1735,6 +2250,7 @@ select (nfds, rfds, wfds, efds, timeout)
            }
          else
            pause ();
+#endif /* not MSDOS */
        }
       (*local_timeout) -= SELECT_PAUSE;
       /* Reset the old alarm if there was one */
@@ -1767,33 +2283,60 @@ select (nfds, rfds, wfds, efds, timeout)
 
 read_input_waiting ()
 {
-  char buf[256 * BUFFER_SIZE_FACTOR];
   struct input_event e;
   int nread, i;
   extern int quit_char;
 
   if (read_socket_hook)
     {
+      struct input_event buf[256];
+
       read_alarm_should_throw = 0;
       if (! setjmp (read_alarm_throw))
-       nread = (*read_socket_hook) (0, buf, 256 * BUFFER_SIZE_FACTOR, 1, 0);
+       nread = (*read_socket_hook) (0, buf, 256, 1, 0);
       else
        nread = -1;
+
+      /* Scan the chars for C-g and store them in kbd_buffer.  */
+      for (i = 0; i < nread; i++)
+       {
+         kbd_buffer_store_event (&buf[i]);
+         /* 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)
+           break;
+       }
     }
   else
-    nread = read (fileno (stdin), buf, 1);
-
-  /* Scan the chars for C-g and store them in kbd_buffer.  */
-  e.kind = ascii_keystroke;
-  e.frame_or_window = selected_frame;
-  for (i = 0; i < nread; i++)
     {
-      XSET (e.code, Lisp_Int, 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.  */
-      if (buf[i] == quit_char)
-       break;
+      char buf[3];
+      nread = read (fileno (stdin), buf, 1);
+
+      /* Scan the chars for C-g and store them in kbd_buffer.  */
+      e.kind = ascii_keystroke;
+      e.frame_or_window = selected_frame;
+      e.modifiers = 0;
+      for (i = 0; i < nread; i++)
+       {
+         /* Convert chars > 0177 to meta events if desired.
+            We do this under the same conditions that read_avail_input does.  */
+         if (read_socket_hook == 0)
+           {
+             /* If the user says she has a meta key, then believe her. */
+             if (meta_key == 1 && (buf[i] & 0x80))
+               e.modifiers = meta_modifier;
+             if (meta_key != 2)
+               buf[i] &= ~0x80;
+           }
+
+         XSET (e.code, Lisp_Int, 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.  */
+         if (buf[i] == quit_char)
+           break;
+       }
     }
 }
 
@@ -1901,14 +2444,10 @@ static struct sigaction new_action, old_action;
 
 init_signals ()
 {
-#ifdef POSIX_SIGNALS
-  sigemptyset (&signal_empty_mask);
-  sigfillset (&signal_full_mask);
-#endif
+  sigemptyset (&empty_mask);
+  sigfillset (&full_mask);
 }
 
-int (*signal_handler_t) ();
-
 signal_handler_t
 sys_signal (int signal_number, signal_handler_t action)
 {
@@ -1919,7 +2458,14 @@ sys_signal (int signal_number, signal_handler_t action)
 #else
   sigemptyset (&new_action.sa_mask);
   new_action.sa_handler = action;
-  new_action.sa_flags = NULL;
+#ifdef SA_RESTART
+  /* Emacs mostly works better with restartable system services. If this
+   * flag exists, we probably want to turn it on here.
+   */
+  new_action.sa_flags = SA_RESTART;
+#else
+  new_action.sa_flags = 0;
+#endif
   sigaction (signal_number, &new_action, &old_action);
   return (old_action.sa_handler);
 #endif /* DGUX */
@@ -1979,6 +2525,8 @@ sys_sigsetmask (sigset_t new_mask)
 \f
 #ifndef BSTRING
 
+#ifndef bzero
+
 void
 bzero (b, length)
      register char *b;
@@ -2001,6 +2549,9 @@ bzero (b, length)
 #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)
@@ -2024,7 +2575,9 @@ bcopy (b1, b2, length)
     *b2++ = *b1++;
 #endif /* not VMS */
 }
+#endif /* no bcopy */
 
+#ifndef bcmp
 int
 bcmp (b1, b2, length)  /* This could be a macro! */
      register char *b1;
@@ -2044,10 +2597,13 @@ bcmp (b1, b2, length)   /* This could be a macro! */
   return 0;
 #endif /* not VMS */
 }
+#endif /* no bcmp */
+
 #endif /* not BSTRING */
 \f
 #ifndef HAVE_RANDOM
-#ifdef USG
+#ifndef random 
+
 /*
  *     The BSD random returns numbers in the range of
  *     0 to 2e31 - 1.  The USG rand returns numbers in the
@@ -2058,32 +2614,33 @@ bcmp (b1, b2, length)   /* This could be a macro! */
 long
 random ()
 {
-  /* Arrange to return a range centered on zero.  */
-  return (rand () << 15) + rand () - (1 << 29);
+#ifdef HAVE_LRAND48
+  return lrand48 ();
+#else
+/* The BSD rand returns numbers in the range of 0 to 2e31 - 1,
+   with unusable least significant bits.  The USG rand returns
+   numbers in the range of 0 to 2e15 - 1, all usable.  Let us
+   build a usable 30 bit number from either.  */
+#ifdef USG
+  return (rand () << 15) + rand ();
+#else
+  return (rand () & 0x3fff8000) + (rand () >> 16);
+#endif
+#endif
 }
 
 srandom (arg)
      int arg;
 {
+#ifdef HAVE_LRAND48
+  return srand48 ();
+#else
   srand (arg);
+#endif
 }
 
-#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
+#endif /* no random */
+#endif /* not HAVE_RANDOM */
 \f
 #ifdef WRONG_NAME_INSQUE
 
@@ -2152,7 +2709,7 @@ sys_abort ()
 #ifdef VMS
 #ifdef LINK_CRTL_SHARE
 #ifdef SHAREABLE_LIB_BUG
-/* Variables declared noshare and initialized in shareable libraries
+/* 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
    could use the C library definition of sys_nerr and sys_errlist. */
@@ -2200,6 +2757,21 @@ char *sys_errlist[] =
 #endif /* SHAREABLE_LIB_BUG */
 #endif /* LINK_CRTL_SHARE */
 #endif /* VMS */
+
+#ifndef HAVE_STRERROR
+char *
+strerror (errnum)
+     int errnum;
+{
+  extern char *sys_errlist[];
+  extern int sys_nerr;
+
+  if (errnum >= 0 && errnum < sys_nerr)
+    return sys_errlist[errnum];
+  return (char *) "Unknown error";
+}
+
+#endif /* ! HAVE_STRERROR */
 \f
 #ifdef INTERRUPTIBLE_OPEN
 
@@ -2253,15 +2825,44 @@ sys_write (fildes, buf, nbyte)
      char *buf;
      unsigned int nbyte;
 {
-  register int rtnval;
+  register int rtnval, bytes_written;
 
-  while ((rtnval = write (fildes, buf, nbyte)) == -1
-        && (errno == EINTR));
-  return (rtnval);
+  bytes_written = 0;
+
+  while (nbyte > 0)
+    {
+      rtnval = write (fildes, buf, nbyte);
+
+      if (rtnval == -1)
+       {
+         if (errno == EINTR)
+           continue;
+         else
+           return (bytes_written ? bytes_written : -1);
+       }
+
+      buf += rtnval;
+      nbyte -= rtnval;
+      bytes_written += rtnval;
+    }
+  return (bytes_written);
 }
 
 #endif /* INTERRUPTIBLE_IO */
 \f
+#ifndef HAVE_VFORK
+
+/*
+ *     Substitute fork for vfork on USG flavors.
+ */
+
+vfork ()
+{
+  return (fork ());
+}
+
+#endif /* not HAVE_VFORK */
+\f
 #ifdef USG
 /*
  *     All of the following are for USG.
@@ -2273,11 +2874,12 @@ sys_write (fildes, buf, nbyte)
  *     to names for our own functions in sysdep.c that do the system call
  *     with retries.  Actually, for portability reasons, it is good
  *     programming practice, as this example shows, to limit all actual
- *     system calls to a single occurance in the source.  Sure, this
+ *     system calls to a single occurrence in the source.  Sure, this
  *     adds an extra level of function call overhead but it is almost
  *     always negligible.   Fred Fish, Unisoft Systems Inc.
  */
 
+#ifndef HAVE_SYS_SIGLIST
 char *sys_siglist[NSIG + 1] =
 {
 #ifdef AIX
@@ -2335,9 +2937,32 @@ char *sys_siglist[NSIG + 1] =
   "user defined signal 2",             /* 17 SIGUSR2 */
   "death of a child",                  /* 18 SIGCLD */
   "power-fail restart",                        /* 19 SIGPWR */
+#ifdef sun
+  "window size change",                            /* 20 SIGWINCH */
+  "urgent socket condition",               /* 21 SIGURG */
+  "pollable event occured",                /* 22 SIGPOLL */
+  "stop (cannot be caught or ignored)", /*  23 SIGSTOP */
+  "user stop requested from tty",          /* 24 SIGTSTP */
+  "stopped process has been continued",        /* 25 SIGCONT */
+  "background tty read attempted",         /* 26 SIGTTIN */
+  "background tty write attempted",    /* 27 SIGTTOU */
+  "virtual timer expired",                 /* 28 SIGVTALRM */
+  "profiling timer expired",               /* 29 SIGPROF */
+  "exceeded cpu limit",                            /* 30 SIGXCPU */
+  "exceeded file size limit",              /* 31 SIGXFSZ */
+  "process's lwps are blocked",            /*  32 SIGWAITING */
+  "special signal used by thread library", /* 33 SIGLWP */
+#ifdef SIGFREEZE
+  "Special Signal Used By CPR",            /* 34 SIGFREEZE */
+#endif
+#ifdef SIGTHAW
+  "Special Signal Used By CPR",            /* 35 SIGTHAW */
+#endif
+#endif /* sun */
 #endif /* not AIX */
   0
   };
+#endif /* HAVE_SYS_SIGLIST */
 
 /*
  *     Warning, this function may not duplicate 4.2 action properly
@@ -2360,6 +2985,8 @@ getwd (pathname)
 
   BLOCK_INPUT;                 /* getcwd uses malloc */
   spath = npath = getcwd ((char *) 0, MAXPATHLEN);
+  if (spath == 0)
+    return spath;
   /* On Altos 3068, getcwd can return @hostname/dir, so discard
      up to first slash.  Should be harmless on other systems.  */
   while (*npath && *npath != '/')
@@ -2381,8 +3008,8 @@ getwd (pathname)
 #ifndef HAVE_RENAME
 
 rename (from, to)
-     char *from;
-     char *to;
+     const char *from;
+     const char *to;
 {
   if (access (from, 0) == 0)
     {
@@ -2396,19 +3023,6 @@ rename (from, to)
 
 #endif
 
-#ifndef HAVE_VFORK
-
-/*
- *     Substitute fork for vfork on USG flavors.
- */
-
-vfork ()
-{
-  return (fork ());
-}
-
-#endif /* not HAVE_VFORK */
-
 #ifdef MISSING_UTIMES
 
 /* HPUX (among others) sets HAVE_TIMEVAL but does not implement utimes.  */
@@ -2473,7 +3087,7 @@ dup2 (oldd, newd)
 #ifdef F_DUPFD
   fd = fcntl (oldd, F_DUPFD, newd);
   if (fd != newd)
-    error ("can't dup2 (%i,%i) : %s", oldd, newd, sys_errlist[errno]);
+    error ("can't dup2 (%i,%i) : %s", oldd, newd, strerror (errno));
 #else
   fd = dup (old);
   if (fd == -1)
@@ -2508,7 +3122,8 @@ gettimeofday (tp, tzp)
 
   tp->tv_sec = time ((long *)0);    
   tp->tv_usec = 0;
-  tzp->tz_minuteswest = -1;
+  if (tzp != 0)
+    tzp->tz_minuteswest = -1;
 }
  
 #endif
@@ -2556,7 +3171,7 @@ char *sys_siglist[NSIG + 1] =
   "power-fail restart",                         /* 19 SIGPWR    */
   "window size changed",                /* 20 SIGWINCH  */
   "undefined",                          /* 21           */
-  "pollable event occured",             /* 22 SIGPOLL   */
+  "pollable event occurred",            /* 22 SIGPOLL   */
   "sendable stop signal not from tty",  /* 23 SIGSTOP   */
   "stop signal from tty",               /* 24 SIGSTP    */
   "continue a stopped process",                 /* 25 SIGCONT   */
@@ -2610,16 +3225,27 @@ char *sys_siglist[NSIG + 1] =
 
 #include <dirent.h>
 
-#ifndef AIX
+#if defined(BROKEN_CLOSEDIR) || !defined(HAVE_CLOSEDIR)
+
 int
 closedir (dirp)
      register DIR *dirp;              /* stream from opendir */
 {
-  sys_close (dirp->dd_fd);
-  xfree ((char *) dirp->dd_buf);       /* directory block defined in <dirent.h> */
+  int rtnval;
+
+  rtnval = sys_close (dirp->dd_fd);
+
+  /* Some systems (like Solaris) allocate the buffer and the DIR all
+     in one block.  Why in the world are we freeing this ourselves
+     anyway?  */
+#if ! (defined (sun) && defined (USG5_4))
+  xfree ((char *) dirp->dd_buf); /* directory block defined in <dirent.h> */
+#endif
   xfree ((char *) dirp);
+
+  return rtnval;
 }
-#endif /* not AIX */
+#endif /* BROKEN_CLOSEDIR or not HAVE_CLOSEDIR */
 #endif /* SYSV_SYSTEM_DIR */
 
 #ifdef NONSYSTEM_DIR_LIBRARY
@@ -2765,6 +3391,138 @@ readdirver (dirp)
 #endif /* VMS */
 
 #endif /* NONSYSTEM_DIR_LIBRARY */
+
+\f
+/* mkdir and rmdir functions, for systems which don't have them.  */
+
+#ifndef HAVE_MKDIR
+/*
+ * Written by Robert Rother, Mariah Corporation, August 1985.
+ *
+ * If you want it, it's yours.  All I ask in return is that if you
+ * figure out how to do this in a Bourne Shell script you send me
+ * a copy.
+ *                                     sdcsvax!rmr or rmr@uscd
+ *
+ * Severely hacked over by John Gilmore to make a 4.2BSD compatible
+ * subroutine. 11Mar86; hoptoad!gnu
+ *
+ * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
+ * subroutine didn't return EEXIST.  It does now.
+ */
+
+/*
+ * Make a directory.
+ */
+#ifdef MKDIR_PROTOTYPE
+MKDIR_PROTOTYPE
+#else
+int
+mkdir (dpath, dmode)
+     char *dpath;
+     int dmode;
+#endif
+{
+  int cpid, status, fd;
+  struct stat statbuf;
+
+  if (stat (dpath, &statbuf) == 0)
+    {
+      errno = EEXIST;          /* Stat worked, so it already exists */
+      return -1;
+    }
+
+  /* If stat fails for a reason other than non-existence, return error */
+  if (errno != ENOENT)
+    return -1;
+
+  synch_process_alive = 1;
+  switch (cpid = fork ())
+    {
+
+    case -1:                   /* Error in fork */
+      return (-1);             /* Errno is set already */
+
+    case 0:                    /* Child process */
+      /*
+                * Cheap hack to set mode of new directory.  Since this
+                * child process is going away anyway, we zap its umask.
+                * FIXME, this won't suffice to set SUID, SGID, etc. on this
+                * directory.  Does anybody care?
+                */
+      status = umask (0);      /* Get current umask */
+      status = umask (status | (0777 & ~dmode));       /* Set for mkdir */
+      fd = sys_open("/dev/null", 2);
+      if (fd >= 0)
+        {
+         dup2 (fd, 0);
+         dup2 (fd, 1);
+         dup2 (fd, 2);
+        }
+      execl ("/bin/mkdir", "mkdir", dpath, (char *) 0);
+      _exit (-1);              /* Can't exec /bin/mkdir */
+
+    default:                   /* Parent process */
+      wait_for_termination (cpid);
+    }
+
+  if (synch_process_death != 0 || synch_process_retcode != 0)
+    {
+      errno = EIO;             /* We don't know why, but */
+      return -1;               /* /bin/mkdir failed */
+    }
+
+  return 0;
+}
+#endif /* not HAVE_MKDIR */
+
+#ifndef HAVE_RMDIR
+int
+rmdir (dpath)
+     char *dpath;
+{
+  int cpid, status, fd;
+  struct stat statbuf;
+
+  if (stat (dpath, &statbuf) != 0)
+    {
+      /* Stat just set errno.  We don't have to */
+      return -1;
+    }
+
+  synch_process_alive = 1;
+  switch (cpid = fork ())
+    {
+
+    case -1:                   /* Error in fork */
+      return (-1);             /* Errno is set already */
+
+    case 0:                    /* Child process */
+      fd = sys_open("/dev/null", 2);
+      if (fd >= 0)
+        {
+         dup2 (fd, 0);
+         dup2 (fd, 1);
+         dup2 (fd, 2);
+        }
+      wait_for_termination (cpid);
+  if (synch_process_death != 0 || synch_process_retcode != 0)
+      return -1;               /* /bin/rmdir failed */
+    default:                   /* Parent process */
+      while (cpid != wait (&status));  /* Wait for kid to finish */
+    }
+
+  if (WIFSIGNALED (status) || WEXITSTATUS (status) != 0)
+    {
+      errno = EIO;             /* We don't know why, but */
+      return -1;               /* /bin/mkdir failed */
+    }
+
+  return 0;
+}
+#endif /* !HAVE_RMDIR */
+
+
 \f
 /* Functions for VMS */
 #ifdef VMS
@@ -3117,13 +3875,18 @@ char *
 getwd (pathname)
      char *pathname;
 {
-  char *ptr;
+  char *ptr, *val;
   extern char *getcwd ();
 
 #define MAXPATHLEN 1024
 
   ptr = xmalloc (MAXPATHLEN);
-  getcwd (ptr, MAXPATHLEN);
+  val = getcwd (ptr, MAXPATHLEN);
+  if (val == 0)
+    {
+      xfree (ptr);
+      return val;
+    }
   strcpy (pathname, ptr);
   xfree (ptr);
   
@@ -3328,7 +4091,7 @@ creat_copy_attrs (old, new)
 sys_creat (va_alist)
      va_dcl
 {
-  va_list list_incrementor;
+  va_list list_incrementer;
   char *name;
   int mode;
   int rfd;                     /* related file descriptor */
@@ -3342,12 +4105,12 @@ sys_creat (va_alist)
   extern int vms_stmlf_recfm;
 
   va_count (count);
-  va_start (list_incrementor);
-  name = va_arg (list_incrementor, char *);
-  mode = va_arg (list_incrementor, int);
+  va_start (list_incrementer);
+  name = va_arg (list_incrementer, char *);
+  mode = va_arg (list_incrementer, int);
   if (count > 2)
-    rfd = va_arg (list_incrementor, int);
-  va_end (list_incrementor);
+    rfd = va_arg (list_incrementer, int);
+  va_end (list_incrementer);
   if (count > 2)
     {
       /* Use information from the related file descriptor to set record
@@ -3856,7 +4619,7 @@ rename (from, to)
    are renaming.
 
    We could use the chmod function, but Eunichs uses 3 bits per user category
-   to describe the protection, and VMS uses 4 (write and delete are seperate
+   to describe the protection, and VMS uses 4 (write and delete are separate
    bits).  To maintain portability, the VMS implementation of `chmod' wires
    the W and D bits together.  */