* src/nsfns.m (ns_display_info_for_name, Fx_open_connection): Doc fixes.
[bpt/emacs.git] / src / process.c
index 99c707f..85470b6 100644 (file)
@@ -1,6 +1,6 @@
 /* Asynchronous subprocess control for GNU Emacs.
 
-Copyright (C) 1985-1988, 1993-1996, 1998-1999, 2001-2013 Free Software
+Copyright (C) 1985-1988, 1993-1996, 1998-1999, 2001-2014 Free Software
 Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -21,8 +21,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
-#define PROCESS_INLINE EXTERN_INLINE
-
 #include <stdio.h>
 #include <errno.h>
 #include <sys/types.h>         /* Some typedefs are used in sys/file.h.  */
@@ -92,6 +90,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <c-ctype.h>
 #include <sig2str.h>
+#include <verify.h>
 
 #endif /* subprocesses */
 
@@ -131,8 +130,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #endif
 
 #ifdef WINDOWSNT
-extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
-                      EMACS_TIME *, void *);
+extern int sys_select (int, fd_set *, fd_set *, fd_set *,
+                      struct timespec *, void *);
 #endif
 
 #ifndef SOCK_CLOEXEC
@@ -260,7 +259,7 @@ static EMACS_INT update_tick;
 #endif
 
 #ifdef ADAPTIVE_READ_BUFFERING
-#define READ_OUTPUT_DELAY_INCREMENT (EMACS_TIME_RESOLUTION / 100)
+#define READ_OUTPUT_DELAY_INCREMENT (TIMESPEC_RESOLUTION / 100)
 #define READ_OUTPUT_DELAY_MAX       (READ_OUTPUT_DELAY_INCREMENT * 5)
 #define READ_OUTPUT_DELAY_MAX_MAX   (READ_OUTPUT_DELAY_INCREMENT * 7)
 
@@ -279,7 +278,7 @@ static bool process_output_skip;
 
 static void create_process (Lisp_Object, char **, Lisp_Object);
 #ifdef USABLE_SIGIO
-static bool keyboard_bit_set (SELECT_TYPE *);
+static bool keyboard_bit_set (fd_set *);
 #endif
 static void deactivate_process (Lisp_Object);
 static void status_notify (struct Lisp_Process *);
@@ -298,26 +297,26 @@ static void exec_sentinel (Lisp_Object proc, Lisp_Object reason);
 
 /* Mask of bits indicating the descriptors that we wait for input on.  */
 
-static SELECT_TYPE input_wait_mask;
+static fd_set input_wait_mask;
 
 /* Mask that excludes keyboard input descriptor(s).  */
 
-static SELECT_TYPE non_keyboard_wait_mask;
+static fd_set non_keyboard_wait_mask;
 
 /* Mask that excludes process input descriptor(s).  */
 
-static SELECT_TYPE non_process_wait_mask;
+static fd_set non_process_wait_mask;
 
 /* Mask for selecting for write.  */
 
-static SELECT_TYPE write_mask;
+static fd_set write_mask;
 
 #ifdef NON_BLOCKING_CONNECT
 /* Mask of bits indicating the descriptors that we wait for connect to
    complete on.  Once they complete, they are removed from this mask
    and added to the input_wait_mask and non_keyboard_wait_mask.  */
 
-static SELECT_TYPE connect_wait_mask;
+static fd_set connect_wait_mask;
 
 /* Number of bits set in connect_wait_mask.  */
 static int num_pending_connects;
@@ -330,7 +329,7 @@ static int max_process_desc;
 static int max_input_desc;
 
 /* Indexed by descriptor, gives the process (if any) for that descriptor */
-static Lisp_Object chan_process[MAXDESC];
+static Lisp_Object chan_process[FD_SETSIZE];
 
 /* Alist of elements (NAME . PROCESS) */
 static Lisp_Object Vprocess_alist;
@@ -341,18 +340,18 @@ static Lisp_Object Vprocess_alist;
    output from the process is to read at least one char.
    Always -1 on systems that support FIONREAD.  */
 
-static int proc_buffered_char[MAXDESC];
+static int proc_buffered_char[FD_SETSIZE];
 
 /* Table of `struct coding-system' for each process.  */
-static struct coding_system *proc_decode_coding_system[MAXDESC];
-static struct coding_system *proc_encode_coding_system[MAXDESC];
+static struct coding_system *proc_decode_coding_system[FD_SETSIZE];
+static struct coding_system *proc_encode_coding_system[FD_SETSIZE];
 
 #ifdef DATAGRAM_SOCKETS
 /* Table of `partner address' for datagram sockets.  */
 static struct sockaddr_and_len {
   struct sockaddr *sa;
   int len;
-} datagram_address[MAXDESC];
+} datagram_address[FD_SETSIZE];
 #define DATAGRAM_CHAN_P(chan)  (datagram_address[chan].sa != 0)
 #define DATAGRAM_CONN_P(proc)  (PROCESSP (proc) && datagram_address[XPROCESS (proc)->infd].sa != 0)
 #else
@@ -360,6 +359,12 @@ static struct sockaddr_and_len {
 #define DATAGRAM_CONN_P(proc)  (0)
 #endif
 
+/* FOR_EACH_PROCESS (LIST_VAR, PROC_VAR) followed by a statement is
+   a `for' loop which iterates over processes from Vprocess_alist.  */
+
+#define FOR_EACH_PROCESS(list_var, proc_var)                   \
+  FOR_EACH_ALIST_VALUE (Vprocess_alist, list_var, proc_var)
+
 /* These setters are used only in this file, so they can be private.  */
 static void
 pset_buffer (struct Lisp_Process *p, Lisp_Object val)
@@ -451,7 +456,7 @@ static struct fd_callback_data
 #define FOR_READ  1
 #define FOR_WRITE 2
   int condition; /* mask of the defines above.  */
-} fd_callback_info[MAXDESC];
+} fd_callback_info[FD_SETSIZE];
 
 
 /* Add a file descriptor FD to be monitored for when read is possible.
@@ -460,7 +465,7 @@ static struct fd_callback_data
 void
 add_read_fd (int fd, fd_callback func, void *data)
 {
-  eassert (fd < MAXDESC);
+  eassert (fd < FD_SETSIZE);
   add_keyboard_wait_descriptor (fd);
 
   fd_callback_info[fd].func = func;
@@ -473,7 +478,7 @@ add_read_fd (int fd, fd_callback func, void *data)
 void
 delete_read_fd (int fd)
 {
-  eassert (fd < MAXDESC);
+  eassert (fd < FD_SETSIZE);
   delete_keyboard_wait_descriptor (fd);
 
   fd_callback_info[fd].condition &= ~FOR_READ;
@@ -490,7 +495,7 @@ delete_read_fd (int fd)
 void
 add_write_fd (int fd, fd_callback func, void *data)
 {
-  eassert (fd < MAXDESC);
+  eassert (fd < FD_SETSIZE);
   FD_SET (fd, &write_mask);
   if (fd > max_input_desc)
     max_input_desc = fd;
@@ -521,7 +526,7 @@ delete_input_desc (int fd)
 void
 delete_write_fd (int fd)
 {
-  eassert (fd < MAXDESC);
+  eassert (fd < FD_SETSIZE);
   FD_CLR (fd, &write_mask);
   fd_callback_info[fd].condition &= ~FOR_WRITE;
   if (fd_callback_info[fd].condition == 0)
@@ -680,6 +685,15 @@ allocate_pty (char pty_name[PTY_NAME_SIZE])
 
        if (fd >= 0)
          {
+#ifdef PTY_OPEN
+           /* Set FD's close-on-exec flag.  This is needed even if
+              PT_OPEN calls posix_openpt with O_CLOEXEC, since POSIX
+              doesn't require support for that combination.
+              Multithreaded platforms where posix_openpt ignores
+              O_CLOEXEC (or where PTY_OPEN doesn't call posix_openpt)
+              have a race condition between the PTY_OPEN and here.  */
+           fcntl (fd, F_SETFD, FD_CLOEXEC);
+#endif
            /* check to make certain that both sides are available
               this avoids a nasty yet stupid bug in rlogins */
 #ifdef PTY_TTY_NAME_SPRINTF
@@ -722,6 +736,8 @@ make_process (Lisp_Object name)
      non-Lisp data, so do it only for slots which should not be zero.  */
   p->infd = -1;
   p->outfd = -1;
+  for (i = 0; i < PROCESS_OPEN_FDS; i++)
+    p->open_fd[i] = -1;
 
 #ifdef HAVE_GNUTLS
   p->gnutls_initstage = GNUTLS_STAGE_EMPTY;
@@ -796,13 +812,14 @@ get_process (register Lisp_Object name)
   else
     obj = name;
 
-  /* Now obj should be either a buffer object or a process object.
-   */
+  /* Now obj should be either a buffer object or a process object.  */
   if (BUFFERP (obj))
     {
+      if (NILP (BVAR (XBUFFER (obj), name)))
+        error ("Attempt to get process for a dead buffer");
       proc = Fget_buffer_process (obj);
       if (NILP (proc))
-       error ("Buffer %s has no process", SDATA (BVAR (XBUFFER (obj), name)));
+        error ("Buffer %s has no process", SDATA (BVAR (XBUFFER (obj), name)));
     }
   else
     {
@@ -818,13 +835,17 @@ get_process (register Lisp_Object name)
    treated by the SIGCHLD handler and waitpid has been invoked on them;
    otherwise they might fill up the kernel's process table.
 
-   Some processes created by call-process are also put onto this list.  */
+   Some processes created by call-process are also put onto this list.
+
+   Members of this list are (process-ID . filename) pairs.  The
+   process-ID is a number; the filename, if a string, is a file that
+   needs to be removed after the process exits.  */
 static Lisp_Object deleted_pid_list;
 
 void
-record_deleted_pid (pid_t pid)
+record_deleted_pid (pid_t pid, Lisp_Object filename)
 {
-  deleted_pid_list = Fcons (make_fixnum_or_float (pid),
+  deleted_pid_list = Fcons (Fcons (make_fixnum_or_float (pid), filename),
                            /* GC treated elements set to nil.  */
                            Fdelq (Qnil, deleted_pid_list));
 
@@ -852,7 +873,7 @@ nil, indicating the current buffer's process.  */)
   else
     {
       if (p->alive)
-       record_kill_process (p);
+       record_kill_process (p, Qnil);
 
       if (p->infd >= 0)
        {
@@ -1118,15 +1139,18 @@ See `set-process-sentinel' for more info on sentinels.  */)
 DEFUN ("set-process-window-size", Fset_process_window_size,
        Sset_process_window_size, 3, 3, 0,
        doc: /* Tell PROCESS that it has logical window size HEIGHT and WIDTH.  */)
-  (register Lisp_Object process, Lisp_Object height, Lisp_Object width)
+  (Lisp_Object process, Lisp_Object height, Lisp_Object width)
 {
   CHECK_PROCESS (process);
-  CHECK_RANGED_INTEGER (height, 0, INT_MAX);
-  CHECK_RANGED_INTEGER (width, 0, INT_MAX);
+
+  /* All known platforms store window sizes as 'unsigned short'.  */
+  CHECK_RANGED_INTEGER (height, 0, USHRT_MAX);
+  CHECK_RANGED_INTEGER (width, 0, USHRT_MAX);
 
   if (XPROCESS (process)->infd < 0
-      || set_window_size (XPROCESS (process)->infd,
-                         XINT (height), XINT (width)) <= 0)
+      || (set_window_size (XPROCESS (process)->infd,
+                          XINT (height), XINT (width))
+         < 0))
     return Qnil;
   else
     return Qt;
@@ -1386,22 +1410,9 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
      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 = BVAR (current_buffer, directory);
-
-    GCPRO2 (buffer, current_dir);
-
-    current_dir = Funhandled_file_name_directory (current_dir);
-    if (NILP (current_dir))
-      /* If the file name handler says that current_dir is unreachable, use
-        a sensible default. */
-      current_dir = build_string ("~/");
-    current_dir = expand_and_dir_to_file (current_dir, Qnil);
-    if (NILP (Ffile_accessible_directory_p (current_dir)))
-      report_file_error ("Setting current directory",
-                        BVAR (current_buffer, directory));
-
+    struct gcpro gcpro1;
+    GCPRO1 (buffer);
+    current_dir = encode_current_directory ();
     UNGCPRO;
   }
 
@@ -1519,7 +1530,8 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
 
          tem = Qnil;
          GCPRO4 (name, program, buffer, current_dir);
-         openp (Vexec_path, program, Vexec_suffixes, &tem, make_number (X_OK));
+         openp (Vexec_path, program, Vexec_suffixes, &tem,
+                make_number (X_OK), false);
          UNGCPRO;
          if (NILP (tem))
            report_file_error ("Searching for program", program);
@@ -1605,22 +1617,49 @@ start_process_unwind (Lisp_Object proc)
     remove_process (proc);
 }
 
+/* If *FD_ADDR is nonnegative, close it, and mark it as closed.  */
+
+static void
+close_process_fd (int *fd_addr)
+{
+  int fd = *fd_addr;
+  if (0 <= fd)
+    {
+      *fd_addr = -1;
+      emacs_close (fd);
+    }
+}
+
+/* Indexes of file descriptors in open_fds.  */
+enum
+  {
+    /* The pipe from Emacs to its subprocess.  */
+    SUBPROCESS_STDIN,
+    WRITE_TO_SUBPROCESS,
+
+    /* The main pipe from the subprocess to Emacs.  */
+    READ_FROM_SUBPROCESS,
+    SUBPROCESS_STDOUT,
+
+    /* The pipe from the subprocess to Emacs that is closed when the
+       subprocess execs.  */
+    READ_FROM_EXEC_MONITOR,
+    EXEC_MONITOR_OUTPUT
+  };
+
+verify (PROCESS_OPEN_FDS == EXEC_MONITOR_OUTPUT + 1);
 
 static void
 create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
 {
+  struct Lisp_Process *p = XPROCESS (process);
   int inchannel, outchannel;
   pid_t pid;
   int vfork_errno;
-  int sv[2];
-#ifndef WINDOWSNT
-  int wait_child_setup[2];
-#endif
   int forkin, forkout;
   bool pty_flag = 0;
   char pty_name[PTY_NAME_SIZE];
   Lisp_Object lisp_pty_name = Qnil;
-  Lisp_Object encoded_current_dir;
 
   inchannel = outchannel = -1;
 
@@ -1629,6 +1668,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
 
   if (inchannel >= 0)
     {
+      p->open_fd[READ_FROM_SUBPROCESS] = inchannel;
 #if ! defined (USG) || defined (USG_SUBTTY_WORKS)
       /* On most USG systems it does not work to open the pty's tty here,
         then close it and reopen it in the child.  */
@@ -1637,6 +1677,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
       forkout = forkin = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0);
       if (forkin < 0)
        report_file_error ("Opening pty", Qnil);
+      p->open_fd[SUBPROCESS_STDIN] = forkin;
 #else
       forkin = forkout = -1;
 #endif /* not USG, or USG_SUBTTY_WORKS */
@@ -1645,23 +1686,17 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
     }
   else
     {
-      if (emacs_pipe (sv) != 0)
+      if (emacs_pipe (p->open_fd + SUBPROCESS_STDIN) != 0
+         || emacs_pipe (p->open_fd + READ_FROM_SUBPROCESS) != 0)
        report_file_error ("Creating pipe", Qnil);
-      inchannel = sv[0];
-      forkout = sv[1];
-      if (emacs_pipe (sv) != 0)
-       {
-         int pipe_errno = errno;
-         emacs_close (inchannel);
-         emacs_close (forkout);
-         report_file_errno ("Creating pipe", Qnil, pipe_errno);
-       }
-      outchannel = sv[1];
-      forkin = sv[0];
+      forkin = p->open_fd[SUBPROCESS_STDIN];
+      outchannel = p->open_fd[WRITE_TO_SUBPROCESS];
+      inchannel = p->open_fd[READ_FROM_SUBPROCESS];
+      forkout = p->open_fd[SUBPROCESS_STDOUT];
     }
 
 #ifndef WINDOWSNT
-  if (emacs_pipe (wait_child_setup) != 0)
+  if (emacs_pipe (p->open_fd + READ_FROM_EXEC_MONITOR) != 0)
     report_file_error ("Creating pipe", Qnil);
 #endif
 
@@ -1670,16 +1705,16 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
 
   /* Record this as an active process, with its channels.  */
   chan_process[inchannel] = process;
-  XPROCESS (process)->infd = inchannel;
-  XPROCESS (process)->outfd = outchannel;
+  p->infd = inchannel;
+  p->outfd = outchannel;
 
   /* Previously we recorded the tty descriptor used in the subprocess.
      It was only used for getting the foreground tty process, so now
      we just reopen the device (see emacs_get_tty_pgrp) as this is
      more portable (see USG_SUBTTY_WORKS above).  */
 
-  XPROCESS (process)->pty_flag = pty_flag;
-  pset_status (XPROCESS (process), Qrun);
+  p->pty_flag = pty_flag;
+  pset_status (p, Qrun);
 
   FD_SET (inchannel, &input_wait_mask);
   FD_SET (inchannel, &non_keyboard_wait_mask);
@@ -1689,35 +1724,29 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
   /* This may signal an error. */
   setup_process_coding_systems (process);
 
-  encoded_current_dir = ENCODE_FILE (current_dir);
-
   block_input ();
   block_child_signal ();
 
 #ifndef WINDOWSNT
   /* vfork, and prevent local vars from being clobbered by the vfork.  */
   {
-    Lisp_Object volatile encoded_current_dir_volatile = encoded_current_dir;
+    Lisp_Object volatile current_dir_volatile = current_dir;
     Lisp_Object volatile lisp_pty_name_volatile = lisp_pty_name;
-    Lisp_Object volatile process_volatile = process;
     char **volatile new_argv_volatile = new_argv;
     int volatile forkin_volatile = forkin;
     int volatile forkout_volatile = forkout;
-    int volatile wait_child_setup_0_volatile = wait_child_setup[0];
-    int volatile wait_child_setup_1_volatile = wait_child_setup[1];
+    struct Lisp_Process *p_volatile = p;
 
     pid = vfork ();
 
-    encoded_current_dir = encoded_current_dir_volatile;
+    current_dir = current_dir_volatile;
     lisp_pty_name = lisp_pty_name_volatile;
-    process = process_volatile;
     new_argv = new_argv_volatile;
     forkin = forkin_volatile;
     forkout = forkout_volatile;
-    wait_child_setup[0] = wait_child_setup_0_volatile;
-    wait_child_setup[1] = wait_child_setup_1_volatile;
+    p = p_volatile;
 
-    pty_flag = XPROCESS (process)->pty_flag;
+    pty_flag = p->pty_flag;
   }
 
   if (pid == 0)
@@ -1812,6 +1841,9 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
 
       signal (SIGINT, SIG_DFL);
       signal (SIGQUIT, SIG_DFL);
+#ifdef SIGPROF
+      signal (SIGPROF, SIG_DFL);
+#endif
 
       /* Emacs ignores SIGPIPE, but the child should not.  */
       signal (SIGPIPE, SIG_DFL);
@@ -1822,53 +1854,51 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
       if (pty_flag)
        child_setup_tty (xforkout);
 #ifdef WINDOWSNT
-      pid = child_setup (xforkin, xforkout, xforkout,
-                        new_argv, 1, encoded_current_dir);
+      pid = child_setup (xforkin, xforkout, xforkout, new_argv, 1, current_dir);
 #else  /* not WINDOWSNT */
-      child_setup (xforkin, xforkout, xforkout,
-                  new_argv, 1, encoded_current_dir);
+      child_setup (xforkin, xforkout, xforkout, new_argv, 1, current_dir);
 #endif /* not WINDOWSNT */
     }
 
   /* Back in the parent process.  */
 
   vfork_errno = errno;
-  XPROCESS (process)->pid = pid;
+  p->pid = pid;
   if (pid >= 0)
-    XPROCESS (process)->alive = 1;
+    p->alive = 1;
 
   /* Stop blocking in the parent.  */
   unblock_child_signal ();
   unblock_input ();
 
-  if (forkin >= 0)
-    emacs_close (forkin);
-  if (forkin != forkout && forkout >= 0)
-    emacs_close (forkout);
-
   if (pid < 0)
     report_file_errno ("Doing vfork", Qnil, vfork_errno);
   else
     {
       /* vfork succeeded.  */
 
+      /* Close the pipe ends that the child uses, or the child's pty.  */
+      close_process_fd (&p->open_fd[SUBPROCESS_STDIN]);
+      close_process_fd (&p->open_fd[SUBPROCESS_STDOUT]);
+
 #ifdef WINDOWSNT
       register_child (pid, inchannel);
 #endif /* WINDOWSNT */
 
-      pset_tty_name (XPROCESS (process), lisp_pty_name);
+      pset_tty_name (p, lisp_pty_name);
 
 #ifndef WINDOWSNT
       /* Wait for child_setup to complete in case that vfork is
-        actually defined as fork.  The descriptor wait_child_setup[1]
+        actually defined as fork.  The descriptor
+        XPROCESS (proc)->open_fd[EXEC_MONITOR_OUTPUT]
         of a pipe is closed at the child side either by close-on-exec
         on successful execve or the _exit call in child_setup.  */
       {
        char dummy;
 
-       emacs_close (wait_child_setup[1]);
-       emacs_read (wait_child_setup[0], &dummy, 1);
-       emacs_close (wait_child_setup[0]);
+       close_process_fd (&p->open_fd[EXEC_MONITOR_OUTPUT]);
+       emacs_read (p->open_fd[READ_FROM_EXEC_MONITOR], &dummy, 1);
+       close_process_fd (&p->open_fd[READ_FROM_EXEC_MONITOR]);
       }
 #endif
     }
@@ -1877,16 +1907,13 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
 static void
 create_pty (Lisp_Object process)
 {
+  struct Lisp_Process *p = XPROCESS (process);
   char pty_name[PTY_NAME_SIZE];
-  int inchannel, outchannel;
-
-  inchannel = outchannel = -1;
+  int pty_fd = NILP (Vprocess_connection_type) ? -1 : allocate_pty (pty_name);
 
-  if (!NILP (Vprocess_connection_type))
-    outchannel = inchannel = allocate_pty (pty_name);
-
-  if (inchannel >= 0)
+  if (pty_fd >= 0)
     {
+      p->open_fd[SUBPROCESS_STDIN] = pty_fd;
 #if ! defined (USG) || defined (USG_SUBTTY_WORKS)
       /* On most USG systems it does not work to open the pty's tty here,
         then close it and reopen it in the child.  */
@@ -1895,6 +1922,7 @@ create_pty (Lisp_Object process)
       int forkout = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0);
       if (forkout < 0)
        report_file_error ("Opening pty", Qnil);
+      p->open_fd[WRITE_TO_SUBPROCESS] = forkout;
 #if defined (DONT_REOPEN_PTY)
       /* In the case that vfork is defined as fork, the parent process
         (Emacs) may send some data before the child process completes
@@ -1903,40 +1931,42 @@ create_pty (Lisp_Object process)
 #endif /* DONT_REOPEN_PTY */
 #endif /* not USG, or USG_SUBTTY_WORKS */
 
-      fcntl (inchannel, F_SETFL, O_NONBLOCK);
-      fcntl (outchannel, F_SETFL, O_NONBLOCK);
+      fcntl (pty_fd, F_SETFL, O_NONBLOCK);
 
       /* Record this as an active process, with its channels.
         As a result, child_setup will close Emacs's side of the pipes.  */
-      chan_process[inchannel] = process;
-      XPROCESS (process)->infd = inchannel;
-      XPROCESS (process)->outfd = outchannel;
+      chan_process[pty_fd] = process;
+      p->infd = pty_fd;
+      p->outfd = pty_fd;
 
       /* Previously we recorded the tty descriptor used in the subprocess.
         It was only used for getting the foreground tty process, so now
         we just reopen the device (see emacs_get_tty_pgrp) as this is
         more portable (see USG_SUBTTY_WORKS above).  */
 
-      XPROCESS (process)->pty_flag = 1;
-      pset_status (XPROCESS (process), Qrun);
+      p->pty_flag = 1;
+      pset_status (p, Qrun);
       setup_process_coding_systems (process);
 
-      FD_SET (inchannel, &input_wait_mask);
-      FD_SET (inchannel, &non_keyboard_wait_mask);
-      if (inchannel > max_process_desc)
-       max_process_desc = inchannel;
+      FD_SET (pty_fd, &input_wait_mask);
+      FD_SET (pty_fd, &non_keyboard_wait_mask);
+      if (pty_fd > max_process_desc)
+       max_process_desc = pty_fd;
 
-      pset_tty_name (XPROCESS (process), build_string (pty_name));
+      pset_tty_name (p, build_string (pty_name));
     }
 
-  XPROCESS (process)->pid = -2;
+  p->pid = -2;
 }
 
 \f
 /* Convert an internal struct sockaddr to a lisp object (vector or string).
    The address family of sa is not included in the result.  */
 
-static Lisp_Object
+#ifndef WINDOWSNT
+static
+#endif
+Lisp_Object
 conv_sockaddr_to_lisp (struct sockaddr *sa, int len)
 {
   Lisp_Object address;
@@ -2535,6 +2565,7 @@ usage:  (make-serial-process &rest ARGS)  */)
   p = XPROCESS (proc);
 
   fd = serial_open (port);
+  p->open_fd[SUBPROCESS_STDIN] = fd;
   p->infd = fd;
   p->outfd = fd;
   if (fd > max_process_desc)
@@ -3207,7 +3238,7 @@ usage: (make-network-process &rest ARGS)  */)
             wait for completion is pselect(). */
          int sc;
          socklen_t len;
-         SELECT_TYPE fdset;
+         fd_set fdset;
        retry_select:
          FD_ZERO (&fdset);
          FD_SET (s, &fdset);
@@ -3297,12 +3328,6 @@ usage: (make-network-process &rest ARGS)  */)
     }
 #endif
 
-  /* Discard the unwind protect for closing S, if any.  */
-  specpdl_ptr = specpdl + count1;
-
-  /* Unwind bind_polling_period and request_sigio.  */
-  unbind_to (count, Qnil);
-
   if (s < 0)
     {
       /* If non-blocking got this far - and failed - assume non-blocking is
@@ -3344,8 +3369,17 @@ usage: (make-network-process &rest ARGS)  */)
   if ((tem = Fplist_get (contact, QCstop), !NILP (tem)))
     pset_command (p, Qt);
   p->pid = 0;
+
+  p->open_fd[SUBPROCESS_STDIN] = inch;
   p->infd  = inch;
   p->outfd = outch;
+
+  /* Discard the unwind protect for closing S, if any.  */
+  specpdl_ptr = specpdl + count1;
+
+  /* Unwind bind_polling_period and request_sigio.  */
+  unbind_to (count, Qnil);
+
   if (is_server && socktype != SOCK_DGRAM)
     pset_status (p, Qlisten);
 
@@ -3478,15 +3512,11 @@ usage: (make-network-process &rest ARGS)  */)
 }
 
 \f
-#if defined (HAVE_NET_IF_H)
+#ifdef HAVE_NET_IF_H
 
 #ifdef SIOCGIFCONF
-DEFUN ("network-interface-list", Fnetwork_interface_list, Snetwork_interface_list, 0, 0, 0,
-       doc: /* Return an alist of all network interfaces and their network address.
-Each element is a cons, the car of which is a string containing the
-interface name, and the cdr is the network address in internal
-format; see the description of ADDRESS in `make-network-process'.  */)
-  (void)
+static Lisp_Object
+network_interface_list (void)
 {
   struct ifconf ifconf;
   struct ifreq *ifreq;
@@ -3628,13 +3658,8 @@ static const struct ifflag_def ifflag_table[] = {
   { 0, 0 }
 };
 
-DEFUN ("network-interface-info", Fnetwork_interface_info, Snetwork_interface_info, 1, 1, 0,
-       doc: /* Return information about network interface named IFNAME.
-The return value is a list (ADDR BCAST NETMASK HWADDR FLAGS),
-where ADDR is the layer 3 address, BCAST is the layer 3 broadcast address,
-NETMASK is the layer 3 network mask, HWADDR is the layer 2 address, and
-FLAGS is the current flags of the interface.  */)
-  (Lisp_Object ifname)
+static Lisp_Object
+network_interface_info (Lisp_Object ifname)
 {
   struct ifreq rq;
   Lisp_Object res = Qnil;
@@ -3703,7 +3728,9 @@ FLAGS is the current flags of the interface.  */)
 
       any = 1;
       for (n = 0; n < 6; n++)
-       p->contents[n] = make_number (((unsigned char *)&rq.ifr_hwaddr.sa_data[0])[n]);
+       p->contents[n] = make_number (((unsigned char *)
+                                      &rq.ifr_hwaddr.sa_data[0])
+                                     [n]);
       elt = Fcons (make_number (rq.ifr_hwaddr.sa_family), hwaddr);
     }
 #elif defined (HAVE_GETIFADDRS) && defined (LLADDR)
@@ -3776,25 +3803,62 @@ FLAGS is the current flags of the interface.  */)
 
   return unbind_to (count, any ? res : Qnil);
 }
-#endif
+#endif /* !SIOCGIFADDR && !SIOCGIFHWADDR && !SIOCGIFFLAGS */
 #endif /* defined (HAVE_NET_IF_H) */
 
+DEFUN ("network-interface-list", Fnetwork_interface_list,
+       Snetwork_interface_list, 0, 0, 0,
+       doc: /* Return an alist of all network interfaces and their network address.
+Each element is a cons, the car of which is a string containing the
+interface name, and the cdr is the network address in internal
+format; see the description of ADDRESS in `make-network-process'.
+
+If the information is not available, return nil.  */)
+  (void)
+{
+#if (defined HAVE_NET_IF_H && defined SIOCGIFCONF) || defined WINDOWSNT
+  return network_interface_list ();
+#else
+  return Qnil;
+#endif
+}
+
+DEFUN ("network-interface-info", Fnetwork_interface_info,
+       Snetwork_interface_info, 1, 1, 0,
+       doc: /* Return information about network interface named IFNAME.
+The return value is a list (ADDR BCAST NETMASK HWADDR FLAGS),
+where ADDR is the layer 3 address, BCAST is the layer 3 broadcast address,
+NETMASK is the layer 3 network mask, HWADDR is the layer 2 address, and
+FLAGS is the current flags of the interface.
+
+Data that is unavailable is returned as nil.  */)
+  (Lisp_Object ifname)
+{
+#if ((defined HAVE_NET_IF_H                           \
+      && (defined SIOCGIFADDR || defined SIOCGIFHWADDR \
+         || defined SIOCGIFFLAGS))                    \
+     || defined WINDOWSNT)
+  return network_interface_info (ifname);
+#else
+  return Qnil;
+#endif
+}
+
+
 /* Turn off input and output for process PROC.  */
 
 static void
 deactivate_process (Lisp_Object proc)
 {
-  register int inchannel, outchannel;
-  register struct Lisp_Process *p = XPROCESS (proc);
+  int inchannel;
+  struct Lisp_Process *p = XPROCESS (proc);
+  int i;
 
 #ifdef HAVE_GNUTLS
   /* Delete GnuTLS structures in PROC, if any.  */
   emacs_gnutls_deinit (proc);
 #endif /* HAVE_GNUTLS */
 
-  inchannel  = p->infd;
-  outchannel = p->outfd;
-
 #ifdef ADAPTIVE_READ_BUFFERING
   if (p->read_output_delay > 0)
     {
@@ -3805,14 +3869,14 @@ deactivate_process (Lisp_Object proc)
     }
 #endif
 
+  /* Beware SIGCHLD hereabouts. */
+
+  for (i = 0; i < PROCESS_OPEN_FDS; i++)
+    close_process_fd (&p->open_fd[i]);
+
+  inchannel = p->infd;
   if (inchannel >= 0)
     {
-      /* Beware SIGCHLD hereabouts. */
-      flush_pending_output (inchannel);
-      emacs_close (inchannel);
-      if (outchannel >= 0 && outchannel != inchannel)
-       emacs_close (outchannel);
-
       p->infd  = -1;
       p->outfd = -1;
 #ifdef DATAGRAM_SOCKETS
@@ -3906,9 +3970,9 @@ Return non-nil if we received any output before the timeout expired.  */)
        {
          if (XFLOAT_DATA (seconds) > 0)
            {
-             EMACS_TIME t = EMACS_TIME_FROM_DOUBLE (XFLOAT_DATA (seconds));
-             secs = min (EMACS_SECS (t), WAIT_READING_MAX);
-             nsecs = EMACS_NSECS (t);
+             struct timespec t = dtotimespec (XFLOAT_DATA (seconds));
+             secs = min (t.tv_sec, WAIT_READING_MAX);
+             nsecs = t.tv_nsec;
            }
        }
       else
@@ -4095,6 +4159,7 @@ server_accept_connection (Lisp_Object server, int channel)
   /* Discard the unwind protect for closing S.  */
   specpdl_ptr = specpdl + count;
 
+  p->open_fd[SUBPROCESS_STDIN] = s;
   p->infd  = s;
   p->outfd = s;
   pset_status (p, Qrun);
@@ -4205,14 +4270,14 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
                             struct Lisp_Process *wait_proc, int just_wait_proc)
 {
   int channel, nfds;
-  SELECT_TYPE Available;
-  SELECT_TYPE Writeok;
+  fd_set Available;
+  fd_set Writeok;
   bool check_write;
   int check_delay;
   bool no_avail;
   int xerrno;
   Lisp_Object proc;
-  EMACS_TIME timeout, end_time;
+  struct timespec timeout, end_time;
   int wait_channel = -1;
   bool got_some_input = 0;
   ptrdiff_t count = SPECPDL_INDEX ();
@@ -4245,8 +4310,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
      compute the absolute time to return at.  */
   if (time_limit || nsecs > 0)
     {
-      timeout = make_emacs_time (time_limit, nsecs);
-      end_time = add_emacs_time (current_emacs_time (), timeout);
+      timeout = make_timespec (time_limit, nsecs);
+      end_time = timespec_add (current_timespec (), timeout);
     }
 
   while (1)
@@ -4273,18 +4338,18 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
             gobble output available now
             but don't wait at all. */
 
-         timeout = make_emacs_time (0, 0);
+         timeout = make_timespec (0, 0);
        }
       else if (time_limit || nsecs > 0)
        {
-         EMACS_TIME now = current_emacs_time ();
-         if (EMACS_TIME_LE (end_time, now))
+         struct timespec now = current_timespec ();
+         if (timespec_cmp (end_time, now) <= 0)
            break;
-         timeout = sub_emacs_time (end_time, now);
+         timeout = timespec_sub (end_time, now);
        }
       else
        {
-         timeout = make_emacs_time (100000, 0);
+         timeout = make_timespec (100000, 0);
        }
 
       /* Normally we run timers here.
@@ -4294,7 +4359,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
       if (NILP (wait_for_cell)
          && just_wait_proc >= 0)
        {
-         EMACS_TIME timer_delay;
+         struct timespec timer_delay;
 
          do
            {
@@ -4329,9 +4394,9 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
          /* A negative timeout means do not wait at all.  */
          if (nsecs >= 0)
            {
-             if (EMACS_TIME_VALID_P (timer_delay))
+             if (timespec_valid_p (timer_delay))
                {
-                 if (EMACS_TIME_LT (timer_delay, timeout))
+                 if (timespec_cmp (timer_delay, timeout) < 0)
                    {
                      timeout = timer_delay;
                      timeout_reduced_for_timers = 1;
@@ -4360,8 +4425,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
         timeout to get our attention.  */
       if (update_tick != process_tick)
        {
-         SELECT_TYPE Atemp;
-         SELECT_TYPE Ctemp;
+         fd_set Atemp;
+         fd_set Ctemp;
 
           if (kbd_on_hold_p ())
             FD_ZERO (&Atemp);
@@ -4369,7 +4434,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
             Atemp = input_wait_mask;
          Ctemp = write_mask;
 
-         timeout = make_emacs_time (0, 0);
+         timeout = make_timespec (0, 0);
          if ((pselect (max (max_process_desc, max_input_desc) + 1,
                        &Atemp,
 #ifdef NON_BLOCKING_CONNECT
@@ -4491,8 +4556,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
             Vprocess_adaptive_read_buffering is nil.  */
          if (process_output_skip && check_delay > 0)
            {
-             int nsecs = EMACS_NSECS (timeout);
-             if (EMACS_SECS (timeout) > 0 || nsecs > READ_OUTPUT_DELAY_MAX)
+             int nsecs = timeout.tv_nsec;
+             if (timeout.tv_sec > 0 || nsecs > READ_OUTPUT_DELAY_MAX)
                nsecs = READ_OUTPUT_DELAY_MAX;
              for (channel = 0; check_delay > 0 && channel <= max_process_desc; channel++)
                {
@@ -4512,7 +4577,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
                        nsecs = XPROCESS (proc)->read_output_delay;
                    }
                }
-             timeout = make_emacs_time (0, nsecs);
+             timeout = make_timespec (0, nsecs);
              process_output_skip = 0;
            }
 #endif
@@ -4544,12 +4609,12 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
                     the gnutls library -- 2.12.14 has been confirmed
                     to need it.  See
                     http://comments.gmane.org/gmane.emacs.devel/145074 */
-                 for (channel = 0; channel < MAXDESC; ++channel)
+                 for (channel = 0; channel < FD_SETSIZE; ++channel)
                    if (! NILP (chan_process[channel]))
                      {
                        struct Lisp_Process *p =
                          XPROCESS (chan_process[channel]);
-                       if (p && p->gnutls_p && p->infd
+                       if (p && p->gnutls_p && p->gnutls_state && p->infd
                            && ((emacs_gnutls_record_check_pending
                                 (p->gnutls_state))
                                > 0))
@@ -4563,6 +4628,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
                {
                  /* Check this specific channel. */
                  if (wait_proc->gnutls_p /* Check for valid process.  */
+                     && wait_proc->gnutls_state
                      /* Do we have pending data?  */
                      && ((emacs_gnutls_record_check_pending
                           (wait_proc->gnutls_state))
@@ -4822,7 +4888,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
 #else
              {
                struct sockaddr pname;
-               int pnamelen = sizeof (pname);
+               socklen_t pnamelen = sizeof (pname);
 
                /* If connection failed, getpeername will fail.  */
                xerrno = 0;
@@ -4944,7 +5010,7 @@ read_process_output (Lisp_Object proc, register int channel)
          proc_buffered_char[channel] = -1;
        }
 #ifdef HAVE_GNUTLS
-      if (p->gnutls_p)
+      if (p->gnutls_p && p->gnutls_state)
        nbytes = emacs_gnutls_read (p, chars + carryover + buffered,
                                    readmax - buffered);
       else
@@ -5151,15 +5217,10 @@ DEFUN ("internal-default-process-filter", Finternal_default_process_filter,
 
       bset_read_only (current_buffer, Qnil);
 
-      /* Insert new output into buffer
-        at the current end-of-output marker,
-        thus preserving logical ordering of input and output.  */
+      /* Insert new output into buffer at the current end-of-output
+        marker, thus preserving logical ordering of input and output.  */
       if (XMARKER (p->mark)->buffer)
-       SET_PT_BOTH (clip_to_bounds (BEGV,
-                                    marker_position (p->mark), ZV),
-                    clip_to_bounds (BEGV_BYTE,
-                                    marker_byte_position (p->mark),
-                                    ZV_BYTE));
+       set_point_from_marker (p->mark);
       else
        SET_PT_BOTH (ZV, ZV_BYTE);
       before = PT;
@@ -5190,7 +5251,7 @@ DEFUN ("internal-default-process-filter", Finternal_default_process_filter,
       else
        set_marker_both (p->mark, p->buffer, PT, PT_BYTE);
 
-      update_mode_lines++;
+      update_mode_lines = 23;
 
       /* Make sure opoint and the old restrictions
         float ahead of any new text just as point would.  */
@@ -5443,7 +5504,7 @@ send_process (Lisp_Object proc, const char *buf, ptrdiff_t len,
 #endif
            {
 #ifdef HAVE_GNUTLS
-             if (p->gnutls_p)
+             if (p->gnutls_p && p->gnutls_state)
                written = emacs_gnutls_write (p, cur_buf, cur_len);
              else
 #endif
@@ -5740,10 +5801,9 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group,
        return;
     }
 
-  switch (signo)
-    {
 #ifdef SIGCONT
-    case SIGCONT:
+  if (signo == SIGCONT)
+    {
       p->raw_status_new = 0;
       pset_status (p, Qrun);
       p->tick = ++process_tick;
@@ -5752,14 +5812,8 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group,
          status_notify (NULL);
          redisplay_preserve_echo_area (13);
        }
-      break;
-#endif /* ! defined (SIGCONT) */
-    case SIGINT:
-    case SIGQUIT:
-    case SIGKILL:
-      flush_pending_output (p->infd);
-      break;
     }
+#endif
 
   /* If we don't have process groups, send the signal to the immediate
      subprocess.  That isn't really right, but it's better than any
@@ -5982,13 +6036,16 @@ process has been transmitted to the serial port.  */)
   (Lisp_Object process)
 {
   Lisp_Object proc;
-  struct coding_system *coding;
+  struct coding_system *coding = NULL;
+  int outfd;
 
   if (DATAGRAM_CONN_P (process))
     return process;
 
   proc = get_process (process);
-  coding = proc_encode_coding_system[XPROCESS (proc)->outfd];
+  outfd = XPROCESS (proc)->outfd;
+  if (outfd >= 0)
+    coding = proc_encode_coding_system[outfd];
 
   /* Make sure the process is really alive.  */
   if (XPROCESS (proc)->raw_status_new)
@@ -5996,7 +6053,7 @@ process has been transmitted to the serial port.  */)
   if (! EQ (XPROCESS (proc)->status, Qrun))
     error ("Process %s not running", SDATA (XPROCESS (proc)->name));
 
-  if (CODING_REQUIRE_FLUSHING (coding))
+  if (coding && CODING_REQUIRE_FLUSHING (coding))
     {
       coding->mode |= CODING_MODE_LAST_BLOCK;
       send_process (proc, "", 0, Qnil);
@@ -6014,36 +6071,39 @@ process has been transmitted to the serial port.  */)
     }
   else
     {
-      int old_outfd, new_outfd;
+      struct Lisp_Process *p = XPROCESS (proc);
+      int old_outfd = p->outfd;
+      int new_outfd;
 
 #ifdef HAVE_SHUTDOWN
       /* If this is a network connection, or socketpair is used
         for communication with the subprocess, call shutdown to cause EOF.
         (In some old system, shutdown to socketpair doesn't work.
         Then we just can't win.)  */
-      if (EQ (XPROCESS (proc)->type, Qnetwork)
-         || XPROCESS (proc)->outfd == XPROCESS (proc)->infd)
-       shutdown (XPROCESS (proc)->outfd, 1);
-      /* In case of socketpair, outfd == infd, so don't close it.  */
-      if (XPROCESS (proc)->outfd != XPROCESS (proc)->infd)
-       emacs_close (XPROCESS (proc)->outfd);
-#else /* not HAVE_SHUTDOWN */
-      emacs_close (XPROCESS (proc)->outfd);
-#endif /* not HAVE_SHUTDOWN */
+      if (EQ (p->type, Qnetwork)
+         || p->infd == old_outfd)
+       shutdown (old_outfd, 1);
+#endif
+      close_process_fd (&p->open_fd[WRITE_TO_SUBPROCESS]);
       new_outfd = emacs_open (NULL_DEVICE, O_WRONLY, 0);
       if (new_outfd < 0)
-       emacs_abort ();
-      old_outfd = XPROCESS (proc)->outfd;
+       report_file_error ("Opening null device", Qnil);
+      p->open_fd[WRITE_TO_SUBPROCESS] = new_outfd;
+      p->outfd = new_outfd;
 
       if (!proc_encode_coding_system[new_outfd])
        proc_encode_coding_system[new_outfd]
          = xmalloc (sizeof (struct coding_system));
-      *proc_encode_coding_system[new_outfd]
-       = *proc_encode_coding_system[old_outfd];
-      memset (proc_encode_coding_system[old_outfd], 0,
-             sizeof (struct coding_system));
-
-      XPROCESS (proc)->outfd = new_outfd;
+      if (old_outfd >= 0)
+       {
+         *proc_encode_coding_system[new_outfd]
+           = *proc_encode_coding_system[old_outfd];
+         memset (proc_encode_coding_system[old_outfd], 0,
+                 sizeof (struct coding_system));
+       }
+      else
+       setup_coding_system (p->encode_coding_system,
+                            proc_encode_coding_system[new_outfd]);
     }
   return process;
 }
@@ -6109,7 +6169,7 @@ static signal_handler_t volatile lib_child_handler;
 static void
 handle_child_signal (int sig)
 {
-  Lisp_Object tail;
+  Lisp_Object tail, proc;
 
   /* Find the process that signaled us, and record its status.  */
 
@@ -6120,7 +6180,11 @@ handle_child_signal (int sig)
       bool all_pids_are_fixnums
        = (MOST_NEGATIVE_FIXNUM <= TYPE_MINIMUM (pid_t)
           && TYPE_MAXIMUM (pid_t) <= MOST_POSITIVE_FIXNUM);
-      Lisp_Object xpid = XCAR (tail);
+      Lisp_Object head = XCAR (tail);
+      Lisp_Object xpid;
+      if (! CONSP (head))
+       continue;
+      xpid = XCAR (head);
       if (all_pids_are_fixnums ? INTEGERP (xpid) : NUMBERP (xpid))
        {
          pid_t deleted_pid;
@@ -6129,14 +6193,17 @@ handle_child_signal (int sig)
          else
            deleted_pid = XFLOAT_DATA (xpid);
          if (child_status_changed (deleted_pid, 0, 0))
-           XSETCAR (tail, Qnil);
+           {
+             if (STRINGP (XCDR (head)))
+               unlink (SSDATA (XCDR (head)));
+             XSETCAR (tail, Qnil);
+           }
        }
     }
 
   /* Otherwise, if it is asynchronous, it is in Vprocess_alist.  */
-  for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
+  FOR_EACH_PROCESS (tail, proc)
     {
-      Lisp_Object proc = XCDR (XCAR (tail));
       struct Lisp_Process *p = XPROCESS (proc);
       int status;
 
@@ -6168,7 +6235,7 @@ handle_child_signal (int sig)
 
   lib_child_handler (sig);
 #ifdef NS_IMPL_GNUSTEP
-  /* NSTask in GNUStep sets its child handler each time it is called.
+  /* NSTask in GNUstep sets its child handler each time it is called.
      So we must re-set ours.  */
   catch_child_signal();
 #endif
@@ -6291,13 +6358,10 @@ status_notify (struct Lisp_Process *deleting_process)
      that we run, we get called again to handle their status changes.  */
   update_tick = process_tick;
 
-  for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
+  FOR_EACH_PROCESS (tail, proc)
     {
       Lisp_Object symbol;
-      register struct Lisp_Process *p;
-
-      proc = Fcdr (XCAR (tail));
-      p = XPROCESS (proc);
+      register struct Lisp_Process *p = XPROCESS (proc);
 
       if (p->tick != p->update_tick)
        {
@@ -6341,7 +6405,7 @@ status_notify (struct Lisp_Process *deleting_process)
        }
     } /* end for */
 
-  update_mode_lines++;  /* In case buffers use %s in mode-line-format.  */
+  update_mode_lines = 24;  /* In case buffers use %s in mode-line-format.  */
   UNGCPRO;
 }
 
@@ -6522,8 +6586,8 @@ keyboard_bit_set (fd_set *mask)
 #else  /* not subprocesses */
 
 /* Defined on msdos.c.  */
-extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
-                      EMACS_TIME *, void *);
+extern int sys_select (int, fd_set *, fd_set *, fd_set *,
+                      struct timespec *, void *);
 
 /* Implementation of wait_reading_process_output, assuming that there
    are no subprocesses.  Used only by the MS-DOS build.
@@ -6562,7 +6626,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
                             struct Lisp_Process *wait_proc, int just_wait_proc)
 {
   register int nfds;
-  EMACS_TIME end_time, timeout;
+  struct timespec end_time, timeout;
 
   if (time_limit < 0)
     {
@@ -6575,8 +6639,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
   /* What does time_limit really mean?  */
   if (time_limit || nsecs > 0)
     {
-      timeout = make_emacs_time (time_limit, nsecs);
-      end_time = add_emacs_time (current_emacs_time (), timeout);
+      timeout = make_timespec (time_limit, nsecs);
+      end_time = timespec_add (current_timespec (), timeout);
     }
 
   /* Turn off periodic alarms (in case they are in use)
@@ -6588,7 +6652,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
   while (1)
     {
       bool timeout_reduced_for_timers = 0;
-      SELECT_TYPE waitchannels;
+      fd_set waitchannels;
       int xerrno;
 
       /* If calling from keyboard input, do not quit
@@ -6609,18 +6673,18 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
             gobble output available now
             but don't wait at all.  */
 
-         timeout = make_emacs_time (0, 0);
+         timeout = make_timespec (0, 0);
        }
       else if (time_limit || nsecs > 0)
        {
-         EMACS_TIME now = current_emacs_time ();
-         if (EMACS_TIME_LE (end_time, now))
+         struct timespec now = current_timespec ();
+         if (timespec_cmp (end_time, now) <= 0)
            break;
-         timeout = sub_emacs_time (end_time, now);
+         timeout = timespec_sub (end_time, now);
        }
       else
        {
-         timeout = make_emacs_time (100000, 0);
+         timeout = make_timespec (100000, 0);
        }
 
       /* If our caller will not immediately handle keyboard events,
@@ -6629,7 +6693,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
         call timer_delay on their own.)  */
       if (NILP (wait_for_cell))
        {
-         EMACS_TIME timer_delay;
+         struct timespec timer_delay;
 
          do
            {
@@ -6649,9 +6713,9 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
              && requeued_events_pending_p ())
            break;
 
-         if (EMACS_TIME_VALID_P (timer_delay) && nsecs >= 0)
+         if (timespec_valid_p (timer_delay) && nsecs >= 0)
            {
-             if (EMACS_TIME_LT (timer_delay, timeout))
+             if (timespec_cmp (timer_delay, timeout) < 0)
                {
                  timeout = timer_delay;
                  timeout_reduced_for_timers = 1;
@@ -6820,12 +6884,9 @@ BUFFER may be a buffer or the name of one.  */)
   buf = Fget_buffer (buffer);
   if (NILP (buf)) return Qnil;
 
-  for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
-    {
-      proc = Fcdr (XCAR (tail));
-      if (PROCESSP (proc) && EQ (XPROCESS (proc)->buffer, buf))
-       return proc;
-    }
+  FOR_EACH_PROCESS (tail, proc)
+    if (EQ (XPROCESS (proc)->buffer, buf))
+      return proc;
 #endif /* subprocesses */
   return Qnil;
 }
@@ -6858,18 +6919,14 @@ kill_buffer_processes (Lisp_Object buffer)
 #ifdef subprocesses
   Lisp_Object tail, proc;
 
-  for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
-    {
-      proc = XCDR (XCAR (tail));
-      if (PROCESSP (proc)
-         && (NILP (buffer) || EQ (XPROCESS (proc)->buffer, buffer)))
-       {
-         if (NETCONN_P (proc) || SERIALCONN_P (proc))
-           Fdelete_process (proc);
-         else if (XPROCESS (proc)->infd >= 0)
-           process_send_signal (proc, SIGHUP, Qnil, 1);
-       }
-    }
+  FOR_EACH_PROCESS (tail, proc)
+    if (NILP (buffer) || EQ (XPROCESS (proc)->buffer, buffer))
+      {
+       if (NETCONN_P (proc) || SERIALCONN_P (proc))
+         Fdelete_process (proc);
+       else if (XPROCESS (proc)->infd >= 0)
+         process_send_signal (proc, SIGHUP, Qnil, 1);
+      }
 #else  /* subprocesses */
   /* Since we have no subprocesses, this does nothing.  */
 #endif /* subprocesses */
@@ -7059,7 +7116,7 @@ init_process_emacs (void)
 
   Vprocess_alist = Qnil;
   deleted_pid_list = Qnil;
-  for (i = 0; i < MAXDESC; i++)
+  for (i = 0; i < FD_SETSIZE; i++)
     {
       chan_process[i] = Qnil;
       proc_buffered_char[i] = -1;
@@ -7287,14 +7344,8 @@ The variable takes effect when `start-process' is called.  */);
   defsubr (&Sset_network_process_option);
   defsubr (&Smake_network_process);
   defsubr (&Sformat_network_address);
-#if defined (HAVE_NET_IF_H)
-#ifdef SIOCGIFCONF
   defsubr (&Snetwork_interface_list);
-#endif
-#if defined (SIOCGIFADDR) || defined (SIOCGIFHWADDR) || defined (SIOCGIFFLAGS)
   defsubr (&Snetwork_interface_info);
-#endif
-#endif /* defined (HAVE_NET_IF_H) */
 #ifdef DATAGRAM_SOCKETS
   defsubr (&Sprocess_datagram_address);
   defsubr (&Sset_process_datagram_address);