Promote SSDATA macro from gtkutil.c and xsmfns.c to lisp.h.
[bpt/emacs.git] / src / process.c
index f348dca..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,11 +31,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #ifdef HAVE_INTTYPES_H
 #include <inttypes.h>
 #endif
-#include <stdlib.h>
 
-#ifdef HAVE_UNISTD_H
 #include <unistd.h>
-#endif
 #include <fcntl.h>
 
 /* Only MS-DOS does not define `subprocesses'.  */
@@ -57,21 +54,15 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #endif
 #endif
 
-#if defined(HAVE_SYS_IOCTL_H)
 #include <sys/ioctl.h>
 #if defined(HAVE_NET_IF_H)
 #include <net/if.h>
 #endif /* HAVE_NET_IF_H */
-#endif /* HAVE_SYS_IOCTL_H */
 
 #ifdef NEED_BSDTTY
 #include <bsdtty.h>
 #endif
 
-#ifdef HAVE_SYS_WAIT
-#include <sys/wait.h>
-#endif
-
 #ifdef HAVE_RES_INIT
 #include <netinet/in.h>
 #include <arpa/nameser.h>
@@ -82,6 +73,10 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <util.h>
 #endif
 
+#ifdef HAVE_PTY_H
+#include <pty.h>
+#endif
+
 #endif /* subprocesses */
 
 #include "lisp.h"
@@ -105,6 +100,9 @@ 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"
@@ -112,7 +110,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #ifdef HAVE_NS
 #include "nsterm.h"
 #endif
-extern int timers_run;
 
 Lisp_Object Qeuid, Qegid, Qcomm, Qstate, Qppid, Qpgrp, Qsess, Qttname, Qtpgid;
 Lisp_Object Qminflt, Qmajflt, Qcminflt, Qcmajflt, Qutime, Qstime, Qcstime;
@@ -124,9 +121,6 @@ Lisp_Object QCname, QCtype;
 
 static int kbd_is_on_hold;
 
-/* Nonzero means delete a process right away if it exits.  */
-static int delete_exited_processes;
-
 /* Nonzero means don't run process sentinels.  This is used
    when exiting.  */
 int inhibit_sentinels;
@@ -168,13 +162,6 @@ extern Lisp_Object QCfilter;
 /* 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);
 
 /* From sysdep.c or w32.c  */
@@ -185,10 +172,6 @@ extern void serial_configure (struct Lisp_Process *p, Lisp_Object contact);
 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.  */
@@ -198,8 +181,10 @@ 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_SELECT
@@ -255,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
@@ -291,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
@@ -313,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];
@@ -354,14 +331,90 @@ struct sockaddr_and_len {
 /* Maximum number of bytes to send to a pty without an eof.  */
 static int pty_max_bytes;
 
-#ifdef HAVE_PTYS
-#ifdef HAVE_PTY_H
-#include <pty.h>
-#endif
-/* The file name of the pty opened by allocate_pty.  */
+\f
+
+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'.  */
@@ -445,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));
@@ -477,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
@@ -583,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;
@@ -1358,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))
@@ -1376,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))
@@ -1526,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
@@ -1584,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.  */
   }
 
 
@@ -1626,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);
 
@@ -1643,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;
@@ -1781,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);
@@ -2444,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;
@@ -2483,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);
          }
@@ -2768,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)
@@ -3170,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);
     }
 
@@ -3302,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));
 
@@ -3605,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++;
        }
     }
@@ -3717,7 +3793,7 @@ usage: (make-network-process &rest ARGS)  */)
 }
 
 \f
-#if 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,
@@ -3960,7 +4036,7 @@ FLAGS is the current flags of the interface.  */)
   return any ? res : Qnil;
 }
 #endif
-#endif /* defined(HAVE_NET_IF_H) && defined(HAVE_SYS_IOCTL_H) */
+#endif /* defined(HAVE_NET_IF_H) */
 
 /* Turn off input and output for process PROC.  */
 
@@ -4008,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 ();
        }
@@ -4386,10 +4463,8 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
 {
   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;
@@ -4399,11 +4474,9 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
   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!!");
 
@@ -4537,19 +4610,16 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
       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),
@@ -4620,13 +4690,13 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
            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
        {
@@ -4634,7 +4704,12 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
            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;
        }
 
@@ -4659,10 +4734,6 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
        }
       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
@@ -4704,15 +4775,10 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
 #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;
@@ -4752,7 +4818,7 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
       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,
@@ -4848,12 +4914,26 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
       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;
 
@@ -4958,12 +5038,13 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
                }
            }
 #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 ();
 
@@ -5073,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;
@@ -5097,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)
        {
@@ -5130,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
@@ -5263,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;
 
@@ -5403,11 +5496,11 @@ send_process_trap (int ignore)
 
 static void
 send_process (volatile Lisp_Object proc, const unsigned char *volatile buf,
-             volatile int len, volatile Lisp_Object object)
+             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);
@@ -5429,12 +5522,21 @@ send_process (volatile Lisp_Object proc, const 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
@@ -5464,8 +5566,8 @@ send_process (volatile Lisp_Object proc, const 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));
@@ -5517,7 +5619,7 @@ send_process (volatile Lisp_Object proc, const 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)
@@ -5540,7 +5642,14 @@ send_process (volatile Lisp_Object proc, const 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)
@@ -5651,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);
@@ -6592,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) */
@@ -6711,35 +6820,16 @@ DEFUN ("process-filter-multibyte-p", Fprocess_filter_multibyte_p,
 
 \f
 
-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;
+  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
@@ -6750,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;
@@ -6989,11 +7079,11 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
 void
 add_keyboard_wait_descriptor (int desc)
 {
-#ifdef subprocesses
+#ifdef subprocesses /* actually means "not MSDOS" */
   FD_SET (desc, &input_wait_mask);
   FD_SET (desc, &non_process_wait_mask);
-  if (desc > max_keyboard_desc)
-    max_keyboard_desc = desc;
+  if (desc > max_input_desc)
+    max_input_desc = desc;
 #endif
 }
 
@@ -7004,18 +7094,16 @@ delete_keyboard_wait_descriptor (int desc)
 {
 #ifdef subprocesses
   int fd;
-  int lim = max_keyboard_desc;
+  int lim = max_input_desc;
 
   FD_CLR (desc, &input_wait_mask);
   FD_CLR (desc, &non_process_wait_mask);
 
-  if (desc == max_keyboard_desc)
+  if (desc == max_input_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;
-#endif /* subprocesses */
+      if (FD_ISSET (fd, &input_wait_mask) || FD_ISSET (fd, &write_mask))
+        max_input_desc = fd;
+#endif
 }
 
 /* Setup coding systems of PROCESS.  */
@@ -7272,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);
@@ -7540,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:
@@ -7556,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.
@@ -7600,14 +7690,14 @@ 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) && 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 /* defined(HAVE_NET_IF_H) && defined(HAVE_SYS_IOCTL_H) */
+#endif /* defined(HAVE_NET_IF_H) */
 #ifdef DATAGRAM_SOCKETS
   defsubr (&Sprocess_datagram_address);
   defsubr (&Sset_process_datagram_address);
@@ -7637,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) */