(read_process_output): Deactivate the mark.
[bpt/emacs.git] / src / process.c
index 018adf1..91e411e 100644 (file)
@@ -1,11 +1,11 @@
 /* Asynchronous subprocess control for GNU Emacs.
-   Copyright (C) 1985, 1986, 1987, 1988, 1992 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1987, 1988, 1993 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,
@@ -48,58 +48,21 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #if defined(BSD) || defined(STRIDE)
 #include <sys/ioctl.h>
-#if !defined (O_NDELAY) && defined (HAVE_PTYS)
+#if !defined (O_NDELAY) && defined (HAVE_PTYS) && !defined(USG5)
 #include <fcntl.h>
 #endif /* HAVE_PTYS and no O_NDELAY */
 #endif /* BSD or STRIDE */
-#ifdef USG
-#ifdef HAVE_TERMIOS
-#include <termios.h>
-#else
-#include <termio.h>
-#endif
-#include <fcntl.h>
-#endif /* USG */
 
 #ifdef NEED_BSDTTY
 #include <bsdtty.h>
 #endif
 
-#ifdef HPUX
-#undef TIOCGPGRP
-#endif
-
 #ifdef IRIS
 #include <sys/sysmacros.h>     /* for "minor" */
 #endif /* not IRIS */
 
 #include "systime.h"
-
-#if defined (HPUX) && defined (HAVE_PTYS)
-#include <sys/ptyio.h>
-#endif
-
-#ifdef AIX
-#include <sys/pty.h>
-#include <unistd.h>
-#endif
-
-#ifdef SYSV_PTYS
-#include <sys/tty.h>
-#ifdef titan
-#include <sys/ttyhw.h>
-#include <sys/stream.h>
-#endif
-#include <sys/pty.h>
-#endif
-
-#ifdef XENIX
-#undef TIOCGETC  /* Avoid confusing some conditionals that test this.  */
-#endif
-
-#ifdef BROKEN_TIOCGETC
-#undef TIOCGETC
-#endif
+#include "systty.h"
 
 #include "lisp.h"
 #include "window.h"
@@ -108,8 +71,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "termhooks.h"
 #include "termopts.h"
 #include "commands.h"
-
-extern int screen_garbaged;
+#include "frame.h"
 
 Lisp_Object Qrun, Qstop, Qsignal, Qopen, Qclosed;
 /* Qexit is declared and initialized in eval.c.  */
@@ -148,16 +110,17 @@ static Lisp_Object stream_process;
 
 #ifndef VMS
 #ifndef WAITTYPE
-#if !defined (BSD) && !defined (UNIPLUS) && !defined (STRIDE) && !(defined (HPUX) && !defined (NOMULTIPLEJOBS)) && !defined (HAVE_WAIT_HEADER)
-mis;tak-+;;:
+#if (!defined (BSD) && !defined (UNIPLUS) && !defined (STRIDE) && !(defined (HPUX) && !defined (NOMULTIPLEJOBS)) && !defined (HAVE_WAIT_HEADER)) || defined (LINUX)
 #define WAITTYPE int
 #define WIFSTOPPED(w) ((w&0377) == 0177)
 #define WIFSIGNALED(w) ((w&0377) != 0177 && (w&~0377) == 0)
 #define WIFEXITED(w) ((w&0377) == 0)
 #define WRETCODE(w) (w >> 8)
 #define WSTOPSIG(w) (w >> 8)
-#define WCOREDUMP(w) ((w&0200) != 0)
 #define WTERMSIG(w) (w & 0377)
+#ifndef WCOREDUMP
+#define WCOREDUMP(w) ((w&0200) != 0)
+#endif
 #else 
 #ifdef BSD4_1
 #include <wait.h>
@@ -196,10 +159,14 @@ mis;tak-+;;:
 #endif /* BSD or UNIPLUS or STRIDE */
 #endif /* no WAITTYPE */
 #else /* VMS */
-
-/* For the CMU PTY driver + */
-#define DCL_PROMPT "$ "
-
+#define WAITTYPE int
+#define WIFSTOPPED(w) 0
+#define WIFSIGNALED(w) 0
+#define WIFEXITED(w) ((w) != -1)
+#define WRETCODE(w) (w)
+#define WSTOPSIG(w) (w)
+#define WCOREDUMP(w) 0
+#define WTERMSIG(w) (w)
 #include <ssdef.h>
 #include <iodef.h>
 #include <clidef.h>
@@ -212,7 +179,9 @@ extern char *sys_errlist[];
 
 #ifndef VMS
 #ifndef BSD4_1
+#ifndef LINUX
 extern char *sys_siglist[];
+#endif
 #else
 char *sys_siglist[] =
   {
@@ -246,13 +215,6 @@ char *sys_siglist[] =
 #endif
 #endif /* VMS */
 
-#ifdef vipc
-
-#include "vipc.h"
-extern int comm_server;
-extern int net_listen_address;
-#endif /* vipc */
-
 /* t means use pty, nil means use a pipe,
    maybe other values to come.  */
 Lisp_Object Vprocess_connection_type;
@@ -273,7 +235,11 @@ int update_tick;
 /* We could get this from param.h, but better not to depend on finding that.
    And better not to risk that it might define other symbols used in this
    file.  */
+#ifdef FD_SETSIZE
+#define MAXDESC FD_SETSIZE
+#else
 #define MAXDESC 64
+#endif
 #define SELECT_TYPE fd_set
 #else /* no FD_SET */
 #define MAXDESC 32
@@ -313,6 +279,8 @@ int proc_buffered_char[MAXDESC];
 /* Compute the Lisp form of the process status, p->status, from
    the numeric status that was returned by `wait'.  */
 
+Lisp_Object status_convert ();
+
 update_status (p)
      struct Lisp_Process *p;
 {
@@ -365,7 +333,7 @@ decode_status (l, symbol, code, coredump)
       *symbol = XCONS (l)->car;
       tem = XCONS (l)->cdr;
       *code = XFASTINT (XCONS (tem)->car);
-      tem = XFASTINT (XCONS (tem)->cdr);
+      tem = XCONS (tem)->cdr;
       *coredump = !NILP (tem);
     }
 }
@@ -384,7 +352,11 @@ status_message (status)
 
   if (EQ (symbol, Qsignal) || EQ (symbol, Qstop))
     {
+#ifndef VMS
       string = build_string (code < NSIG ? sys_siglist[code] : "unknown");
+#else
+      string = build_string (code < NSIG ? sys_errlist[code] : "unknown");
+#endif
       string2 = build_string (coredump ? " (core dumped)\n" : "\n");
       XSTRING (string)->data[0] = DOWNCASE (XSTRING (string)->data[0]);
       return concat2 (string, string2);
@@ -393,7 +365,7 @@ status_message (status)
     {
       if (code == 0)
        return build_string ("finished\n");
-      string = Fint_to_string (make_number (code));
+      string = Fnumber_to_string (make_number (code));
       string2 = build_string (coredump ? " (core dumped)\n" : "\n");
       return concat2 (build_string ("exited abnormally with code "),
                      concat2 (string, string2));
@@ -403,7 +375,6 @@ status_message (status)
 }
 \f
 #ifdef HAVE_PTYS
-static pty_process;
 
 /* Open an available pty, returning a file descriptor.
    Return -1 on failure.
@@ -419,6 +390,13 @@ allocate_pty ()
   register c, i;
   int fd;
 
+  /* Some systems name their pseudoterminals so that there are gaps in
+     the usual sequence - for example, on HP9000/S700 systems, there
+     are no pseudoterminals with names ending in 'f'.  So we wait for
+     three failures in a row before deciding that we've reached the
+     end of the ptys.  */
+  int failed_count = 0;
+
 #ifdef PTY_ITERATION
   PTY_ITERATION
 #else
@@ -428,33 +406,36 @@ allocate_pty ()
       {
 #ifdef PTY_NAME_SPRINTF
        PTY_NAME_SPRINTF
-#else
-#ifdef HPUX
-       sprintf (pty_name, "/dev/ptym/pty%c%x", c, i);
-#else
-#ifdef RTU
-       sprintf (pty_name, "/dev/pty%x", i);
 #else
        sprintf (pty_name, "/dev/pty%c%x", c, i);
-#endif /* not RTU */
-#endif /* not HPUX */
 #endif /* no PTY_NAME_SPRINTF */
 
-#ifndef IRIS
-       if (stat (pty_name, &stb) < 0)
+#ifdef PTY_OPEN
+       PTY_OPEN;
+#else /* no PTY_OPEN */
+#ifdef IRIS
+       /* Unusual IRIS code */
+       *ptyv = open ("/dev/ptc", O_RDWR | O_NDELAY, 0);
+       if (fd < 0)
+         return -1;
+       if (fstat (fd, &stb) < 0)
          return -1;
+#else /* not IRIS */
+       if (stat (pty_name, &stb) < 0)
+         {
+           failed_count++;
+           if (failed_count >= 3)
+             return -1;
+         }
+       else
+         failed_count = 0;
 #ifdef O_NONBLOCK
        fd = open (pty_name, O_RDWR | O_NONBLOCK, 0);
 #else
        fd = open (pty_name, O_RDWR | O_NDELAY, 0);
 #endif
-#else /* Unusual IRIS code */
-       *ptyv = open ("/dev/ptc", O_RDWR | O_NDELAY, 0);
-       if (fd < 0)
-         return -1;
-       if (fstat (fd, &stb) < 0)
-         return -1;
-#endif /* IRIS */
+#endif /* not IRIS */
+#endif /* no PTY_OPEN */
 
        if (fd >= 0)
          {
@@ -462,27 +443,14 @@ allocate_pty ()
               this avoids a nasty yet stupid bug in rlogins */
 #ifdef PTY_TTY_NAME_SPRINTF
            PTY_TTY_NAME_SPRINTF
-#else
-           /* TODO: In version 19, make these special cases use the macro above.  */
-#ifdef HPUX
-            sprintf (pty_name, "/dev/pty/tty%c%x", c, i);
-#else
-#ifdef RTU
-            sprintf (pty_name, "/dev/ttyp%x", i);
-#else
-#ifdef IRIS
-           sprintf (pty_name, "/dev/ttyq%d", minor (stb.st_rdev));
 #else
             sprintf (pty_name, "/dev/tty%c%x", c, i);
-#endif /* not IRIS */
-#endif /* not RTU */
-#endif /* not HPUX */
 #endif /* no PTY_TTY_NAME_SPRINTF */
 #ifndef UNIPLUS
            if (access (pty_name, 6) != 0)
              {
                close (fd);
-#ifndef IRIS
+#if !defined(IRIS) && !defined(__sgi)
                continue;
 #else
                return -1;
@@ -595,7 +563,10 @@ BUFFER may be a buffer or the name of one.")
   return Qnil;
 }
 
-/* This is how commands for the user decode process arguments */
+/* This is how commands for the user decode process arguments.  It
+   accepts a process, a process name, a buffer, a buffer name, or nil.
+   Buffers denote the first process in the buffer, and nil denotes the
+   current buffer.  */
 
 Lisp_Object
 get_process (name)
@@ -623,7 +594,8 @@ get_process (name)
 
 DEFUN ("delete-process", Fdelete_process, Sdelete_process, 1, 1, 0,
   "Delete PROCESS: kill it and forget about it immediately.\n\
-PROCESS may be a process or the name of one, or a buffer name.")
+PROCESS may be a process, a buffer, the name of a process or buffer, or\n\
+nil, indicating the current buffer's process.")
   (proc)
      register Lisp_Object proc;
 {
@@ -656,7 +628,9 @@ exit -- for a process that has exited.\n\
 signal -- for a process that has got a fatal signal.\n\
 open -- for a network stream connection that is open.\n\
 closed -- for a network stream connection that is closed.\n\
-nil -- if arg is a process name and no such process exists.")
+nil -- if arg is a process name and no such process exists.\n\
+PROCESS may be a process, a buffer, the name of a process or buffer, or\n\
+nil, indicating the current buffer's process.")
 /* command -- for a command channel opened to Emacs by another process.\n\
    external -- for an i/o channel opened to Emacs by another process.\n\  */
   (proc)
@@ -664,7 +638,7 @@ nil -- if arg is a process name and no such process exists.")
 {
   register struct Lisp_Process *p;
   register Lisp_Object status;
-  proc = Fget_process (proc);
+  proc = get_process (proc);
   if (NILP (proc))
     return proc;
   p = XPROCESS (proc);
@@ -880,7 +854,7 @@ Proc         Status   Buffer         Command\n\
          tem = Fcar (Fcdr (p->status));
 #ifdef VMS
          if (XINT (tem) < NSIG)
-           write_string (sys_siglist [XINT (tem)], -1);
+           write_string (sys_errlist [XINT (tem)], -1);
          else
 #endif
            Fprinc (symbol, Qnil);
@@ -963,6 +937,10 @@ DEFUN ("process-list", Fprocess_list, Sprocess_list, 0, 0, 0,
   return Fmapcar (Qcdr, Vprocess_alist);
 }
 \f
+/* Starting asynchronous inferior processes.  */
+
+static Lisp_Object start_process_unwind ();
+
 DEFUN ("start-process", Fstart_process, Sstart_process, 3, MANY, 0,
   "Start a program in a subprocess.  Return the process object for it.\n\
 Args are NAME BUFFER PROGRAM &rest PROGRAM-ARGS\n\
@@ -978,7 +956,7 @@ Remaining arguments are strings to give program as arguments.")
      int nargs;
      register Lisp_Object *args;
 {
-  Lisp_Object buffer, name, program, proc, tem;
+  Lisp_Object buffer, name, program, proc, current_dir, tem;
 #ifdef VMS
   register unsigned char *new_argv;
   int len;
@@ -986,11 +964,38 @@ Remaining arguments are strings to give program as arguments.")
   register unsigned char **new_argv;
 #endif
   register int i;
+  int count = specpdl_ptr - specpdl;
 
   buffer = args[1];
   if (!NILP (buffer))
     buffer = Fget_buffer_create (buffer);
 
+  /* Make sure that the child will be able to chdir to the current
+     buffer's current directory, or its unhandled equivalent.  We
+     can't just have the child check for an error when it does the
+     chdir, since it's in a vfork.
+
+     We have to GCPRO around this because Fexpand_file_name and
+     Funhandled_file_name_directory might call a file name handling
+     function.  The argument list is protected by the caller, so all
+     we really have to worry about is buffer.  */
+  {
+    struct gcpro gcpro1, gcpro2;
+
+    current_dir = current_buffer->directory;
+
+    GCPRO2 (buffer, current_dir);
+
+    current_dir = 
+      expand_and_dir_to_file
+       (Funhandled_file_name_directory (current_dir), Qnil);
+    if (NILP (Ffile_accessible_directory_p (current_dir)))
+      report_file_error ("Setting current directory",
+                        Fcons (current_buffer->directory, Qnil));
+
+    UNGCPRO;
+  }
+
   name = args[0];
   CHECK_STRING (name, 0);
 
@@ -1017,6 +1022,8 @@ Remaining arguments are strings to give program as arguments.")
       strcat (new_argv, " ");
       strcat (new_argv, XSTRING (tem)->data);
     }
+  /* Need to add code here to check for program existence on VMS */
+  
 #else /* not VMS */
   new_argv = (unsigned char **) alloca ((nargs - 1) * sizeof (char *));
 
@@ -1033,7 +1040,7 @@ Remaining arguments are strings to give program as arguments.")
   if (new_argv[0][0] != '/')
     {
       tem = Qnil;
-      openp (Vexec_path, program, "", &tem, 1);
+      openp (Vexec_path, program, EXEC_SUFFIXES, &tem, 1);
       if (NILP (tem))
        report_file_error ("Searching for program", Fcons (program, Qnil));
       new_argv[0] = XSTRING (tem)->data;
@@ -1041,6 +1048,11 @@ Remaining arguments are strings to give program as arguments.")
 #endif /* not VMS */
 
   proc = make_process (name);
+  /* If an error occurs and we can't start the process, we want to
+     remove it from the process list.  This means that each error
+     check in create_process doesn't need to call remove_process
+     itself; it's all taken care of here.  */
+  record_unwind_protect (start_process_unwind, proc);
 
   XPROCESS (proc)->childp = Qt;
   XPROCESS (proc)->command_channel_p = Qnil;
@@ -1049,11 +1061,30 @@ Remaining arguments are strings to give program as arguments.")
   XPROCESS (proc)->filter = Qnil;
   XPROCESS (proc)->command = Flist (nargs - 2, args + 2);
 
-  create_process (proc, new_argv);
+  create_process (proc, new_argv, current_dir);
 
-  return proc;
+  return unbind_to (count, proc);
 }
 
+/* This function is the unwind_protect form for Fstart_process.  If
+   PROC doesn't have its pid set, then we know someone has signalled
+   an error and the process wasn't started successfully, so we should
+   remove it from the process list.  */
+static Lisp_Object
+start_process_unwind (proc)
+     Lisp_Object proc;
+{
+  if (XTYPE (proc) != Lisp_Process)
+    abort ();
+
+  /* Was PROC started successfully?  */
+  if (XPROCESS (proc)->pid <= 0)
+    remove_process (proc);
+
+  return Qnil;
+}
+
+
 SIGTYPE
 create_process_1 (signo)
      int signo;
@@ -1085,9 +1116,10 @@ create_process_sigchld ()
 #endif
 
 #ifndef VMS /* VMS version of this function is in vmsproc.c.  */
-create_process (process, new_argv)
+create_process (process, new_argv, current_dir)
      Lisp_Object process;
      char **new_argv;
+     Lisp_Object current_dir;
 {
   int pid, inchannel, outchannel, forkin, forkout;
   int sv[2];
@@ -1095,26 +1127,14 @@ create_process (process, new_argv)
   SIGTYPE (*sigchld)();
 #endif
   int pty_flag = 0;
-  Lisp_Object current_dir;
-  char **env;
   extern char **environ;
 
-  env = environ;
-
   inchannel = outchannel = -1;
 
 #ifdef HAVE_PTYS
   if (EQ (Vprocess_connection_type, Qt))
     outchannel = inchannel = allocate_pty ();
 
-  /* Make sure that the child will be able to chdir to the current
-     buffer's current directory.  We can't just have the child check
-     for an error when it does the chdir, since it's in a vfork.  */
-  current_dir = expand_and_dir_to_file (current_buffer->directory, Qnil);
-  if (NILP (Ffile_accessible_directory_p (current_dir)))
-    report_file_error ("Setting current directory",
-                      Fcons (current_buffer->directory, Qnil));
-
   if (inchannel >= 0)
     {
 #ifndef USG 
@@ -1237,6 +1257,13 @@ create_process (process, new_argv)
        /* First, disconnect its current controlling terminal.  */
 #ifdef HAVE_SETSID
        setsid ();
+#ifdef TIOCSCTTY
+       /* Make the pty's terminal the controlling terminal.  */
+       if (pty_flag)
+         /* We ignore the return value
+            because faith@cs.unc.edu says that is necessary on Linux.  */
+         ioctl (xforkin, TIOCSCTTY, 0);
+#endif
 #else /* not HAVE_SETSID */
 #ifdef USG
        /* It's very important to call setpgrp() here and no time
@@ -1298,24 +1325,23 @@ create_process (process, new_argv)
 #if defined (BSD) || defined (UNIPLUS) || defined (HPUX)
        sigsetmask (SIGEMPTYMASK);
 #else /* ordinary USG */
+#if 0
        signal (SIGCHLD, sigchld);
+#endif
 #endif /* ordinary USG */
 #endif /* not BSD4_1 */
 #endif /* SIGCHLD */
 
        child_setup_tty (xforkout);
        child_setup (xforkin, xforkout, xforkout,
-                    new_argv, env, 1, current_dir);
+                    new_argv, 1, current_dir);
       }
     environ = save_environ;
   }
 
   if (pid < 0)
-    {
-      remove_process (process);
-      report_file_error ("Doing vfork", Qnil);
-    }
-
+    report_file_error ("Doing vfork", Qnil);
+  
   XFASTINT (XPROCESS (process)->pid) = pid;
 
   FD_SET (inchannel, &input_wait_mask);
@@ -1430,8 +1456,13 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\
       host_info.h_name = 0;
       host_info.h_aliases = 0;
       host_info.h_addrtype = AF_INET;
-      host_info.h_addr_list  =  &(addr_list[0]);
-      addr_list[0] = (char*)(&numeric_addr);
+#ifdef h_addr
+      /* Older machines have only one address slot called h_addr.
+        Newer machines have h_addr_list, but #define h_addr to
+        be its first element.  */
+      host_info.h_addr_list = &(addr_list[0]);
+#endif
+      host_info.h_addr = (char*)(&numeric_addr);
       addr_list[1] = 0;
       host_info.h_length = strlen (addr_list[0]);
     }
@@ -1511,7 +1542,7 @@ deactivate_process (proc)
       {
        VMS_PROC_STUFF *get_vms_process_pointer (), *vs;
        sys$dassgn (outchannel);
-       vs = get_vms_process_pointer (p->pid)
+       vs = get_vms_process_pointer (p->pid);
        if (vs)
          give_back_vms_process_stuff (vs);
       }
@@ -1590,6 +1621,8 @@ Return non-nil iff we received any output before the timeout expired.")
          }
       }
     }
+  else
+    useconds = 0;
 
   if (! NILP (timeout))
     {
@@ -1606,10 +1639,11 @@ Return non-nil iff we received any output before the timeout expired.")
        seconds = 0;
     }
 
+  if (NILP (proc))
+    XFASTINT (proc) = 0;
+
   return
-    (wait_reading_process_input (seconds, useconds,
-                                (NILP (proc)
-                                 ? XPROCESS (get_process (proc)) : 0), 0)
+    (wait_reading_process_input (seconds, useconds, proc, 0)
      ? Qt : Qnil);
 }
 
@@ -1629,14 +1663,19 @@ static int waiting_for_user_input_p;
      zero for no limit, or
      -1 means gobble data immediately available but don't wait for any.
 
-   read_kbd is:
+   microsecs is:
+     an additional duration to wait (if time_limit is greater than
+     zero), specified in millisec.
+
+   read_kbd is a lisp value:
      0 to ignore keyboard input, or
      1 to return when input is available, or
-     -1 means caller will actually read the input, so don't throw to
+     -1 meaning caller will actually read the input, so don't throw to
        the quit handler, or
-     a pointer to a struct Lisp_Process, meaning wait until something
-       arrives from that process.  The return value is true iff we read
-       some input from that process.
+     a cons cell, meaning wait wait until its car is non-nil, or
+     a process object, meaning wait until something arrives from that
+       process.  The return value is true iff we read some input from
+       that process.
 
    do_display != 0 means redisplay should be done to show subprocess
    output that arrives.
@@ -1647,7 +1686,9 @@ static int waiting_for_user_input_p;
    Otherwise, return true iff we recieved input from any process.  */
 
 wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
-     int time_limit, microsecs, read_kbd, do_display;
+     int time_limit, microsecs;
+     Lisp_Object read_kbd;
+     int do_display;
 {
   register int channel, nfds, m;
   static SELECT_TYPE Available;
@@ -1658,18 +1699,27 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
   int wait_channel = 0;
   struct Lisp_Process *wait_proc = 0;
   int got_some_input = 0;
+  Lisp_Object *wait_for_cell = 0;
 
   FD_ZERO (&Available);
 
-  /* Detect when read_kbd is really the address of a Lisp_Process.  */
-  if (read_kbd > 10 || read_kbd < -1)
+  /* If read_kbd is a process to watch, set wait_proc and wait_channel
+     accordingly.  */
+  if (XTYPE (read_kbd) == Lisp_Process)
     {
-      wait_proc = (struct Lisp_Process *) read_kbd;
+      wait_proc = XPROCESS (read_kbd);
       wait_channel = XFASTINT (wait_proc->infd);
-      read_kbd = 0;
+      XFASTINT (read_kbd) = 0;
+    }
+
+  /* If waiting for non-nil in a cell, record where.  */
+  if (XTYPE (read_kbd) == Lisp_Cons)
+    {
+      wait_for_cell = &XCONS (read_kbd)->car;
+      XFASTINT (read_kbd) = 0;
     }
 
-  waiting_for_user_input_p = read_kbd;
+  waiting_for_user_input_p = XINT (read_kbd);
 
   /* Since we may need to wait several times,
      compute the absolute time to return at.  */
@@ -1680,35 +1730,14 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
       EMACS_ADD_TIME (end_time, end_time, timeout);
     }
 
-  /* Turn off periodic alarms (in case they are in use)
-     because the select emulator uses alarms.  */
-  stop_polling ();
-
   while (1)
     {
       /* If calling from keyboard input, do not quit
         since we want to return C-g as an input character.
         Otherwise, do pending quit if requested.  */
-      if (read_kbd >= 0)
+      if (XINT (read_kbd) >= 0)
        QUIT;
 
-      /* If status of something has changed, and no input is available,
-        notify the user of the change right away */
-      if (update_tick != process_tick && do_display)
-       {
-         Atemp = input_wait_mask;
-         EMACS_SET_SECS_USECS (timeout, 0, 0);
-         if (select (MAXDESC, &Atemp, 0, 0, &timeout) <= 0)
-           status_notify ();
-       }
-
-      /* Don't wait for output from a non-running process.  */
-      if (wait_proc != 0 && !NILP (wait_proc->raw_status_low))
-       update_status (wait_proc);
-      if (wait_proc != 0
-         && ! EQ (wait_proc->status, Qrun))
-       break;
-
       /* Compute time from now till when time limit is up */
       /* Exit if already run out */
       if (time_limit == -1)
@@ -1732,22 +1761,56 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
        }
 
       /* Cause C-g and alarm signals to take immediate action,
-        and cause input available signals to zero out timeout */
-      if (read_kbd < 0)
+        and cause input available signals to zero out timeout.
+
+        It is important that we do this before checking for process
+        activity.  If we get a SIGCHLD after the explicit checks for
+        process activity, timeout is the only way we will know.  */
+      if (XINT (read_kbd) < 0)
        set_waiting_for_input (&timeout);
 
+      /* If status of something has changed, and no input is
+        available, notify the user of the change right away.  After
+        this explicit check, we'll let the SIGCHLD handler zap
+        timeout to get our attention.  */
+      if (update_tick != process_tick && do_display)
+       {
+         Atemp = input_wait_mask;
+         EMACS_SET_SECS_USECS (timeout, 0, 0);
+         if (select (MAXDESC, &Atemp, 0, 0, &timeout) <= 0)
+           {
+             /* It's okay for us to do this and then continue with
+                the loop, since timeout has already been zeroed out. */
+             clear_waiting_for_input ();
+             status_notify ();
+           }
+       }
+
+      /* Don't wait for output from a non-running process.  */
+      if (wait_proc != 0 && !NILP (wait_proc->raw_status_low))
+       update_status (wait_proc);
+      if (wait_proc != 0
+         && ! EQ (wait_proc->status, Qrun))
+       {
+         clear_waiting_for_input ();
+         break;
+       }
+
       /* Wait till there is something to do */
 
       Available = input_wait_mask;
-      if (!read_kbd)
+      if (! XINT (read_kbd))
        FD_CLR (0, &Available);
 
-      /* If a screen has been newly mapped and needs updating,
-        reprocess its display stuff.  */
-      if (screen_garbaged)
+      /* If frame size has changed or the window is newly mapped,
+        redisplay now, before we start to wait.  There is a race
+        condition here; if a SIGIO arrives between now and the select
+        and indicates that a frame is trashed, the select may block
+        displaying a trashed screen.  */
+      if (frame_garbaged)
        redisplay_preserve_echo_area ();
 
-      if (read_kbd && detect_input_pending ())
+      if (XINT (read_kbd) && detect_input_pending ())
        nfds = 0;
       else
        nfds = select (MAXDESC, &Available, 0, 0, &timeout);
@@ -1760,12 +1823,21 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
       /*  If we woke up due to SIGWINCH, actually change size now.  */
       do_pending_window_change ();
 
-      if (time_limit && nfds == 0)     /* timeout elapsed */
+      if (time_limit && nfds == 0) /* timeout elapsed */
        break;
       if (nfds < 0)
        {
          if (xerrno == EINTR)
            FD_ZERO (&Available);
+#ifdef ultrix
+         /* Ultrix select seems to return ENOMEM when it is
+            interrupted.  Treat it just like EINTR.  Bleah.  Note
+            that we want to test for the "ultrix" CPP symbol, not
+            "__ultrix__"; the latter is only defined under GCC, but
+            not by DEC's bundled CC.  -JimB  */
+         else if (xerrno == ENOMEM)
+           FD_ZERO (&Available);
+#endif
 #ifdef ALLIANT
          /* This happens for no known reason on ALLIANT.
             I am guessing that this is the right response. -- RMS.  */
@@ -1782,7 +1854,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
                 So, SIGHUP is ignored (see def of PTY_TTY_NAME_SPRINTF
                 in m-ibmrt-aix.h), and here we just ignore the select error.
                 Cleanup occurs c/o status_notify after SIGCLD. */
-             FD_ZERO (&Available);          /* Cannot depend on values returned */
+             FD_ZERO (&Available); /* Cannot depend on values returned */
 #else
              abort ();
 #endif
@@ -1790,9 +1862,15 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
          else
            error("select error: %s", sys_errlist[xerrno]);
        }
-#ifdef sun
+#if defined(sun) && !defined(USG5_4)
       else if (nfds > 0 && FD_ISSET (0, &Available) && interrupt_input)
-       /* System sometimes fails to deliver SIGIO.  */
+       /* System sometimes fails to deliver SIGIO.
+
+          David J. Mackenzie says that Emacs doesn't compile under
+          Solaris if this code is enabled, thus the USG5_4 in the CPP
+          conditional.  "I haven't noticed any ill effects so far.
+          If you find a Solaris expert somewhere, they might know
+          better." */
        kill (getpid (), SIGIO);
 #endif
 
@@ -1800,33 +1878,35 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
       /* If there is any, return immediately
         to give it higher priority than subprocesses */
 
-      if (read_kbd && detect_input_pending ())
+      if (XINT (read_kbd) && detect_input_pending ())
+       {
+         swallow_events ();
+         if (detect_input_pending ())
+           break;
+       }
+
+      /* Exit now if the cell we're waiting for became non-nil.  */
+      if (wait_for_cell && ! NILP (*wait_for_cell))
        break;
 
+#ifdef SIGIO
       /* If we think we have keyboard input waiting, but didn't get SIGIO
         go read it.  This can happen with X on BSD after logging out.
         In that case, there really is no input and no SIGIO,
         but select says there is input.  */
 
-      /*
-      if (read_kbd && interrupt_input && (Available & fileno (stdin)))
-      */
-      if (read_kbd && interrupt_input && (FD_ISSET (fileno (stdin), &Available)))
+      if (XINT (read_kbd) && interrupt_input && (FD_ISSET (fileno (stdin), &Available)))
        kill (0, SIGIO);
-
-#ifdef vipc
-      /* Check for connection from other process */
-
-      if (Available & ChannelMask (comm_server))
-       {
-         Available &= ~(ChannelMask (comm_server));
-         create_commchan ();
-       }
-#endif vipc
+#endif
 
       if (! wait_proc)
        got_some_input |= nfds > 0;
 
+      /* If checking input just got us a size-change event from X,
+        obey it now if we should.  */
+      if (XINT (read_kbd))
+       do_pending_window_change ();
+
       /* Check for data from a process or a command channel */
       for (channel = FIRST_PROC_DESC; channel < MAXDESC; channel++)
        {
@@ -1847,24 +1927,6 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
              if (NILP (proc))
                continue;
 
-#ifdef vipc
-             /* It's a command channel */
-             if (!NILP (XPROCESS (proc)->command_channel_p))
-               {
-                 ProcessCommChan (channel, proc);
-                 if (NILP (XPROCESS (proc)->command_channel_p))
-                   {
-                     /* It has ceased to be a command channel! */
-                     int bytes_available;
-                     if (ioctl (channel, FIONREAD, &bytes_available) < 0)
-                       bytes_available = 0;
-                     if (bytes_available)
-                       FD_SET (channel, &Available);
-                   }
-                 continue;
-               }
-#endif /* vipc */
-
              /* Read data from the process, starting with our
                 buffered-ahead character if we have one.  */
 
@@ -1897,9 +1959,9 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
                 subprocess termination and SIGCHLD.  */
              else if (nread == 0 && !NETCONN_P (proc))
                ;
-#endif /* O_NDELAY */
-#endif /* O_NONBLOCK */
-#endif /* EWOULDBLOCK */
+#endif                         /* O_NDELAY */
+#endif                         /* O_NONBLOCK */
+#endif                         /* EWOULDBLOCK */
 #ifdef HAVE_PTYS
              /* On some OSs with ptys, when the process on one end of
                 a pty exits, the other end gets an error reading with
@@ -1910,9 +1972,9 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
                 get a SIGCHLD). */
              else if (nread == -1 && errno == EIO)
                ;
-#endif /* HAVE_PTYS */
-/* If we can detect process termination, don't consider the process
-   gone just because its pipe is closed.  */
+#endif                         /* HAVE_PTYS */
+             /* If we can detect process termination, don't consider the process
+                gone just because its pipe is closed.  */
 #ifdef SIGCHLD
              else if (nread == 0 && !NETCONN_P (proc))
                ;
@@ -1929,11 +1991,18 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
                      = Fcons (Qexit, Fcons (make_number (256), Qnil));
                }
            }
-       } /* end for each file descriptor */
-    } /* end while exit conditions not met */
+       }                       /* end for each file descriptor */
+    }                          /* end while exit conditions not met */
 
-  /* Resume periodic signals to poll for input, if necessary.  */
-  start_polling ();
+  /* If calling from keyboard input, do not quit
+     since we want to return C-g as an input character.
+     Otherwise, do pending quit if requested.  */
+  if (XINT (read_kbd) >= 0)
+    {
+      /* Prevent input_pending from remaining set if we quit.  */
+      clear_input_pending ();
+      QUIT;
+    }
 
   return got_some_input;
 }
@@ -2006,9 +2075,25 @@ read_process_output (proc, channel)
         hitting ^G when a filter happens to be running won't screw
         it up.  */
       int count = specpdl_ptr - specpdl;
+      Lisp_Object odeactivate;
+
+      odeactivate = Vdeactivate_mark;
+
       specbind (Qinhibit_quit, Qt);
       call2 (outstream, proc, make_string (chars, nchars));
 
+      /* Deactivate the mark now, so it doesn't happen
+        *after* the following command.  */
+      if (!NILP (current_buffer->mark_active))
+       {
+         if (!NILP (Vdeactivate_mark) && !NILP (Vtransient_mark_mode))
+           {
+             current_buffer->mark_active = Qnil;
+             call1 (Vrun_hooks, intern ("deactivate-mark-hook"));
+           }
+       }
+      Vdeactivate_mark = odeactivate;
+
 #ifdef VMS
       start_vms_process_read (vs);
 #endif
@@ -2019,10 +2104,19 @@ read_process_output (proc, channel)
   /* If no filter, write into buffer if it isn't dead.  */
   if (!NILP (p->buffer) && !NILP (XBUFFER (p->buffer)->name))
     {
-      Lisp_Object tem;
+      Lisp_Object old_read_only;
+      Lisp_Object old_begv, old_zv;
+      Lisp_Object odeactivate;
+
+      odeactivate = Vdeactivate_mark;
 
       Fset_buffer (p->buffer);
       opoint = point;
+      old_read_only = current_buffer->read_only;
+      XFASTINT (old_begv) = BEGV;
+      XFASTINT (old_zv) = ZV;
+
+      current_buffer->read_only = Qnil;
 
       /* Insert new output into buffer
         at the current end-of-output marker,
@@ -2031,18 +2125,48 @@ read_process_output (proc, channel)
        SET_PT (marker_position (p->mark));
       else
        SET_PT (ZV);
+
+      /* If the output marker is outside of the visible region, save
+        the restriction and widen.  */
+      if (! (BEGV <= point && point <= ZV))
+       Fwiden ();
+
+      /* Make sure opoint floats ahead of any new text, just as point
+        would.  */
       if (point <= opoint)
        opoint += nchars;
 
-      tem = current_buffer->read_only;
-      current_buffer->read_only = Qnil;
+      /* Insert after old_begv, but before old_zv.  */
+      if (point < XFASTINT (old_begv))
+       XFASTINT (old_begv) += nchars;
+      if (point <= XFASTINT (old_zv))
+       XFASTINT (old_zv) += nchars;
+
       /* Insert before markers in case we are inserting where
         the buffer's mark is, and the user's next command is Meta-y.  */
       insert_before_markers (chars, nchars);
-      current_buffer->read_only = tem;
       Fset_marker (p->mark, make_number (point), p->buffer);
+
       update_mode_lines++;
 
+      /* If the restriction isn't what it should be, set it.  */
+      if (XFASTINT (old_begv) != BEGV || XFASTINT (old_zv) != ZV)
+       Fnarrow_to_region (old_begv, old_zv);
+
+      /* Deactivate the mark now, so it doesn't happen
+        *after* the following command.  */
+      if (!NILP (current_buffer->mark_active))
+       {
+         if (!NILP (Vdeactivate_mark) && !NILP (Vtransient_mark_mode))
+           {
+             current_buffer->mark_active = Qnil;
+             call1 (Vrun_hooks, intern ("deactivate-mark-hook"));
+           }
+       }
+
+      Vdeactivate_mark = odeactivate;
+
+      current_buffer->read_only = old_read_only;
       SET_PT (opoint);
       set_buffer_internal (old);
     }
@@ -2106,12 +2230,14 @@ send_process (proc, buf, len)
     while (len > 0)
       {
        int this = len;
+       SIGTYPE (*old_sigpipe)();
+
        /* Don't send more than 500 bytes at a time.  */
        if (this > 500)
          this = 500;
-       signal (SIGPIPE, send_process_trap);
+       old_sigpipe = (SIGTYPE (*) ()) signal (SIGPIPE, send_process_trap);
        rv = write (XFASTINT (XPROCESS (proc)->outfd), buf, this);
-       signal (SIGPIPE, SIG_DFL);
+       signal (SIGPIPE, old_sigpipe);
        if (rv < 0)
          {
            if (0
@@ -2139,7 +2265,12 @@ send_process (proc, buf, len)
        /* Allow input from processes between bursts of sending.
           Otherwise things may get stopped up.  */
        if (len > 0)
-         wait_reading_process_input (-1, 0, 0, 0);
+         {
+           Lisp_Object zero;
+
+           XFASTINT (zero) = 0;
+           wait_reading_process_input (-1, 0, zero, 0);
+         }
       }
 #endif
   else
@@ -2160,7 +2291,8 @@ send_process (proc, buf, len)
 DEFUN ("process-send-region", Fprocess_send_region, Sprocess_send_region,
   3, 3, 0,
   "Send current contents of region as input to PROCESS.\n\
-PROCESS may be a process name or an actual process.\n\
+PROCESS may be a process, a buffer, the name of a process or buffer, or\n\
+nil, indicating the current buffer's process.\n\
 Called from program, takes three arguments, PROCESS, START and END.\n\
 If the region is more than 500 characters long,\n\
 it is sent in several bunches.  This may happen even for shorter regions.\n\
@@ -2186,7 +2318,8 @@ Output from processes can arrive in between bunches.")
 DEFUN ("process-send-string", Fprocess_send_string, Sprocess_send_string,
   2, 2, 0,
   "Send PROCESS the contents of STRING as input.\n\
-PROCESS may be a process name or an actual process.\n\
+PROCESS may be a process, a buffer, the name of a process or buffer, or\n\
+nil, indicating the current buffer's process.\n\
 If STRING is more than 500 characters long,\n\
 it is sent in several bunches.  This may happen even for shorter strings.\n\
 Output from processes can arrive in between bunches.")
@@ -2205,8 +2338,13 @@ Output from processes can arrive in between bunches.")
    the terminal being used to communicate with PROCESS.
    This is used for various commands in shell mode.
    If NOMSG is zero, insert signal-announcements into process's buffers
-   right away.  */
+   right away.
 
+   If we can, we try to signal PROCESS by sending control characters
+   down the pipe.  This allows us to signal inferiors who have changed
+   their uid, for which killpg would return an EPERM error.  */
+
+static void
 process_send_signal (process, signo, current_group, nomsg)
      Lisp_Object process;
      int signo;
@@ -2231,13 +2369,46 @@ process_send_signal (process, signo, current_group, nomsg)
   if (NILP (p->pty_flag))
     current_group = Qnil;
 
-#ifdef TIOCGPGRP               /* Not sure about this! (fnf) */
   /* If we are using pgrps, get a pgrp number and make it negative.  */
   if (!NILP (current_group))
     {
+#ifdef SIGNALS_VIA_CHARACTERS
       /* If possible, send signals to the entire pgrp
         by sending an input character to it.  */
+
+      /* TERMIOS is the latest and bestest, and seems most likely to
+         work.  If the system has it, use it.  */
+#ifdef HAVE_TERMIOS
+      struct termios t;
+
+      switch (signo)
+       {
+       case SIGINT:
+         tcgetattr (XFASTINT (p->infd), &t);
+         send_process (proc, &t.c_cc[VINTR], 1);
+         return;
+
+       case SIGQUIT:
+         tcgetattr (XFASTINT (p->infd), &t);
+         send_process (proc, &t.c_cc[VQUIT], 1);
+         return;
+
+       case SIGTSTP:
+         tcgetattr (XFASTINT (p->infd), &t);
+#ifdef VSWTCH
+         send_process (proc, &t.c_cc[VSWTCH], 1);
+#else
+         send_process (proc, &t.c_cc[VSUSP], 1);
+#endif
+         return;
+       }
+
+#else /* ! HAVE_TERMIOS */
+
+      /* On Berkeley descendants, the following IOCTL's retrieve the
+        current control characters.  */
 #if defined (TIOCGLTC) && defined (TIOCGETC)
+
       struct tchars c;
       struct ltchars lc;
 
@@ -2246,45 +2417,57 @@ process_send_signal (process, signo, current_group, nomsg)
        case SIGINT:
          ioctl (XFASTINT (p->infd), TIOCGETC, &c);
          send_process (proc, &c.t_intrc, 1);
-         return Qnil;
+         return;
        case SIGQUIT:
          ioctl (XFASTINT (p->infd), TIOCGETC, &c);
          send_process (proc, &c.t_quitc, 1);
-         return Qnil;
+         return;
+#ifdef SIGTSTP
        case SIGTSTP:
          ioctl (XFASTINT (p->infd), TIOCGLTC, &lc);
          send_process (proc, &lc.t_suspc, 1);
-         return Qnil;
+         return;
+#endif /* ! defined (SIGTSTP) */
        }
-#endif /* have TIOCGLTC and have TIOCGETC */
-      /* It is possible that the following code would work
-        on other kinds of USG systems, not just on the IRIS.
-        This should be tried in Emacs 19.  */
-#if defined (IRIS) && defined (HAVE_SETSID) /* Check for Irix, not older
-                                              systems.  */
+
+#else /* ! defined (TIOCGLTC) && defined (TIOCGETC) */
+
+      /* On SYSV descendants, the TCGETA ioctl retrieves the current control
+        characters.  */
+#ifdef TCGETA
       struct termio t;
       switch (signo)
        {
        case SIGINT:
          ioctl (XFASTINT (p->infd), TCGETA, &t);
          send_process (proc, &t.c_cc[VINTR], 1);
-         return Qnil;
+         return;
        case SIGQUIT:
          ioctl (XFASTINT (p->infd), TCGETA, &t);
          send_process (proc, &t.c_cc[VQUIT], 1);
-         return Qnil;
+         return;
+#ifdef SIGTSTP
        case SIGTSTP:
          ioctl (XFASTINT (p->infd), TCGETA, &t);
          send_process (proc, &t.c_cc[VSWTCH], 1);
-         return Qnil;
+         return;
+#endif /* ! defined (SIGTSTP) */
        }
-#endif /* IRIS and HAVE_SETSID */
-
+#else /* ! defined (TCGETA) */
+      Your configuration files are messed up.
+      /* If your system configuration files define SIGNALS_VIA_CHARACTERS,
+        you'd better be using one of the alternatives above!  */
+#endif /* ! defined (TCGETA) */
+#endif /* ! defined (TIOCGLTC) && defined (TIOCGETC) */
+#endif /* ! defined HAVE_TERMIOS */
+#endif /* ! defined (SIGNALS_VIA_CHARACTERS) */
+
+#ifdef TIOCGPGRP 
       /* Get the pgrp using the tty itself, if we have that.
         Otherwise, use the pty to get the pgrp.
         On pfa systems, saka@pfu.fujitsu.co.JP writes:
-        "TICGPGRP symbol defined in sys/ioctl.h at E50.
-         But, TIOCGPGRP donot work on E50 ;-P work fine on E60"
+        "TIOCGPGRP symbol defined in sys/ioctl.h at E50.
+        But, TIOCGPGRP does not work on E50 ;-P works fine on E60"
         His patch indicates that if TIOCGPGRP returns an error, then
         we should just assume that p->pid is also the process group id.  */
       {
@@ -2298,20 +2481,20 @@ process_send_signal (process, signo, current_group, nomsg)
 #ifdef pfa
        if (err == -1)
          gid = - XFASTINT (p->pid);
-#endif
+#endif /* ! defined (pfa) */
       }
       if (gid == -1)
        no_pgrp = 1;
       else
        gid = - gid;
+#else  /* ! defined (TIOCGPGRP ) */
+      /* Can't select pgrps on this system, so we know that
+        the child itself heads the pgrp.  */
+      gid = - XFASTINT (p->pid);
+#endif /* ! defined (TIOCGPGRP ) */
     }
   else
     gid = - XFASTINT (p->pid);
-#else /* not using pgrps */
-  /* Can't select pgrps on this system, so we know that
-     the child itself heads the pgrp.  */
-  gid = - XFASTINT (p->pid);
-#endif /* not using pgrps */
 
   switch (signo)
     {
@@ -2324,7 +2507,7 @@ process_send_signal (process, signo, current_group, nomsg)
       if (!nomsg)
        status_notify ();
       break;
-#endif
+#endif /* ! defined (SIGCONT) */
     case SIGINT:
 #ifdef VMS
       send_process (proc, "\003", 1);  /* ^C */
@@ -2362,13 +2545,14 @@ process_send_signal (process, signo, current_group, nomsg)
       gid = - XFASTINT (p->pid);
       kill (gid, signo);
     }
-#else /* no TIOCSIGSEND */
+#else /* ! defined (TIOCSIGSEND) */
   EMACS_KILLPG (-gid, signo);
-#endif
+#endif /* ! defined (TIOCSIGSEND) */
 }
 
 DEFUN ("interrupt-process", Finterrupt_process, Sinterrupt_process, 0, 2, 0,
   "Interrupt process PROCESS.  May be process or name of one.\n\
+PROCESS may be a process, a buffer, or the name of a process or buffer.\n\
 Nil or no arg means current buffer's process.\n\
 Second arg CURRENT-GROUP non-nil means send signal to\n\
 the current process-group of the process's controlling terminal\n\
@@ -2445,13 +2629,21 @@ Both PID and CODE are integers.")
 DEFUN ("process-send-eof", Fprocess_send_eof, Sprocess_send_eof, 0, 1, 0,
   "Make PROCESS see end-of-file in its input.\n\
 Eof comes after any text already sent to it.\n\
-nil or no arg means current buffer's process.")
+PROCESS may be a process, a buffer, the name of a process or buffer, or\n\
+nil, indicating the current buffer's process.")
   (process)
      Lisp_Object process;
 {
   Lisp_Object proc;
 
   proc = get_process (process);
+
+  /* Make sure the process is really alive.  */
+  if (! NILP (XPROCESS (proc)->raw_status_low))
+    update_status (XPROCESS (proc));
+  if (! EQ (XPROCESS (proc)->status, Qrun))
+    error ("Process %s not running", XSTRING (XPROCESS (proc)->name)->data);
+
   /* Sending a zero-length record is supposed to mean eof
      when TIOCREMOTE is turned on.  */
 #ifdef DID_REMOTE
@@ -2468,7 +2660,7 @@ nil or no arg means current buffer's process.")
   else
     {
       close (XPROCESS (proc)->outfd);
-      XFASTINT (XPROCESS (proc)->outfd) = open ("/dev/null", O_WRONLY);
+      XFASTINT (XPROCESS (proc)->outfd) = open (NULL_DEVICE, O_WRONLY);
     }
 #endif /* VMS */
 #endif /* did not do TOICREMOTE */
@@ -2526,6 +2718,7 @@ sigchld_handler (signo)
   int old_errno = errno;
   Lisp_Object proc;
   register struct Lisp_Process *p;
+  extern EMACS_TIME *input_available_clear_time;
 
 #ifdef BSD4_1
   extern int sigheld;
@@ -2606,8 +2799,13 @@ sigchld_handler (signo)
          
          /* If process has terminated, stop waiting for its output.  */
          if (WIFSIGNALED (w) || WIFEXITED (w))
-           if (p->infd)
-             FD_CLR (p->infd, &input_wait_mask);
+           if (XFASTINT (p->infd))
+             FD_CLR (XFASTINT (p->infd), &input_wait_mask);
+
+         /* Tell wait_reading_process_input that it needs to wake up and
+            look around.  */
+         if (input_available_clear_time)
+           EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
        }
 
        /* There was no asynchronous process found for that id.  Check
@@ -2620,7 +2818,16 @@ sigchld_handler (signo)
          if (WIFEXITED (w))
            synch_process_retcode = WRETCODE (w);
          else if (WIFSIGNALED (w))
+#ifndef VMS
            synch_process_death = sys_siglist[WTERMSIG (w)];
+#else
+           synch_process_death = sys_errlist[WTERMSIG (w)];
+#endif
+
+         /* Tell wait_reading_process_input that it needs to wake up and
+            look around.  */
+         if (input_available_clear_time)
+           EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
        }
 
       /* On some systems, we must return right away.
@@ -2794,7 +3001,7 @@ init_process ()
       proc_buffered_char[i] = -1;
     }
 }
-#ifdef 0
+#if 0
 DEFUN ("process-connection", Fprocess_connection, Sprocess_connection, 0, 1, 0,
  "Return the connection type of `PROCESS'.  This can be nil (pipe),\n\
 t or pty (pty) or stream (socket connection).")
@@ -2806,9 +3013,6 @@ t or pty (pty) or stream (socket connection).")
 #endif
 syms_of_process ()
 {
-#ifdef HAVE_PTYS
-  pty_process = intern ("pty");
-#endif
 #ifdef HAVE_SOCKETS
   stream_process = intern ("stream");
 #endif
@@ -2894,7 +3098,7 @@ effect when `start-process' is called.");
 #include "systime.h"
 #include "termopts.h"
 
-extern int screen_garbaged;
+extern int frame_garbaged;
 
 
 /* As described above, except assuming that there are no subprocesses:
@@ -2906,7 +3110,7 @@ extern int screen_garbaged;
      zero for no limit, or
      -1 means gobble data immediately available but don't wait for any.
 
-   read_kbd is:
+   read_kbd is a Lisp_Object:
      0 to ignore keyboard input, or
      1 to return when input is available, or
      -1 means caller will actually read the input, so don't throw to
@@ -2917,14 +3121,13 @@ extern int screen_garbaged;
    do_display != 0 means redisplay should be done to show subprocess
    output that arrives.  This version of the function ignores it.
 
-   If read_kbd is a pointer to a struct Lisp_Process, then the
-     function returns true iff we received input from that process
-     before the timeout elapsed.
-   Otherwise, return true iff we recieved input from any process.  */
+   Return true iff we recieved input from any process.  */
 
 int
 wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
-     int time_limit, microsecs, read_kbd, do_display;
+     int time_limit, microsecs;
+     Lisp_Object read_kbd;
+     int do_display;
 {
   EMACS_TIME end_time, timeout, *timeout_p;
   int waitchannels;
@@ -2957,12 +3160,12 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
     {
       int nfds;
 
-      waitchannels = read_kbd ? 1 : 0;
+      waitchannels = XINT (read_kbd) ? 1 : 0;
 
       /* If calling from keyboard input, do not quit
         since we want to return C-g as an input character.
         Otherwise, do pending quit if requested.  */
-      if (read_kbd >= 0)
+      if (XINT (read_kbd) >= 0)
        QUIT;
 
       if (timeout_p)
@@ -2975,15 +3178,15 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
 
       /* Cause C-g and alarm signals to take immediate action,
         and cause input available signals to zero out timeout.  */
-      if (read_kbd < 0)
+      if (XINT (read_kbd) < 0)
        set_waiting_for_input (&timeout);
 
-      /* If a screen has been newly mapped and needs updating,
+      /* If a frame has been newly mapped and needs updating,
         reprocess its display stuff.  */
-      if (screen_garbaged)
+      if (frame_garbaged)
        redisplay_preserve_echo_area ();
 
-      if (read_kbd && detect_input_pending ())
+      if (XINT (read_kbd) && detect_input_pending ())
        nfds = 0;
       else
        nfds = select (1, &waitchannels, 0, 0, timeout_p);
@@ -3006,7 +3209,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
        /* System sometimes fails to deliver SIGIO.  */
        kill (getpid (), SIGIO);
 #endif
-      if (read_kbd && interrupt_input && (waitchannels & 1))
+      if (XINT (read_kbd) && interrupt_input && (waitchannels & 1))
        kill (0, SIGIO);
 
       /* If we have timed out (nfds == 0) or found some input (nfds > 0),
@@ -3015,6 +3218,8 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
        break;
     }
 
+  start_polling ();
+
   return 0;
 }