Promote SSDATA macro from gtkutil.c and xsmfns.c to lisp.h.
[bpt/emacs.git] / src / process.c
index 226326d..5f28cc6 100644 (file)
@@ -1,7 +1,7 @@
 /* Asynchronous subprocess control for GNU Emacs.
    Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995,
                 1996, 1998, 1999, 2001, 2002, 2003, 2004,
-                2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+                2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -31,19 +31,13 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #ifdef HAVE_INTTYPES_H
 #include <inttypes.h>
 #endif
-#ifdef STDC_HEADERS
-#include <stdlib.h>
-#endif
 
-#ifdef HAVE_UNISTD_H
 #include <unistd.h>
-#endif
 #include <fcntl.h>
 
 /* Only MS-DOS does not define `subprocesses'.  */
 #ifdef subprocesses
 
-#ifdef HAVE_SOCKETS    /* TCP connection support, if kernel can do it */
 #include <sys/socket.h>
 #include <netdb.h>
 #include <netinet/in.h>
@@ -59,40 +53,30 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <sys/un.h>
 #endif
 #endif
-#endif /* HAVE_SOCKETS */
 
-#if defined(HAVE_SYS_IOCTL_H)
 #include <sys/ioctl.h>
-#if !defined (O_NDELAY) && defined (HAVE_PTYS) && !defined(USG5)
-#include <fcntl.h>
-#endif /* HAVE_PTYS and no O_NDELAY */
-#endif /* HAVE_SYS_IOCTL_H */
+#if defined(HAVE_NET_IF_H)
+#include <net/if.h>
+#endif /* HAVE_NET_IF_H */
 
 #ifdef NEED_BSDTTY
 #include <bsdtty.h>
 #endif
 
-/* Can we use SIOCGIFCONF and/or SIOCGIFADDR */
-#ifdef HAVE_SOCKETS
-#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H)
-/* sys/ioctl.h may have been included already */
-#ifndef SIOCGIFADDR
-#include <sys/ioctl.h>
-#endif
-#include <net/if.h>
-#endif
-#endif
-
-#ifdef HAVE_SYS_WAIT
-#include <sys/wait.h>
-#endif
-
 #ifdef HAVE_RES_INIT
 #include <netinet/in.h>
 #include <arpa/nameser.h>
 #include <resolv.h>
 #endif
 
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+
+#ifdef HAVE_PTY_H
+#include <pty.h>
+#endif
+
 #endif /* subprocesses */
 
 #include "lisp.h"
@@ -116,10 +100,30 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "sysselect.h"
 #include "syssignal.h"
 #include "syswait.h"
+#ifdef HAVE_GNUTLS
+#include "gnutls.h"
+#endif
 
 #if defined (USE_GTK) || defined (HAVE_GCONF)
 #include "xgselect.h"
 #endif /* defined (USE_GTK) || defined (HAVE_GCONF) */
+#ifdef HAVE_NS
+#include "nsterm.h"
+#endif
+
+Lisp_Object Qeuid, Qegid, Qcomm, Qstate, Qppid, Qpgrp, Qsess, Qttname, Qtpgid;
+Lisp_Object Qminflt, Qmajflt, Qcminflt, Qcmajflt, Qutime, Qstime, Qcstime;
+Lisp_Object Qcutime, Qpri, Qnice, Qthcount, Qstart, Qvsize, Qrss, Qargs;
+Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem, Qtime, Qctime;
+Lisp_Object QCname, QCtype;
+\f
+/* Non-zero if keyboard input is on hold, zero otherwise.  */
+
+static int kbd_is_on_hold;
+
+/* Nonzero means don't run process sentinels.  This is used
+   when exiting.  */
+int inhibit_sentinels;
 
 #ifdef subprocesses
 
@@ -150,49 +154,24 @@ extern Lisp_Object QCfamily;
 /* QCfilter is defined in keyboard.c.  */
 extern Lisp_Object QCfilter;
 
-#ifdef HAVE_SOCKETS
 #define NETCONN_P(p) (EQ (XPROCESS (p)->type, Qnetwork))
 #define NETCONN1_P(p) (EQ ((p)->type, Qnetwork))
 #define SERIALCONN_P(p) (EQ (XPROCESS (p)->type, Qserial))
 #define SERIALCONN1_P(p) (EQ ((p)->type, Qserial))
-#else
-#define NETCONN_P(p) 0
-#define NETCONN1_P(p) 0
-#define SERIALCONN_P(p) 0
-#define SERIALCONN1_P(p) 0
-#endif /* HAVE_SOCKETS */
 
 /* Define first descriptor number available for subprocesses.  */
 #define FIRST_PROC_DESC 3
 
-/* Define SIGCHLD as an alias for SIGCLD.  There are many conditionals
-   testing SIGCHLD.  */
-
-#if !defined (SIGCHLD) && defined (SIGCLD)
-#define SIGCHLD SIGCLD
-#endif /* SIGCLD */
+extern const char *get_operating_system_release (void);
 
-extern char *get_operating_system_release (void);
-
-/* Serial processes require termios or Windows.  */
-#if defined (HAVE_TERMIOS) || defined (WINDOWSNT)
-#define HAVE_SERIAL
-#endif
-
-#ifdef HAVE_SERIAL
 /* From sysdep.c or w32.c  */
 extern int serial_open (char *port);
 extern void serial_configure (struct Lisp_Process *p, Lisp_Object contact);
-#endif
 
 #ifndef HAVE_H_ERRNO
 extern int h_errno;
 #endif
 
-/* t means use pty, nil means use a pipe,
-   maybe other values to come.  */
-static Lisp_Object Vprocess_connection_type;
-
 /* These next two vars are non-static since sysdep.c uses them in the
    emulation of `select'.  */
 /* Number of events of change of status of a process.  */
@@ -202,11 +181,12 @@ int update_tick;
 
 /* Define NON_BLOCKING_CONNECT if we can support non-blocking connects.  */
 
+/* Only W32 has this, it really means that select can't take write mask.  */
 #ifdef BROKEN_NON_BLOCKING_CONNECT
 #undef NON_BLOCKING_CONNECT
+#define SELECT_CANT_DO_WRITE_MASK
 #else
 #ifndef NON_BLOCKING_CONNECT
-#ifdef HAVE_SOCKETS
 #ifdef HAVE_SELECT
 #if defined (HAVE_GETPEERNAME) || defined (GNU_LINUX)
 #if defined (O_NONBLOCK) || defined (O_NDELAY)
@@ -216,7 +196,6 @@ int update_tick;
 #endif /* O_NONBLOCK || O_NDELAY */
 #endif /* HAVE_GETPEERNAME || GNU_LINUX */
 #endif /* HAVE_SELECT */
-#endif /* HAVE_SOCKETS */
 #endif /* NON_BLOCKING_CONNECT */
 #endif /* BROKEN_NON_BLOCKING_CONNECT */
 
@@ -229,13 +208,11 @@ int update_tick;
 #undef DATAGRAM_SOCKETS
 #else
 #ifndef DATAGRAM_SOCKETS
-#ifdef HAVE_SOCKETS
 #if defined (HAVE_SELECT) || defined (FIONREAD)
 #if defined (HAVE_SENDTO) && defined (HAVE_RECVFROM) && defined (EMSGSIZE)
 #define DATAGRAM_SOCKETS
 #endif /* HAVE_SENDTO && HAVE_RECVFROM && EMSGSIZE */
 #endif /* HAVE_SELECT || FIONREAD */
-#endif /* HAVE_SOCKETS */
 #endif /* DATAGRAM_SOCKETS */
 #endif /* BROKEN_DATAGRAM_SOCKETS */
 
@@ -263,11 +240,6 @@ static int process_output_delay_count;
 
 static int process_output_skip;
 
-/* Non-nil means to delay reading process output to improve buffering.
-   A value of t means that delay is reset after each send, any other
-   non-nil value does not reset the delay.  A value of nil disables
-   adaptive read buffering completely.  */
-static Lisp_Object Vprocess_adaptive_read_buffering;
 #else
 #define process_output_delay_count 0
 #endif
@@ -287,25 +259,6 @@ static void create_pty (Lisp_Object);
 static Lisp_Object get_process (register Lisp_Object name);
 static void exec_sentinel (Lisp_Object proc, Lisp_Object reason);
 
-#endif /* subprocesses */
-
-extern int timers_run;
-
-Lisp_Object Qeuid, Qegid, Qcomm, Qstate, Qppid, Qpgrp, Qsess, Qttname, Qtpgid;
-Lisp_Object Qminflt, Qmajflt, Qcminflt, Qcmajflt, Qutime, Qstime, Qcstime;
-Lisp_Object Qcutime, Qpri, Qnice, Qthcount, Qstart, Qvsize, Qrss, Qargs;
-Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem, Qtime, Qctime;
-Lisp_Object QCname, QCtype;
-\f
-/* Non-zero if keyboard input is on hold, zero otherwise.  */
-
-static int kbd_is_on_hold;
-
-/* Nonzero means delete a process right away if it exits.  */
-static int delete_exited_processes;
-
-#ifdef subprocesses
-
 /* Mask of bits indicating the descriptors that we wait for input on.  */
 
 static SELECT_TYPE input_wait_mask;
@@ -318,9 +271,9 @@ static SELECT_TYPE non_keyboard_wait_mask;
 
 static SELECT_TYPE non_process_wait_mask;
 
-/* Mask for the gpm mouse input descriptor.  */
+/* Mask for selecting for write.  */
 
-static SELECT_TYPE gpm_wait_mask;
+static SELECT_TYPE write_mask;
 
 #ifdef NON_BLOCKING_CONNECT
 /* Mask of bits indicating the descriptors that we wait for connect to
@@ -340,11 +293,8 @@ static int num_pending_connects;
 /* The largest descriptor currently in use for a process object.  */
 static int max_process_desc;
 
-/* The largest descriptor currently in use for keyboard input.  */
-static int max_keyboard_desc;
-
-/* The largest descriptor currently in use for gpm mouse input.  */
-static int max_gpm_desc;
+/* The largest descriptor currently in use for input.  */
+static int max_input_desc;
 
 /* Indexed by descriptor, gives the process (if any) for that descriptor */
 Lisp_Object chan_process[MAXDESC];
@@ -381,18 +331,90 @@ struct sockaddr_and_len {
 /* Maximum number of bytes to send to a pty without an eof.  */
 static int pty_max_bytes;
 
-/* Nonzero means don't run process sentinels.  This is used
-   when exiting.  */
-int inhibit_sentinels;
+\f
 
-#ifdef HAVE_PTYS
-#ifdef HAVE_PTY_H
-#include <pty.h>
-#endif
-/* The file name of the pty opened by allocate_pty.  */
+struct fd_callback_data
+{
+  fd_callback func;
+  void *data;
+#define FOR_READ  1
+#define FOR_WRITE 2
+  int condition; /* mask of the defines above.  */
+} fd_callback_info[MAXDESC];
+
+
+/* Add a file descriptor FD to be monitored for when read is possible.
+   When read is possible, call FUNC with argument DATA.  */
+
+void
+add_read_fd (int fd, fd_callback func, void *data)
+{
+  xassert (fd < MAXDESC);
+  add_keyboard_wait_descriptor (fd);
+
+  fd_callback_info[fd].func = func;
+  fd_callback_info[fd].data = data;
+  fd_callback_info[fd].condition |= FOR_READ;
+}
+
+/* Stop monitoring file descriptor FD for when read is possible.  */
+
+void
+delete_read_fd (int fd)
+{
+  xassert (fd < MAXDESC);
+  delete_keyboard_wait_descriptor (fd);
+
+  fd_callback_info[fd].condition &= ~FOR_READ;
+  if (fd_callback_info[fd].condition == 0)
+    {
+      fd_callback_info[fd].func = 0;
+      fd_callback_info[fd].data = 0;
+    }
+}
+
+/* Add a file descriptor FD to be monitored for when write is possible.
+   When write is possible, call FUNC with argument DATA.  */
+
+void
+add_write_fd (int fd, fd_callback func, void *data)
+{
+  xassert (fd < MAXDESC);
+  FD_SET (fd, &write_mask);
+  if (fd > max_input_desc)
+    max_input_desc = fd;
+
+  fd_callback_info[fd].func = func;
+  fd_callback_info[fd].data = data;
+  fd_callback_info[fd].condition |= FOR_WRITE;
+}
+
+/* Stop monitoring file descriptor FD for when write is possible.  */
+
+void
+delete_write_fd (int fd)
+{
+  int lim = max_input_desc;
+
+  xassert (fd < MAXDESC);
+  FD_CLR (fd, &write_mask);
+  fd_callback_info[fd].condition &= ~FOR_WRITE;
+  if (fd_callback_info[fd].condition == 0)
+    {
+      fd_callback_info[fd].func = 0;
+      fd_callback_info[fd].data = 0;
+
+      if (fd == max_input_desc)
+        for (fd = lim; fd >= 0; fd--)
+          if (FD_ISSET (fd, &input_wait_mask) || FD_ISSET (fd, &write_mask))
+            {
+              max_input_desc = fd;
+              break;
+            }
+
+    }
+}
 
-static char pty_name[24];
-#endif
 \f
 /* Compute the Lisp form of the process status, p->status, from
    the numeric status that was returned by `wait'.  */
@@ -476,7 +498,7 @@ status_message (struct Lisp_Process *p)
          if (! NILP (Vlocale_coding_system))
            string = (code_convert_string_norecord
                      (string, Vlocale_coding_system, 0));
-         c1 = STRING_CHAR ((char *) SDATA (string));
+         c1 = STRING_CHAR (SSDATA (string));
          c2 = DOWNCASE (c1);
          if (c1 != c2)
            Faset (string, make_number (0), make_number (c2));
@@ -508,6 +530,9 @@ status_message (struct Lisp_Process *p)
 \f
 #ifdef HAVE_PTYS
 
+/* The file name of the pty opened by allocate_pty.  */
+static char pty_name[24];
+
 /* Open an available pty, returning a file descriptor.
    Return -1 on failure.
    The file name of the terminal corresponding to the pty
@@ -614,6 +639,12 @@ make_process (Lisp_Object name)
   p->read_output_skip = 0;
 #endif
 
+#ifdef HAVE_GNUTLS
+  p->gnutls_initstage = GNUTLS_STAGE_EMPTY;
+  p->gnutls_log_level = 0;
+  p->gnutls_p = 0;
+#endif
+
   /* If name is already in use, modify it until it is unused.  */
 
   name1 = name;
@@ -1148,7 +1179,6 @@ nil, indicating the current buffer's process.  */)
   return XPROCESS (proc)->type;
 }
 
-#ifdef HAVE_SOCKETS
 DEFUN ("format-network-address", Fformat_network_address, Sformat_network_address,
        1, 2, 0,
        doc: /* Convert network ADDRESS from internal format to a string.
@@ -1222,7 +1252,6 @@ Returns nil if format of ADDRESS is invalid.  */)
 
   return Qnil;
 }
-#endif
 \f
 static Lisp_Object
 list_processes_1 (Lisp_Object query_only)
@@ -1391,7 +1420,7 @@ list_processes_1 (Lisp_Object query_only)
            port = Fformat_network_address (Fplist_get (p->childp, QClocal), Qnil);
          sprintf (tembuf, "(network %s server on %s)\n",
                   (DATAGRAM_CHAN_P (p->infd) ? "datagram" : "stream"),
-                  (STRINGP (port) ? (char *)SDATA (port) : "?"));
+                  (STRINGP (port) ? SSDATA (port) : "?"));
          insert_string (tembuf);
        }
       else if (NETCONN1_P (p))
@@ -1409,7 +1438,7 @@ list_processes_1 (Lisp_Object query_only)
            host = Fformat_network_address (Fplist_get (p->childp, QCremote), Qnil);
          sprintf (tembuf, "(network %s connection to %s)\n",
                   (DATAGRAM_CHAN_P (p->infd) ? "datagram" : "stream"),
-                  (STRINGP (host) ? (char *)SDATA (host) : "?"));
+                  (STRINGP (host) ? SSDATA (host) : "?"));
          insert_string (tembuf);
        }
       else if (SERIALCONN1_P (p))
@@ -1559,6 +1588,12 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
   XPROCESS (proc)->filter = Qnil;
   XPROCESS (proc)->command = Flist (nargs - 2, args + 2);
 
+#ifdef HAVE_GNUTLS
+  /* AKA GNUTLS_INITSTAGE(proc).  */
+  XPROCESS (proc)->gnutls_initstage = GNUTLS_STAGE_EMPTY;
+  XPROCESS (proc)->gnutls_cred_type = Qnil;
+#endif
+
 #ifdef ADAPTIVE_READ_BUFFERING
   XPROCESS (proc)->adaptive_read_buffering
     = (NILP (Vprocess_adaptive_read_buffering) ? 0
@@ -1617,6 +1652,11 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
          val = XCDR (Vdefault_process_coding_system);
       }
     XPROCESS (proc)->encode_coding_system = val;
+    /* Note: At this momemnt, the above coding system may leave
+       text-conversion or eol-conversion unspecified.  They will be
+       decided after we read output from the process and decode it by
+       some coding system, or just before we actually send a text to
+       the process.  */
   }
 
 
@@ -1659,6 +1699,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
        tem = Fsubstring (tem, make_number (2), Qnil);
 
       {
+       Lisp_Object arg_encoding = Qnil;
        struct gcpro gcpro1;
        GCPRO1 (tem);
 
@@ -1676,9 +1717,14 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
            tem = Fcons (args[i], tem);
            CHECK_STRING (XCAR (tem));
            if (STRING_MULTIBYTE (XCAR (tem)))
-             XSETCAR (tem,
-                      code_convert_string_norecord
-                      (XCAR (tem), XPROCESS (proc)->encode_coding_system, 1));
+             {
+               if (NILP (arg_encoding))
+                 arg_encoding = (complement_process_encoding_system
+                                 (XPROCESS (proc)->encode_coding_system));
+               XSETCAR (tem,
+                        code_convert_string_norecord
+                        (XCAR (tem), arg_encoding, 1));
+             }
          }
 
        UNGCPRO;
@@ -1727,25 +1773,6 @@ create_process_1 (struct atimer *timer)
 }
 
 
-#if 0  /* This doesn't work; see the note before sigchld_handler.  */
-#ifdef USG
-#ifdef SIGCHLD
-/* Mimic blocking of signals on system V, which doesn't really have it.  */
-
-/* Nonzero means we got a SIGCHLD when it was supposed to be blocked.  */
-int sigchld_deferred;
-
-SIGTYPE
-create_process_sigchld ()
-{
-  signal (SIGCHLD, create_process_sigchld);
-
-  sigchld_deferred = 1;
-}
-#endif
-#endif
-#endif
-
 void
 create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
 {
@@ -1833,12 +1860,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
     }
 #endif
 
-#if 0
-  /* Replaced by close_process_descs */
-  set_exclusive_use (inchannel);
-  set_exclusive_use (outchannel);
-#endif
-
 #ifdef O_NONBLOCK
   fcntl (inchannel, F_SETFL, O_NONBLOCK);
   fcntl (outchannel, F_SETFL, O_NONBLOCK);
@@ -1943,7 +1964,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
        setpgrp ();
 #endif /* USG */
 #endif /* not HAVE_SETSID */
-#if defined (HAVE_TERMIOS) && defined (LDISC1)
+#if defined (LDISC1)
        if (pty_flag && xforkin >= 0)
          {
            struct termios t;
@@ -2215,8 +2236,6 @@ create_pty (Lisp_Object process)
 }
 
 \f
-#ifdef HAVE_SOCKETS
-
 /* Convert an internal struct sockaddr to a lisp object (vector or string).
    The address family of sa is not included in the result.  */
 
@@ -2447,7 +2466,7 @@ Returns nil upon error setting address, ADDRESS otherwise.  */)
 static const struct socket_options {
   /* The name of this option.  Should be lowercase version of option
      name without SO_ prefix. */
-  char *name;
+  const char *name;
   /* Option level SOL_... */
   int optlevel;
   /* Option number SO_... */
@@ -2498,7 +2517,7 @@ set_socket_option (int s, Lisp_Object opt, Lisp_Object val)
 
   CHECK_SYMBOL (opt);
 
-  name = (char *) SDATA (SYMBOL_NAME (opt));
+  name = SSDATA (SYMBOL_NAME (opt));
   for (sopt = socket_options; sopt->name; sopt++)
     if (strcmp (name, sopt->name) == 0)
       break;
@@ -2537,7 +2556,7 @@ set_socket_option (int s, Lisp_Object opt, Lisp_Object val)
        memset (devname, 0, sizeof devname);
        if (STRINGP (val))
          {
-           char *arg = (char *) SDATA (val);
+           char *arg = SSDATA (val);
            int len = min (strlen (arg), IFNAMSIZ);
            memcpy (devname, arg, len);
          }
@@ -2611,7 +2630,6 @@ OPTION is not a supported option, return nil instead; otherwise return t.  */)
 }
 
 \f
-#ifdef HAVE_SERIAL
 DEFUN ("serial-process-configure",
        Fserial_process_configure,
        Sserial_process_configure,
@@ -2823,7 +2841,7 @@ usage:  (make-serial-process &rest ARGS)  */)
   record_unwind_protect (make_serial_process_unwind, proc);
   p = XPROCESS (proc);
 
-  fd = serial_open ((char*) SDATA (port));
+  fd = serial_open (SSDATA (port));
   p->infd = fd;
   p->outfd = fd;
   if (fd > max_process_desc)
@@ -2907,7 +2925,6 @@ usage:  (make-serial-process &rest ARGS)  */)
   UNGCPRO;
   return proc;
 }
-#endif /* HAVE_SERIAL  */
 
 /* Create a network stream/datagram client/server process.  Treated
    exactly like a normal process when reading and writing.  Primary
@@ -3075,7 +3092,8 @@ usage: (make-network-process &rest ARGS)  */)
 #ifdef HAVE_GETADDRINFO
   struct addrinfo ai, *res, *lres;
   struct addrinfo hints;
-  char *portstring, portbuf[128];
+  const char *portstring;
+  char portbuf[128];
 #else /* HAVE_GETADDRINFO */
   struct _emacs_addrinfo
   {
@@ -3225,7 +3243,9 @@ usage: (make-network-process &rest ARGS)  */)
   if (!NILP (host))
     {
       if (EQ (host, Qlocal))
-       host = build_string ("localhost");
+       /* Depending on setup, "localhost" may map to different IPv4 and/or
+          IPv6 addresses, so it's better to be explicit.  (Bug#6781) */
+       host = build_string ("127.0.0.1");
       CHECK_STRING (host);
     }
 
@@ -3357,7 +3377,7 @@ usage: (make-network-process &rest ARGS)  */)
        /* Attempt to interpret host as numeric inet address */
        {
          unsigned long numeric_addr;
-         numeric_addr = inet_addr ((char *) SDATA (host));
+         numeric_addr = inet_addr (SSDATA (host));
          if (numeric_addr == -1)
            error ("Unknown host \"%s\"", SDATA (host));
 
@@ -3660,6 +3680,7 @@ usage: (make-network-process &rest ARGS)  */)
       if (!FD_ISSET (inch, &connect_wait_mask))
        {
          FD_SET (inch, &connect_wait_mask);
+         FD_SET (inch, &write_mask);
          num_pending_connects++;
        }
     }
@@ -3770,10 +3791,9 @@ usage: (make-network-process &rest ARGS)  */)
   UNGCPRO;
   return proc;
 }
-#endif /* HAVE_SOCKETS */
 
 \f
-#if defined(HAVE_SOCKETS) && defined(HAVE_NET_IF_H) && defined(HAVE_SYS_IOCTL_H)
+#if defined(HAVE_NET_IF_H)
 
 #ifdef SIOCGIFCONF
 DEFUN ("network-interface-list", Fnetwork_interface_list, Snetwork_interface_list, 0, 0, 0,
@@ -4016,7 +4036,7 @@ FLAGS is the current flags of the interface.  */)
   return any ? res : Qnil;
 }
 #endif
-#endif /* HAVE_SOCKETS */
+#endif /* defined(HAVE_NET_IF_H) */
 
 /* Turn off input and output for process PROC.  */
 
@@ -4064,6 +4084,7 @@ deactivate_process (Lisp_Object proc)
       if (FD_ISSET (inchannel, &connect_wait_mask))
        {
          FD_CLR (inchannel, &connect_wait_mask);
+         FD_CLR (inchannel, &write_mask);
          if (--num_pending_connects < 0)
            abort ();
        }
@@ -4435,19 +4456,15 @@ select_wrapper (int n, fd_set *rfd, fd_set *wfd, fd_set *xfd, struct timeval *tm
    Otherwise, return true if we received input from any process.  */
 
 int
-wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
-                            wait_for_cell, wait_proc, just_wait_proc)
-     int time_limit, microsecs, read_kbd, do_display;
-     Lisp_Object wait_for_cell;
-     struct Lisp_Process *wait_proc;
-     int just_wait_proc;
+wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
+                            int do_display,
+                            Lisp_Object wait_for_cell,
+                            struct Lisp_Process *wait_proc, int just_wait_proc)
 {
   register int channel, nfds;
   SELECT_TYPE Available;
-#ifdef NON_BLOCKING_CONNECT
-  SELECT_TYPE Connecting;
-  int check_connect;
-#endif
+  SELECT_TYPE Writeok;
+  int check_write;
   int check_delay, no_avail;
   int xerrno;
   Lisp_Object proc;
@@ -4457,11 +4474,9 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
   int count = SPECPDL_INDEX ();
 
   FD_ZERO (&Available);
-#ifdef NON_BLOCKING_CONNECT
-  FD_ZERO (&Connecting);
-#endif
+  FD_ZERO (&Writeok);
 
-  if (time_limit == 0 && wait_proc && !NILP (Vinhibit_quit)
+  if (time_limit == 0 && microsecs == 0 && wait_proc && !NILP (Vinhibit_quit)
       && !(CONSP (wait_proc->status) && EQ (XCAR (wait_proc->status), Qexit)))
     message ("Blocking call to accept-process-output with quit inhibited!!");
 
@@ -4595,19 +4610,16 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
       if (update_tick != process_tick)
        {
          SELECT_TYPE Atemp;
-#ifdef NON_BLOCKING_CONNECT
          SELECT_TYPE Ctemp;
-#endif
 
           if (kbd_on_hold_p ())
             FD_ZERO (&Atemp);
           else
             Atemp = input_wait_mask;
-         IF_NON_BLOCKING_CONNECT (Ctemp = connect_wait_mask);
+         Ctemp = write_mask;
 
          EMACS_SET_SECS_USECS (timeout, 0, 0);
-         if ((select (max (max (max_process_desc, max_keyboard_desc),
-                             max_gpm_desc) + 1,
+         if ((select (max (max_process_desc, max_input_desc) + 1,
                       &Atemp,
 #ifdef NON_BLOCKING_CONNECT
                       (num_pending_connects > 0 ? &Ctemp : (SELECT_TYPE *)0),
@@ -4678,13 +4690,13 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
            break;
          FD_SET (wait_proc->infd, &Available);
          check_delay = 0;
-         IF_NON_BLOCKING_CONNECT (check_connect = 0);
+          check_write = 0;
        }
       else if (!NILP (wait_for_cell))
        {
          Available = non_process_wait_mask;
          check_delay = 0;
-         IF_NON_BLOCKING_CONNECT (check_connect = 0);
+         check_write = 0;
        }
       else
        {
@@ -4692,7 +4704,12 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
            Available = non_keyboard_wait_mask;
          else
            Available = input_wait_mask;
-         IF_NON_BLOCKING_CONNECT (check_connect = (num_pending_connects > 0));
+          Writeok = write_mask;
+#ifdef SELECT_CANT_DO_WRITE_MASK
+          check_write = 0;
+#else
+          check_write = 1;
+#endif
          check_delay = wait_channel >= 0 ? 0 : process_output_delay_count;
        }
 
@@ -4717,10 +4734,6 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
        }
       else
        {
-#ifdef NON_BLOCKING_CONNECT
-         if (check_connect)
-           Connecting = connect_wait_mask;
-#endif
 
 #ifdef ADAPTIVE_READ_BUFFERING
          /* Set the timeout for adaptive read buffering if any
@@ -4762,15 +4775,10 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
 #else
          nfds = select
 #endif
-                       (max (max (max_process_desc, max_keyboard_desc),
-                             max_gpm_desc) + 1,
-                        &Available,
-#ifdef NON_BLOCKING_CONNECT
-                        (check_connect ? &Connecting : (SELECT_TYPE *)0),
-#else
-                        (SELECT_TYPE *)0,
-#endif
-                        (SELECT_TYPE *)0, &timeout);
+            (max (max_process_desc, max_input_desc) + 1,
+             &Available,
+             (check_write ? &Writeok : (SELECT_TYPE *)0),
+             (SELECT_TYPE *)0, &timeout);
        }
 
       xerrno = errno;
@@ -4810,7 +4818,7 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
       if (no_avail)
        {
          FD_ZERO (&Available);
-         IF_NON_BLOCKING_CONNECT (check_connect = 0);
+         check_write = 0;
        }
 
 #if 0 /* When polling is used, interrupt_input is 0,
@@ -4906,12 +4914,26 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
       if (no_avail || nfds == 0)
        continue;
 
+      for (channel = 0; channel <= max_input_desc; ++channel)
+        {
+          struct fd_callback_data *d = &fd_callback_info[channel];
+          if (FD_ISSET (channel, &Available)
+              && d->func != 0
+              && (d->condition & FOR_READ) != 0)
+            d->func (channel, d->data, 1);
+          if (FD_ISSET (channel, &write_mask)
+              && d->func != 0
+              && (d->condition & FOR_WRITE) != 0)
+            d->func (channel, d->data, 0);
+          }
+
       /* Really FIRST_PROC_DESC should be 0 on Unix,
         but this is safer in the short run.  */
       for (channel = 0; channel <= max_process_desc; channel++)
        {
          if (FD_ISSET (channel, &Available)
-             && FD_ISSET (channel, &non_keyboard_wait_mask))
+             && FD_ISSET (channel, &non_keyboard_wait_mask)
+              && !FD_ISSET (channel, &non_process_wait_mask))
            {
              int nread;
 
@@ -5016,12 +5038,13 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
                }
            }
 #ifdef NON_BLOCKING_CONNECT
-         if (check_connect && FD_ISSET (channel, &Connecting)
+         if (FD_ISSET (channel, &Writeok)
              && FD_ISSET (channel, &connect_wait_mask))
            {
              struct Lisp_Process *p;
 
              FD_CLR (channel, &connect_wait_mask);
+              FD_CLR (channel, &write_mask);
              if (--num_pending_connects < 0)
                abort ();
 
@@ -5131,7 +5154,7 @@ read_process_output (Lisp_Object proc, register int channel)
   char *chars;
   register Lisp_Object outstream;
   register struct Lisp_Process *p = XPROCESS (proc);
-  register int opoint;
+  register EMACS_INT opoint;
   struct coding_system *coding = proc_decode_coding_system[channel];
   int carryover = p->decoding_carryover;
   int readmax = 4096;
@@ -5155,7 +5178,13 @@ read_process_output (Lisp_Object proc, register int channel)
 #endif
   if (proc_buffered_char[channel] < 0)
     {
-      nbytes = emacs_read (channel, chars + carryover, readmax);
+#ifdef HAVE_GNUTLS
+      if (XPROCESS (proc)->gnutls_p)
+       nbytes = emacs_gnutls_read (channel, XPROCESS (proc),
+                                    chars + carryover, readmax);
+      else
+#endif
+       nbytes = emacs_read (channel, chars + carryover, readmax);
 #ifdef ADAPTIVE_READ_BUFFERING
       if (nbytes > 0 && p->adaptive_read_buffering)
        {
@@ -5188,7 +5217,13 @@ read_process_output (Lisp_Object proc, register int channel)
     {
       chars[carryover] = proc_buffered_char[channel];
       proc_buffered_char[channel] = -1;
-      nbytes = emacs_read (channel, chars + carryover + 1,  readmax - 1);
+#ifdef HAVE_GNUTLS
+      if (XPROCESS (proc)->gnutls_p)
+       nbytes = emacs_gnutls_read (channel, XPROCESS (proc),
+                                    chars + carryover + 1, readmax - 1);
+      else
+#endif
+       nbytes = emacs_read (channel, chars + carryover + 1,  readmax - 1);
       if (nbytes < 0)
        nbytes = 1;
       else
@@ -5321,10 +5356,10 @@ read_process_output (Lisp_Object proc, register int channel)
   else if (!NILP (p->buffer) && !NILP (XBUFFER (p->buffer)->name))
     {
       Lisp_Object old_read_only;
-      int old_begv, old_zv;
-      int old_begv_byte, old_zv_byte;
-      int before, before_byte;
-      int opoint_byte;
+      EMACS_INT old_begv, old_zv;
+      EMACS_INT old_begv_byte, old_zv_byte;
+      EMACS_INT before, before_byte;
+      EMACS_INT opoint_byte;
       Lisp_Object text;
       struct buffer *b;
 
@@ -5435,15 +5470,6 @@ read_process_output (Lisp_Object proc, register int channel)
   unbind_to (count, Qnil);
   return nbytes;
 }
-
-DEFUN ("waiting-for-user-input-p", Fwaiting_for_user_input_p, Swaiting_for_user_input_p,
-       0, 0, 0,
-       doc: /* Returns non-nil if Emacs is waiting for input from the user.
-This is intended for use by asynchronous process output filters and sentinels.  */)
-  (void)
-{
-  return (waiting_for_user_input_p ? Qt : Qnil);
-}
 \f
 /* Sending data to subprocess */
 
@@ -5469,12 +5495,12 @@ send_process_trap (int ignore)
    This function can evaluate Lisp code and can garbage collect.  */
 
 static void
-send_process (volatile Lisp_Object proc, unsigned char *volatile buf,
-             volatile int len, volatile Lisp_Object object)
+send_process (volatile Lisp_Object proc, const unsigned char *volatile buf,
+             volatile EMACS_INT len, volatile Lisp_Object object)
 {
   /* Use volatile to protect variables from being clobbered by longjmp.  */
   struct Lisp_Process *p = XPROCESS (proc);
-  int rv;
+  EMACS_INT rv;
   struct coding_system *coding;
   struct gcpro gcpro1;
   SIGTYPE (*volatile old_sigpipe) (int);
@@ -5496,12 +5522,21 @@ send_process (volatile Lisp_Object proc, unsigned char *volatile buf,
          && !NILP (XBUFFER (object)->enable_multibyte_characters))
       || EQ (object, Qt))
     {
+      p->encode_coding_system
+       = complement_process_encoding_system (p->encode_coding_system);
       if (!EQ (Vlast_coding_system_used, p->encode_coding_system))
-       /* The coding system for encoding was changed to raw-text
-          because we sent a unibyte text previously.  Now we are
-          sending a multibyte text, thus we must encode it by the
-          original coding system specified for the current process.  */
-       setup_coding_system (p->encode_coding_system, coding);
+       {
+         /* The coding system for encoding was changed to raw-text
+            because we sent a unibyte text previously.  Now we are
+            sending a multibyte text, thus we must encode it by the
+            original coding system specified for the current process.
+
+            Another reason we comming here is that the coding system
+            was just complemented and new one was returned by
+            complement_process_encoding_system.  */
+         setup_coding_system (p->encode_coding_system, coding);
+         Vlast_coding_system_used = p->encode_coding_system;
+       }
       coding->src_multibyte = 1;
     }
   else
@@ -5531,8 +5566,8 @@ send_process (volatile Lisp_Object proc, unsigned char *volatile buf,
       coding->dst_object = Qt;
       if (BUFFERP (object))
        {
-         int from_byte, from, to;
-         int save_pt, save_pt_byte;
+         EMACS_INT from_byte, from, to;
+         EMACS_INT save_pt, save_pt_byte;
          struct buffer *cur = current_buffer;
 
          set_buffer_internal (XBUFFER (object));
@@ -5584,7 +5619,7 @@ send_process (volatile Lisp_Object proc, unsigned char *volatile buf,
       process_sent_to = proc;
       while (len > 0)
        {
-         int this = len;
+         EMACS_INT this = len;
 
          /* Send this batch, using one or more write calls.  */
          while (this > 0)
@@ -5607,7 +5642,14 @@ send_process (volatile Lisp_Object proc, unsigned char *volatile buf,
              else
 #endif
                {
-                 rv = emacs_write (outfd, (char *) buf, this);
+#ifdef HAVE_GNUTLS
+                 if (XPROCESS (proc)->gnutls_p)
+                   rv = emacs_gnutls_write (outfd,
+                                            XPROCESS (proc),
+                                            (char *) buf, this);
+                 else
+#endif
+                   rv = emacs_write (outfd, (char *) buf, this);
 #ifdef ADAPTIVE_READ_BUFFERING
                  if (p->read_output_delay > 0
                      && p->adaptive_read_buffering == 1)
@@ -5718,7 +5760,7 @@ Output from processes can arrive in between bunches.  */)
   (Lisp_Object process, Lisp_Object start, Lisp_Object end)
 {
   Lisp_Object proc;
-  int start1, end1;
+  EMACS_INT start1, end1;
 
   proc = get_process (process);
   validate_region (&start, &end);
@@ -5854,9 +5896,6 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group,
       /* 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;
       cc_t *sig_char = NULL;
 
@@ -5888,65 +5927,6 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group,
        }
       /* If we can't send the signal with a character,
         fall through and send it another way.  */
-#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;
-
-      switch (signo)
-       {
-       case SIGINT:
-         ioctl (p->infd, TIOCGETC, &c);
-         send_process (proc, &c.t_intrc, 1, Qnil);
-         return;
-       case SIGQUIT:
-         ioctl (p->infd, TIOCGETC, &c);
-         send_process (proc, &c.t_quitc, 1, Qnil);
-         return;
-#ifdef SIGTSTP
-       case SIGTSTP:
-         ioctl (p->infd, TIOCGLTC, &lc);
-         send_process (proc, &lc.t_suspc, 1, Qnil);
-         return;
-#endif /* ! defined (SIGTSTP) */
-       }
-
-#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 (p->infd, TCGETA, &t);
-         send_process (proc, &t.c_cc[VINTR], 1, Qnil);
-         return;
-       case SIGQUIT:
-         ioctl (p->infd, TCGETA, &t);
-         send_process (proc, &t.c_cc[VQUIT], 1, Qnil);
-         return;
-#ifdef SIGTSTP
-       case SIGTSTP:
-         ioctl (p->infd, TCGETA, &t);
-         send_process (proc, &t.c_cc[VSWTCH], 1, Qnil);
-         return;
-#endif /* ! defined (SIGTSTP) */
-       }
-#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) */
-       /* In this case, the code above should alway return.  */
-       abort ();
-#endif /* ! defined HAVE_TERMIOS */
 
       /* The code above may fall through if it can't
         handle the signal.  */
@@ -6075,7 +6055,6 @@ If PROCESS is a network or serial process, inhibit handling of incoming
 traffic.  */)
   (Lisp_Object process, Lisp_Object current_group)
 {
-#ifdef HAVE_SOCKETS
   if (PROCESSP (process) && (NETCONN_P (process) || SERIALCONN_P (process)))
     {
       struct Lisp_Process *p;
@@ -6090,7 +6069,6 @@ traffic.  */)
       p->command = Qt;
       return process;
     }
-#endif
 #ifndef SIGTSTP
   error ("No SIGTSTP support");
 #else
@@ -6106,7 +6084,6 @@ If PROCESS is a network or serial process, resume handling of incoming
 traffic.  */)
   (Lisp_Object process, Lisp_Object current_group)
 {
-#ifdef HAVE_SOCKETS
   if (PROCESSP (process) && (NETCONN_P (process) || SERIALCONN_P (process)))
     {
       struct Lisp_Process *p;
@@ -6121,15 +6098,13 @@ traffic.  */)
 #ifdef WINDOWSNT
          if (fd_info[ p->infd ].flags & FILE_SERIAL)
            PurgeComm (fd_info[ p->infd ].hnd, PURGE_RXABORT | PURGE_RXCLEAR);
-#endif
-#ifdef HAVE_TERMIOS
+#else /* not WINDOWSNT */
          tcflush (p->infd, TCIFLUSH);
-#endif
+#endif /* not WINDOWSNT */
        }
       p->command = Qnil;
       return process;
     }
-#endif
 #ifdef SIGCONT
     process_send_signal (process, SIGCONT, current_group, 0);
 #else
@@ -6339,10 +6314,10 @@ process has been transmitted to the serial port.  */)
     send_process (proc, "\004", 1, Qnil);
   else if (EQ (XPROCESS (proc)->type, Qserial))
     {
-#ifdef HAVE_TERMIOS
+#ifndef WINDOWSNT
       if (tcdrain (XPROCESS (proc)->outfd) != 0)
        error ("tcdrain() failed: %s", emacs_strerror (errno));
-#endif
+#endif /* not WINDOWSNT */
       /* Do nothing on Windows because writes are blocking.  */
     }
   else
@@ -6413,8 +6388,7 @@ sigchld_handler (int signo)
 {
   int old_errno = errno;
   Lisp_Object proc;
-  register struct Lisp_Process *p;
-  extern EMACS_TIME *input_available_clear_time;
+  struct Lisp_Process *p;
 
   SIGNAL_THREAD_CHECK (signo);
 
@@ -6727,8 +6701,8 @@ status_notify (struct Lisp_Process *deleting_process)
            {
              Lisp_Object tem;
              struct buffer *old = current_buffer;
-             int opoint, opoint_byte;
-             int before, before_byte;
+             EMACS_INT opoint, opoint_byte;
+             EMACS_INT before, before_byte;
 
              /* Avoid error if buffer is deleted
                 (probably that's why the process is dead, too) */
@@ -6846,65 +6820,16 @@ DEFUN ("process-filter-multibyte-p", Fprocess_filter_multibyte_p,
 
 \f
 
-/* Add DESC to the set of keyboard input descriptors.  */
-
-void
-add_keyboard_wait_descriptor (int desc)
-{
-  FD_SET (desc, &input_wait_mask);
-  FD_SET (desc, &non_process_wait_mask);
-  if (desc > max_keyboard_desc)
-    max_keyboard_desc = desc;
-}
-
-static int add_gpm_wait_descriptor_called_flag;
-
 void
 add_gpm_wait_descriptor (int desc)
 {
-  if (! add_gpm_wait_descriptor_called_flag)
-    FD_CLR (0, &input_wait_mask);
-  add_gpm_wait_descriptor_called_flag = 1;
-  FD_SET (desc, &input_wait_mask);
-  FD_SET (desc, &gpm_wait_mask);
-  if (desc > max_gpm_desc)
-    max_gpm_desc = desc;
-}
-
-/* From now on, do not expect DESC to give keyboard input.  */
-
-void
-delete_keyboard_wait_descriptor (int desc)
-{
-  int fd;
-  int lim = max_keyboard_desc;
-
-  FD_CLR (desc, &input_wait_mask);
-  FD_CLR (desc, &non_process_wait_mask);
-
-  if (desc == max_keyboard_desc)
-    for (fd = 0; fd < lim; fd++)
-      if (FD_ISSET (fd, &input_wait_mask)
-         && !FD_ISSET (fd, &non_keyboard_wait_mask)
-         && !FD_ISSET (fd, &gpm_wait_mask))
-       max_keyboard_desc = fd;
+  add_keyboard_wait_descriptor (desc);
 }
 
 void
 delete_gpm_wait_descriptor (int desc)
 {
-  int fd;
-  int lim = max_gpm_desc;
-
-  FD_CLR (desc, &input_wait_mask);
-  FD_CLR (desc, &non_process_wait_mask);
-
-  if (desc == max_gpm_desc)
-    for (fd = 0; fd < lim; fd++)
-      if (FD_ISSET (fd, &input_wait_mask)
-         && !FD_ISSET (fd, &non_keyboard_wait_mask)
-         && !FD_ISSET (fd, &non_process_wait_mask))
-       max_gpm_desc = fd;
+  delete_keyboard_wait_descriptor (desc);
 }
 
 /* Return nonzero if *MASK has a bit set
@@ -6915,7 +6840,7 @@ keyboard_bit_set (fd_set *mask)
 {
   int fd;
 
-  for (fd = 0; fd <= max_keyboard_desc; fd++)
+  for (fd = 0; fd <= max_input_desc; fd++)
     if (FD_ISSET (fd, mask) && FD_ISSET (fd, &input_wait_mask)
        && !FD_ISSET (fd, &non_keyboard_wait_mask))
       return 1;
@@ -6954,12 +6879,10 @@ extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
    Return true if we received input from any process.  */
 
 int
-wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
-                            wait_for_cell, wait_proc, just_wait_proc)
-     int time_limit, microsecs, read_kbd, do_display;
-     Lisp_Object wait_for_cell;
-     struct Lisp_Process *wait_proc;
-     int just_wait_proc;
+wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
+                            int do_display,
+                            Lisp_Object wait_for_cell,
+                            struct Lisp_Process *wait_proc, int just_wait_proc)
 {
   register int nfds;
   EMACS_TIME end_time, timeout;
@@ -7151,6 +7074,38 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
 /* The following functions are needed even if async subprocesses are
    not supported.  Some of them are no-op stubs in that case.  */
 
+/* Add DESC to the set of keyboard input descriptors.  */
+
+void
+add_keyboard_wait_descriptor (int desc)
+{
+#ifdef subprocesses /* actually means "not MSDOS" */
+  FD_SET (desc, &input_wait_mask);
+  FD_SET (desc, &non_process_wait_mask);
+  if (desc > max_input_desc)
+    max_input_desc = desc;
+#endif
+}
+
+/* From now on, do not expect DESC to give keyboard input.  */
+
+void
+delete_keyboard_wait_descriptor (int desc)
+{
+#ifdef subprocesses
+  int fd;
+  int lim = max_input_desc;
+
+  FD_CLR (desc, &input_wait_mask);
+  FD_CLR (desc, &non_process_wait_mask);
+
+  if (desc == max_input_desc)
+    for (fd = 0; fd < lim; fd++)
+      if (FD_ISSET (fd, &input_wait_mask) || FD_ISSET (fd, &write_mask))
+        max_input_desc = fd;
+#endif
+}
+
 /* Setup coding systems of PROCESS.  */
 
 void
@@ -7279,6 +7234,19 @@ kill_buffer_processes (Lisp_Object buffer)
 #endif /* subprocesses */
 }
 
+DEFUN ("waiting-for-user-input-p", Fwaiting_for_user_input_p, Swaiting_for_user_input_p,
+       0, 0, 0,
+       doc: /* Returns non-nil if Emacs is waiting for input from the user.
+This is intended for use by asynchronous process output filters and sentinels.  */)
+  (void)
+{
+#ifdef subprocesses
+  return (waiting_for_user_input_p ? Qt : Qnil);
+#else
+  return Qnil;
+#endif
+}
+
 /* Stop reading input from keyboard sources.  */
 
 void
@@ -7392,7 +7360,9 @@ init_process (void)
   FD_ZERO (&input_wait_mask);
   FD_ZERO (&non_keyboard_wait_mask);
   FD_ZERO (&non_process_wait_mask);
+  FD_ZERO (&write_mask);
   max_process_desc = 0;
+  memset (fd_callback_info, 0, sizeof (fd_callback_info));
 
 #ifdef NON_BLOCKING_CONNECT
   FD_ZERO (&connect_wait_mask);
@@ -7426,7 +7396,6 @@ init_process (void)
   memset (datagram_address, 0, sizeof datagram_address);
 #endif
 
-#ifdef HAVE_SOCKETS
  {
    Lisp_Object subfeatures = Qnil;
    const struct socket_options *sopt;
@@ -7462,14 +7431,13 @@ init_process (void)
 
    Fprovide (intern_c_string ("make-network-process"), subfeatures);
  }
-#endif /* HAVE_SOCKETS */
 
 #if defined (DARWIN_OS)
   /* PTYs are broken on Darwin < 6, but are sometimes useful for interactive
      processes.  As such, we only change the default value.  */
  if (initialized)
   {
-    char *release = get_operating_system_release ();
+    const char *release = get_operating_system_release ();
     if (!release || !release[0] || (release[0] < MIN_PTY_KERNEL_VERSION
                                    && release[1] == '.')) {
       Vprocess_connection_type = Qnil;
@@ -7662,14 +7630,14 @@ syms_of_process (void)
   Qargs = intern_c_string ("args");
   staticpro (&Qargs);
 
-  DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes,
+  DEFVAR_BOOL ("delete-exited-processes", delete_exited_processes,
               doc: /* *Non-nil means delete processes immediately when they exit.
 A value of nil means don't delete them until `list-processes' is run.  */);
 
   delete_exited_processes = 1;
 
 #ifdef subprocesses
-  DEFVAR_LISP ("process-connection-type", &Vprocess_connection_type,
+  DEFVAR_LISP ("process-connection-type", Vprocess_connection_type,
               doc: /* Control type of device used to communicate with subprocesses.
 Values are nil to use a pipe, or t or `pty' to use a pty.
 The value has no effect if the system has no ptys or if all ptys are busy:
@@ -7678,7 +7646,7 @@ The value takes effect when `start-process' is called.  */);
   Vprocess_connection_type = Qt;
 
 #ifdef ADAPTIVE_READ_BUFFERING
-  DEFVAR_LISP ("process-adaptive-read-buffering", &Vprocess_adaptive_read_buffering,
+  DEFVAR_LISP ("process-adaptive-read-buffering", Vprocess_adaptive_read_buffering,
               doc: /* If non-nil, improve receive buffering by delaying after short reads.
 On some systems, when Emacs reads the output from a subprocess, the output data
 is read in very small blocks, potentially resulting in very poor performance.
@@ -7717,23 +7685,19 @@ The variable takes effect when `start-process' is called.  */);
   defsubr (&Slist_processes);
   defsubr (&Sprocess_list);
   defsubr (&Sstart_process);
-#ifdef HAVE_SERIAL
   defsubr (&Sserial_process_configure);
   defsubr (&Smake_serial_process);
-#endif /* HAVE_SERIAL  */
-#ifdef HAVE_SOCKETS
   defsubr (&Sset_network_process_option);
   defsubr (&Smake_network_process);
   defsubr (&Sformat_network_address);
-#endif /* HAVE_SOCKETS */
-#if defined(HAVE_SOCKETS) && defined(HAVE_NET_IF_H) && defined(HAVE_SYS_IOCTL_H)
+#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 /* HAVE_SOCKETS ... */
+#endif /* defined(HAVE_NET_IF_H) */
 #ifdef DATAGRAM_SOCKETS
   defsubr (&Sprocess_datagram_address);
   defsubr (&Sset_process_datagram_address);
@@ -7763,6 +7727,3 @@ The variable takes effect when `start-process' is called.  */);
   defsubr (&Slist_system_processes);
   defsubr (&Sprocess_attributes);
 }
-
-/* arch-tag: 3706c011-7b9a-4117-bd4f-59e7f701a4c4
-   (do not change this comment) */