]> code.delx.au - gnu-emacs/blobdiff - src/process.c
Speed up insertion of subprocess output on MS-Windows.
[gnu-emacs] / src / process.c
index a9a8eb79edecdf28566aa6376ef1b4c7b3d5d8ae..bdf16b7dbd25a1399aad4579613ee06155e190f0 100644 (file)
@@ -1,6 +1,6 @@
 /* Asynchronous subprocess control for GNU Emacs.
 
-Copyright (C) 1985-1988, 1993-1996, 1998-1999, 2001-2011
+Copyright (C) 1985-1988, 1993-1996, 1998-1999, 2001-2012
   Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -24,17 +24,16 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <stdio.h>
 #include <errno.h>
 #include <setjmp.h>
-#include <sys/types.h>         /* some typedefs are used in sys/file.h */
+#include <sys/types.h>         /* Some typedefs are used in sys/file.h.  */
 #include <sys/file.h>
 #include <sys/stat.h>
 #include <setjmp.h>
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
 
 #include <unistd.h>
 #include <fcntl.h>
 
+#include "lisp.h"
+
 /* Only MS-DOS does not define `subprocesses'.  */
 #ifdef subprocesses
 
@@ -55,10 +54,21 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #endif
 
 #include <sys/ioctl.h>
-#if defined(HAVE_NET_IF_H)
+#if defined (HAVE_NET_IF_H)
 #include <net/if.h>
 #endif /* HAVE_NET_IF_H */
 
+#if defined (HAVE_IFADDRS_H)
+/* Must be after net/if.h */
+#include <ifaddrs.h>
+
+/* We only use structs from this header when we use getifaddrs.  */
+#if defined (HAVE_NET_IF_DL_H)
+#include <net/if_dl.h>
+#endif
+
+#endif
+
 #ifdef NEED_BSDTTY
 #include <bsdtty.h>
 #endif
@@ -79,7 +89,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #endif /* subprocesses */
 
-#include "lisp.h"
 #include "systime.h"
 #include "systty.h"
 
@@ -104,9 +113,9 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "gnutls.h"
 #endif
 
-#if defined (USE_GTK) || defined (HAVE_GCONF)
+#if defined (USE_GTK) || defined (HAVE_GCONF) || defined (HAVE_GSETTINGS)
 #include "xgselect.h"
-#endif /* defined (USE_GTK) || defined (HAVE_GCONF) */
+#endif
 #ifdef HAVE_NS
 #include "nsterm.h"
 #endif
@@ -128,21 +137,23 @@ int inhibit_sentinels;
 #ifdef subprocesses
 
 Lisp_Object Qprocessp;
-Lisp_Object Qrun, Qstop, Qsignal;
-Lisp_Object Qopen, Qclosed, Qconnect, Qfailed, Qlisten;
-Lisp_Object Qlocal, Qipv4, Qdatagram, Qseqpacket;
-Lisp_Object Qreal, Qnetwork, Qserial;
+static Lisp_Object Qrun, Qstop, Qsignal;
+static Lisp_Object Qopen, Qclosed, Qconnect, Qfailed, Qlisten;
+Lisp_Object Qlocal;
+static Lisp_Object Qipv4, Qdatagram, Qseqpacket;
+static Lisp_Object Qreal, Qnetwork, Qserial;
 #ifdef AF_INET6
-Lisp_Object Qipv6;
+static Lisp_Object Qipv6;
 #endif
-Lisp_Object QCport, QCspeed, QCprocess;
+static Lisp_Object QCport, QCprocess;
+Lisp_Object QCspeed;
 Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven;
 Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary;
-Lisp_Object QCbuffer, QChost, QCservice;
-Lisp_Object QClocal, QCremote, QCcoding;
-Lisp_Object QCserver, QCnowait, QCnoquery, QCstop;
-Lisp_Object QCsentinel, QClog, QCoptions, QCplist;
-Lisp_Object Qlast_nonmenu_event;
+static Lisp_Object QCbuffer, QChost, QCservice;
+static Lisp_Object QClocal, QCremote, QCcoding;
+static Lisp_Object QCserver, QCnowait, QCnoquery, QCstop;
+static Lisp_Object QCsentinel, QClog, QCoptions, QCplist;
+static Lisp_Object Qlast_nonmenu_event;
 /* QCfamily is declared and initialized in xfaces.c,
    QCfilter in keyboard.c.  */
 extern Lisp_Object QCfamily, QCfilter;
@@ -163,12 +174,10 @@ extern Lisp_Object QCfilter;
 extern int h_errno;
 #endif
 
-/* 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.  */
-int process_tick;
+static int process_tick;
 /* Number of events for which the user or sentinel has been notified.  */
-int update_tick;
+static int update_tick;
 
 /* Define NON_BLOCKING_CONNECT if we can support non-blocking connects.  */
 
@@ -235,7 +244,11 @@ static int process_output_skip;
 #define process_output_delay_count 0
 #endif
 
+static Lisp_Object Fget_process (Lisp_Object);
+static void create_process (Lisp_Object, char **, Lisp_Object);
+#ifdef SIGIO
 static int keyboard_bit_set (SELECT_TYPE *);
+#endif
 static void deactivate_process (Lisp_Object);
 static void status_notify (struct Lisp_Process *);
 static int read_process_output (Lisp_Object, int);
@@ -243,7 +256,7 @@ static void create_pty (Lisp_Object);
 
 /* If we support a window system, turn on the code to poll periodically
    to detect C-g.  It isn't actually used when doing interrupt input.  */
-#ifdef HAVE_WINDOW_SYSTEM
+#if defined (HAVE_WINDOW_SYSTEM) && !defined (USE_ASYNC_EVENTS)
 #define POLL_FOR_INPUT
 #endif
 
@@ -284,10 +297,10 @@ static int max_process_desc;
 static int max_input_desc;
 
 /* Indexed by descriptor, gives the process (if any) for that descriptor */
-Lisp_Object chan_process[MAXDESC];
+static Lisp_Object chan_process[MAXDESC];
 
 /* Alist of elements (NAME . PROCESS) */
-Lisp_Object Vprocess_alist;
+static Lisp_Object Vprocess_alist;
 
 /* Buffered-ahead input char from process, indexed by channel.
    -1 means empty (no char is buffered).
@@ -295,8 +308,7 @@ Lisp_Object Vprocess_alist;
    output from the process is to read at least one char.
    Always -1 on systems that support FIONREAD.  */
 
-/* Don't make static; need to access externally.  */
-int proc_buffered_char[MAXDESC];
+static int proc_buffered_char[MAXDESC];
 
 /* Table of `struct coding-system' for each process.  */
 static struct coding_system *proc_decode_coding_system[MAXDESC];
@@ -304,7 +316,7 @@ static struct coding_system *proc_encode_coding_system[MAXDESC];
 
 #ifdef DATAGRAM_SOCKETS
 /* Table of `partner address' for datagram sockets.  */
-struct sockaddr_and_len {
+static struct sockaddr_and_len {
   struct sockaddr *sa;
   int len;
 } datagram_address[MAXDESC];
@@ -320,7 +332,7 @@ static int pty_max_bytes;
 
 \f
 
-struct fd_callback_data
+static struct fd_callback_data
 {
   fd_callback func;
   void *data;
@@ -604,8 +616,8 @@ make_process (Lisp_Object name)
 {
   register Lisp_Object val, tem, name1;
   register struct Lisp_Process *p;
-  char suffix[10];
-  register int i;
+  char suffix[sizeof "<>" + INT_STRLEN_BOUND (printmax_t)];
+  printmax_t i;
 
   p = allocate_process ();
 
@@ -630,6 +642,9 @@ make_process (Lisp_Object name)
   p->gnutls_initstage = GNUTLS_STAGE_EMPTY;
   p->gnutls_log_level = 0;
   p->gnutls_p = 0;
+  p->gnutls_state = NULL;
+  p->gnutls_x509_cred = NULL;
+  p->gnutls_anon_cred = NULL;
 #endif
 
   /* If name is already in use, modify it until it is unused.  */
@@ -639,7 +654,7 @@ make_process (Lisp_Object name)
     {
       tem = Fget_process (name1);
       if (NILP (tem)) break;
-      sprintf (suffix, "<%d>", i);
+      sprintf (suffix, "<%"pMd">", i);
       name1 = concat2 (name, build_string (suffix));
     }
   name = name1;
@@ -891,7 +906,8 @@ not the name of the pty that Emacs uses to talk with that terminal.  */)
 
 DEFUN ("set-process-buffer", Fset_process_buffer, Sset_process_buffer,
        2, 2, 0,
-       doc: /* Set buffer associated with PROCESS to BUFFER (a buffer, or nil).  */)
+       doc: /* Set buffer associated with PROCESS to BUFFER (a buffer, or nil).
+Return BUFFER.  */)
   (register Lisp_Object process, Lisp_Object buffer)
 {
   struct Lisp_Process *p;
@@ -1083,7 +1099,7 @@ DEFUN ("process-query-on-exit-flag",
 }
 
 #ifdef DATAGRAM_SOCKETS
-Lisp_Object Fprocess_datagram_address (Lisp_Object process);
+static Lisp_Object Fprocess_datagram_address (Lisp_Object);
 #endif
 
 DEFUN ("process-contact", Fprocess_contact, Sprocess_contact,
@@ -1185,25 +1201,26 @@ Returns nil if format of ADDRESS is invalid.  */)
   if (VECTORP (address))  /* AF_INET or AF_INET6 */
     {
       register struct Lisp_Vector *p = XVECTOR (address);
+      EMACS_INT size = p->header.size;
       Lisp_Object args[10];
       int nargs, i;
 
-      if (p->size == 4 || (p->size == 5 && !NILP (omit_port)))
+      if (size == 4 || (size == 5 && !NILP (omit_port)))
        {
          args[0] = build_string ("%d.%d.%d.%d");
          nargs = 4;
        }
-      else if (p->size == 5)
+      else if (size == 5)
        {
          args[0] = build_string ("%d.%d.%d.%d:%d");
          nargs = 5;
        }
-      else if (p->size == 8 || (p->size == 9 && !NILP (omit_port)))
+      else if (size == 8 || (size == 9 && !NILP (omit_port)))
        {
          args[0] = build_string ("%x:%x:%x:%x:%x:%x:%x:%x");
          nargs = 8;
        }
-      else if (p->size == 9)
+      else if (size == 9)
        {
          args[0] = build_string ("[%x:%x:%x:%x:%x:%x:%x:%x]:%d");
          nargs = 9;
@@ -1239,244 +1256,6 @@ Returns nil if format of ADDRESS is invalid.  */)
 
   return Qnil;
 }
-\f
-static Lisp_Object
-list_processes_1 (Lisp_Object query_only)
-{
-  register Lisp_Object tail;
-  Lisp_Object proc, minspace;
-  register struct Lisp_Process *p;
-  char tembuf[300];
-  int w_proc, w_buffer, w_tty;
-  int exited = 0;
-  Lisp_Object i_status, i_buffer, i_tty, i_command;
-
-  w_proc = 4;    /* Proc   */
-  w_buffer = 6;  /* Buffer */
-  w_tty = 0;     /* Omit if no ttys */
-
-  for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
-    {
-      int i;
-
-      proc = Fcdr (XCAR (tail));
-      p = XPROCESS (proc);
-      if (NILP (p->type))
-       continue;
-      if (!NILP (query_only) && p->kill_without_query)
-       continue;
-      if (STRINGP (p->name)
-         && ( i = SCHARS (p->name), (i > w_proc)))
-       w_proc = i;
-      if (!NILP (p->buffer))
-       {
-         if (NILP (BVAR (XBUFFER (p->buffer), name)))
-           {
-             if (w_buffer < 8)
-               w_buffer = 8;  /* (Killed) */
-           }
-         else if ((i = SCHARS (BVAR (XBUFFER (p->buffer), name)), (i > w_buffer)))
-           w_buffer = i;
-       }
-      if (STRINGP (p->tty_name)
-         && (i = SCHARS (p->tty_name), (i > w_tty)))
-       w_tty = i;
-    }
-
-  XSETFASTINT (i_status, w_proc + 1);
-  XSETFASTINT (i_buffer, XFASTINT (i_status) + 9);
-  if (w_tty)
-    {
-      XSETFASTINT (i_tty, XFASTINT (i_buffer) + w_buffer + 1);
-      XSETFASTINT (i_command, XFASTINT (i_tty) + w_tty + 1);
-    }
-  else
-    {
-      i_tty = Qnil;
-      XSETFASTINT (i_command, XFASTINT (i_buffer) + w_buffer + 1);
-    }
-
-  XSETFASTINT (minspace, 1);
-
-  set_buffer_internal (XBUFFER (Vstandard_output));
-  BVAR (current_buffer, undo_list) = Qt;
-
-  BVAR (current_buffer, truncate_lines) = Qt;
-
-  write_string ("Proc", -1);
-  Findent_to (i_status, minspace); write_string ("Status", -1);
-  Findent_to (i_buffer, minspace); write_string ("Buffer", -1);
-  if (!NILP (i_tty))
-    {
-      Findent_to (i_tty, minspace); write_string ("Tty", -1);
-    }
-  Findent_to (i_command, minspace); write_string ("Command", -1);
-  write_string ("\n", -1);
-
-  write_string ("----", -1);
-  Findent_to (i_status, minspace); write_string ("------", -1);
-  Findent_to (i_buffer, minspace); write_string ("------", -1);
-  if (!NILP (i_tty))
-    {
-      Findent_to (i_tty, minspace); write_string ("---", -1);
-    }
-  Findent_to (i_command, minspace); write_string ("-------", -1);
-  write_string ("\n", -1);
-
-  for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
-    {
-      Lisp_Object symbol;
-
-      proc = Fcdr (XCAR (tail));
-      p = XPROCESS (proc);
-      if (NILP (p->type))
-       continue;
-      if (!NILP (query_only) && p->kill_without_query)
-       continue;
-
-      Finsert (1, &p->name);
-      Findent_to (i_status, minspace);
-
-      if (p->raw_status_new)
-       update_status (p);
-      symbol = p->status;
-      if (CONSP (p->status))
-       symbol = XCAR (p->status);
-
-      if (EQ (symbol, Qsignal))
-       Fprinc (symbol, Qnil);
-      else if (NETCONN1_P (p) || SERIALCONN1_P (p))
-       {
-         if (EQ (symbol, Qexit))
-           write_string ("closed", -1);
-         else if (EQ (p->command, Qt))
-           write_string ("stopped", -1);
-         else if (EQ (symbol, Qrun))
-           write_string ("open", -1);
-         else
-           Fprinc (symbol, Qnil);
-       }
-      else if (SERIALCONN1_P (p))
-       {
-         write_string ("running", -1);
-       }
-      else
-       Fprinc (symbol, Qnil);
-
-      if (EQ (symbol, Qexit))
-       {
-         Lisp_Object tem;
-         tem = Fcar (Fcdr (p->status));
-         if (XFASTINT (tem))
-           {
-             sprintf (tembuf, " %d", (int) XFASTINT (tem));
-             write_string (tembuf, -1);
-           }
-       }
-
-      if (EQ (symbol, Qsignal) || EQ (symbol, Qexit) || EQ (symbol, Qclosed))
-       exited++;
-
-      Findent_to (i_buffer, minspace);
-      if (NILP (p->buffer))
-       insert_string ("(none)");
-      else if (NILP (BVAR (XBUFFER (p->buffer), name)))
-       insert_string ("(Killed)");
-      else
-       Finsert (1, &BVAR (XBUFFER (p->buffer), name));
-
-      if (!NILP (i_tty))
-       {
-         Findent_to (i_tty, minspace);
-         if (STRINGP (p->tty_name))
-           Finsert (1, &p->tty_name);
-       }
-
-      Findent_to (i_command, minspace);
-
-      if (EQ (p->status, Qlisten))
-       {
-         Lisp_Object port = Fplist_get (p->childp, QCservice);
-         if (INTEGERP (port))
-           port = Fnumber_to_string (port);
-         if (NILP (port))
-           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) ? SSDATA (port) : "?"));
-         insert_string (tembuf);
-       }
-      else if (NETCONN1_P (p))
-       {
-         /* For a local socket, there is no host name,
-            so display service instead.  */
-         Lisp_Object host = Fplist_get (p->childp, QChost);
-         if (!STRINGP (host))
-           {
-             host = Fplist_get (p->childp, QCservice);
-             if (INTEGERP (host))
-               host = Fnumber_to_string (host);
-           }
-         if (NILP (host))
-           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) ? SSDATA (host) : "?"));
-         insert_string (tembuf);
-       }
-      else if (SERIALCONN1_P (p))
-       {
-         Lisp_Object port = Fplist_get (p->childp, QCport);
-         Lisp_Object speed = Fplist_get (p->childp, QCspeed);
-         insert_string ("(serial port ");
-         if (STRINGP (port))
-           insert_string (SSDATA (port));
-         else
-           insert_string ("?");
-         if (INTEGERP (speed))
-           {
-             sprintf (tembuf, " at %ld b/s", (long) XINT (speed));
-             insert_string (tembuf);
-           }
-         insert_string (")\n");
-       }
-      else
-       {
-         Lisp_Object tem = p->command;
-         while (1)
-           {
-             Lisp_Object tem1 = Fcar (tem);
-             if (NILP (tem1))
-               break;
-             Finsert (1, &tem1);
-             tem = Fcdr (tem);
-             if (NILP (tem))
-               break;
-             insert_string (" ");
-           }
-         insert_string ("\n");
-       }
-    }
-  if (exited)
-    {
-      status_notify (NULL);
-      redisplay_preserve_echo_area (13);
-    }
-  return Qnil;
-}
-
-DEFUN ("list-processes", Flist_processes, Slist_processes, 0, 1, "P",
-       doc: /* Display a list of all processes.
-If optional argument QUERY-ONLY is non-nil, only processes with
-the query-on-exit flag set will be listed.
-Any process listed as exited or signaled is actually eliminated
-after the listing is made.  */)
-  (Lisp_Object query_only)
-{
-  internal_with_output_to_temp_buffer ("*Process List*",
-                                      list_processes_1, query_only);
-  return Qnil;
-}
 
 DEFUN ("process-list", Fprocess_list, Sprocess_list, 0, 0, 0,
        doc: /* Return a list of all processes.  */)
@@ -1499,20 +1278,20 @@ at end of BUFFER, unless you specify an output stream or filter
 function to handle the output.  BUFFER may also be nil, meaning that
 this process is not associated with any buffer.
 
-PROGRAM is the program file name.  It is searched for in PATH.  If
-nil, just associate a pty with the buffer.  Remaining arguments are
-strings to give program as arguments.
+PROGRAM is the program file name.  It is searched for in `exec-path'
+(which see).  If nil, just associate a pty with the buffer.  Remaining
+arguments are strings to give program as arguments.
 
 If you want to separate standard output from standard error, invoke
 the command through a shell and redirect one of them using the shell
 syntax.
 
 usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
-  (size_t nargs, register Lisp_Object *args)
+  (ptrdiff_t nargs, Lisp_Object *args)
 {
   Lisp_Object buffer, name, program, proc, current_dir, tem;
   register unsigned char **new_argv;
-  register size_t i;
+  ptrdiff_t i;
   int count = SPECPDL_INDEX ();
 
   buffer = args[1];
@@ -1621,7 +1400,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
       {
        if (EQ (coding_systems, Qt))
          {
-           args2 = (Lisp_Object *) alloca ((nargs + 1) * sizeof args2);
+           args2 = (Lisp_Object *) alloca ((nargs + 1) * sizeof *args2);
            args2[0] = Qstart_process;
            for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
            GCPRO2 (proc, current_dir);
@@ -1635,7 +1414,7 @@ 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
+    /* Note: At this moment, 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
@@ -1742,8 +1521,9 @@ start_process_unwind (Lisp_Object proc)
   if (!PROCESSP (proc))
     abort ();
 
-  /* Was PROC started successfully?  */
-  if (XPROCESS (proc)->pid == -1)
+  /* Was PROC started successfully?
+     -2 is used for a pty with no process, eg for gdb.  */
+  if (XPROCESS (proc)->pid <= 0 && XPROCESS (proc)->pid != -2)
     remove_process (proc);
 
   return Qnil;
@@ -1756,7 +1536,7 @@ create_process_1 (struct atimer *timer)
 }
 
 
-void
+static void
 create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
 {
   int inchannel, outchannel;
@@ -1867,7 +1647,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
 
   XPROCESS (process)->pty_flag = pty_flag;
   XPROCESS (process)->status = Qrun;
-  setup_process_coding_systems (process);
 
   /* Delay interrupts until we have a chance to store
      the new fork's pid in its process structure */
@@ -1887,7 +1666,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
   sigaddset (&blocked, SIGHUP );  sigaction (SIGHUP , 0, &sighup_action );
 #endif
 #endif /* HAVE_WORKING_VFORK */
-  sigprocmask (SIG_BLOCK, &blocked, &procmask);
+  pthread_sigmask (SIG_BLOCK, &blocked, &procmask);
 
   FD_SET (inchannel, &input_wait_mask);
   FD_SET (inchannel, &non_keyboard_wait_mask);
@@ -1902,6 +1681,10 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
      processes to get their return values scrambled.  */
   XPROCESS (process)->pid = -1;
 
+  /* This must be called after the above line because it may signal an
+     error. */
+  setup_process_coding_systems (process);
+
   BLOCK_INPUT;
 
   {
@@ -2043,7 +1826,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
        signal (SIGPIPE, SIG_DFL);
 
        /* Stop blocking signals in the child.  */
-       sigprocmask (SIG_SETMASK, &procmask, 0);
+       pthread_sigmask (SIG_SETMASK, &procmask, 0);
 
        if (pty_flag)
          child_setup_tty (xforkout);
@@ -2135,7 +1918,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
 #endif
 #endif /* HAVE_WORKING_VFORK */
   /* Stop blocking signals in the parent.  */
-  sigprocmask (SIG_SETMASK, &procmask, 0);
+  pthread_sigmask (SIG_SETMASK, &procmask, 0);
 
   /* Now generate the error if vfork failed.  */
   if (pid < 0)
@@ -2299,13 +2082,13 @@ get_lisp_to_sockaddr_size (Lisp_Object address, int *familyp)
   if (VECTORP (address))
     {
       p = XVECTOR (address);
-      if (p->size == 5)
+      if (p->header.size == 5)
        {
          *familyp = AF_INET;
          return sizeof (struct sockaddr_in);
        }
 #ifdef AF_INET6
-      else if (p->size == 9)
+      else if (p->header.size == 9)
        {
          *familyp = AF_INET6;
          return sizeof (struct sockaddr_in6);
@@ -2324,7 +2107,7 @@ get_lisp_to_sockaddr_size (Lisp_Object address, int *familyp)
       struct sockaddr *sa;
       *familyp = XINT (XCAR (address));
       p = XVECTOR (XCDR (address));
-      return p->size + sizeof (sa->sa_family);
+      return p->header.size + sizeof (sa->sa_family);
     }
   return 0;
 }
@@ -2672,7 +2455,7 @@ Examples:
 \(serial-process-configure :port "\\\\.\\COM13" :bytesize 7)
 
 usage: (serial-process-configure &rest ARGS)  */)
-  (size_t nargs, Lisp_Object *args)
+  (ptrdiff_t nargs, Lisp_Object *args)
 {
   struct Lisp_Process *p;
   Lisp_Object contact = Qnil;
@@ -2790,7 +2573,7 @@ Examples:
 \(make-serial-process :port "/dev/tty.BlueConsole-SPP-1" :speed nil)
 
 usage:  (make-serial-process &rest ARGS)  */)
-  (size_t nargs, Lisp_Object *args)
+  (ptrdiff_t nargs, Lisp_Object *args)
 {
   int fd = -1;
   Lisp_Object proc, contact, port;
@@ -3068,7 +2851,7 @@ The original argument list, modified with the actual connection
 information, is available via the `process-contact' function.
 
 usage: (make-network-process &rest ARGS)  */)
-  (size_t nargs, Lisp_Object *args)
+  (ptrdiff_t nargs, Lisp_Object *args)
 {
   Lisp_Object proc;
   Lisp_Object contact;
@@ -3142,7 +2925,7 @@ usage: (make-network-process &rest ARGS)  */)
     {
       /* Don't support network sockets when non-blocking mode is
         not available, since a blocked Emacs is not useful.  */
-#if !defined(O_NONBLOCK) && !defined(O_NDELAY)
+#if !defined (O_NONBLOCK) && !defined (O_NDELAY)
       error ("Network servers not supported");
 #else
       is_server = 1;
@@ -3196,7 +2979,7 @@ usage: (make-network-process &rest ARGS)  */)
   tem = Fplist_get (contact, QCfamily);
   if (NILP (tem))
     {
-#if defined(HAVE_GETADDRINFO) && defined(AF_INET6)
+#if defined (HAVE_GETADDRINFO) && defined (AF_INET6)
       family = AF_UNSPEC;
 #else
       family = AF_INET;
@@ -3276,7 +3059,7 @@ usage: (make-network-process &rest ARGS)  */)
        portstring = "0";
       else if (INTEGERP (service))
        {
-         sprintf (portbuf, "%ld", (long) XINT (service));
+         sprintf (portbuf, "%"pI"d", XINT (service));
          portstring = portbuf;
        }
       else
@@ -3338,7 +3121,7 @@ usage: (make-network-process &rest ARGS)  */)
     {
       struct hostent *host_info_ptr;
 
-      /* gethostbyname may fail with TRY_AGAIN, but we don't honour that,
+      /* gethostbyname may fail with TRY_AGAIN, but we don't honor that,
         as it may `hang' Emacs for a very long time.  */
       immediate_quit = 1;
       QUIT;
@@ -3384,7 +3167,7 @@ usage: (make-network-process &rest ARGS)  */)
 
   for (lres = res; lres; lres = lres->ai_next)
     {
-      size_t optn;
+      ptrdiff_t optn;
       int optbits;
 
 #ifdef WINDOWSNT
@@ -3692,7 +3475,7 @@ usage: (make-network-process &rest ARGS)  */)
 
   {
     /* Setup coding systems for communicating with the network stream.  */
-    struct gcpro inner_gcpro1;
+    struct gcpro gcpro1;
     /* Qt denotes we have not yet called Ffind_operation_coding_system.  */
     Lisp_Object coding_systems = Qt;
     Lisp_Object fargs[5], val;
@@ -3709,7 +3492,7 @@ usage: (make-network-process &rest ARGS)  */)
             || (NILP (buffer) && NILP (BVAR (&buffer_defaults, enable_multibyte_characters))))
       /* We dare not decode end-of-line format by setting VAL to
         Qraw_text, because the existing Emacs Lisp libraries
-        assume that they receive bare code including a sequene of
+        assume that they receive bare code including a sequence of
         CR LF.  */
       val = Qnil;
     else
@@ -3720,9 +3503,9 @@ usage: (make-network-process &rest ARGS)  */)
          {
            fargs[0] = Qopen_network_stream, fargs[1] = name,
              fargs[2] = buffer, fargs[3] = host, fargs[4] = service;
-           GCPRO1_VAR (proc, inner_gcpro);
+           GCPRO1 (proc);
            coding_systems = Ffind_operation_coding_system (5, fargs);
-           UNGCPRO_VAR (inner_gcpro);
+           UNGCPRO;
          }
        if (CONSP (coding_systems))
          val = XCAR (coding_systems);
@@ -3753,9 +3536,9 @@ usage: (make-network-process &rest ARGS)  */)
              {
                fargs[0] = Qopen_network_stream, fargs[1] = name,
                  fargs[2] = buffer, fargs[3] = host, fargs[4] = service;
-               GCPRO1_VAR (proc, inner_gcpro);
+               GCPRO1 (proc);
                coding_systems = Ffind_operation_coding_system (5, fargs);
-               UNGCPRO_VAR (inner_gcpro);
+               UNGCPRO;
              }
          }
        if (CONSP (coding_systems))
@@ -3781,7 +3564,7 @@ usage: (make-network-process &rest ARGS)  */)
 }
 
 \f
-#if defined(HAVE_NET_IF_H)
+#if defined (HAVE_NET_IF_H)
 
 #ifdef SIOCGIFCONF
 DEFUN ("network-interface-list", Fnetwork_interface_list, Snetwork_interface_list, 0, 0, 0,
@@ -3792,46 +3575,53 @@ format; see the description of ADDRESS in `make-network-process'.  */)
   (void)
 {
   struct ifconf ifconf;
-  struct ifreq *ifreqs = NULL;
-  int ifaces = 0;
-  int buf_size, s;
+  struct ifreq *ifreq;
+  void *buf = NULL;
+  ptrdiff_t buf_size = 512;
+  int s, i;
   Lisp_Object res;
 
   s = socket (AF_INET, SOCK_STREAM, 0);
   if (s < 0)
     return Qnil;
 
- again:
-  ifaces += 25;
-  buf_size = ifaces * sizeof (ifreqs[0]);
-  ifreqs = (struct ifreq *)xrealloc(ifreqs, buf_size);
-  if (!ifreqs)
-    {
-      close (s);
-      return Qnil;
-    }
-
-  ifconf.ifc_len = buf_size;
-  ifconf.ifc_req = ifreqs;
-  if (ioctl (s, SIOCGIFCONF, &ifconf))
+  do
     {
-      close (s);
-      return Qnil;
+      buf = xpalloc (buf, &buf_size, 1, INT_MAX, 1);
+      ifconf.ifc_buf = buf;
+      ifconf.ifc_len = buf_size;
+      if (ioctl (s, SIOCGIFCONF, &ifconf))
+       {
+         close (s);
+         xfree (buf);
+         return Qnil;
+       }
     }
-
-  if (ifconf.ifc_len == buf_size)
-    goto again;
+  while (ifconf.ifc_len == buf_size);
 
   close (s);
-  ifaces = ifconf.ifc_len / sizeof (ifreqs[0]);
 
   res = Qnil;
-  while (--ifaces >= 0)
+  ifreq = ifconf.ifc_req;
+  while ((char *) ifreq < (char *) ifconf.ifc_req + ifconf.ifc_len)
     {
-      struct ifreq *ifq = &ifreqs[ifaces];
+      struct ifreq *ifq = ifreq;
+#ifdef HAVE_STRUCT_IFREQ_IFR_ADDR_SA_LEN
+#define SIZEOF_IFREQ(sif)                                              \
+      ((sif)->ifr_addr.sa_len < sizeof (struct sockaddr)               \
+       ? sizeof (*(sif)) : sizeof ((sif)->ifr_name) + (sif)->ifr_addr.sa_len)
+
+      int len = SIZEOF_IFREQ (ifq);
+#else
+      int len = sizeof (*ifreq);
+#endif
       char namebuf[sizeof (ifq->ifr_name) + 1];
+      i += len;
+      ifreq = (struct ifreq *) ((char *) ifreq + len);
+
       if (ifq->ifr_addr.sa_family != AF_INET)
        continue;
+
       memcpy (namebuf, ifq->ifr_name, sizeof (ifq->ifr_name));
       namebuf[sizeof (ifq->ifr_name)] = 0;
       res = Fcons (Fcons (build_string (namebuf),
@@ -3840,11 +3630,12 @@ format; see the description of ADDRESS in `make-network-process'.  */)
                   res);
     }
 
+  xfree (buf);
   return res;
 }
 #endif /* SIOCGIFCONF */
 
-#if defined(SIOCGIFADDR) || defined(SIOCGIFHWADDR) || defined(SIOCGIFFLAGS)
+#if defined (SIOCGIFADDR) || defined (SIOCGIFHWADDR) || defined (SIOCGIFFLAGS)
 
 struct ifflag_def {
   int flag_bit;
@@ -3877,8 +3668,13 @@ static const struct ifflag_def ifflag_table[] = {
   { IFF_PROMISC,       "promisc" },
 #endif
 #ifdef IFF_NOTRAILERS
+#ifdef NS_IMPL_COCOA
+  /* Really means smart, notrailers is obsolete */
+  { IFF_NOTRAILERS,    "smart" },
+#else
   { IFF_NOTRAILERS,    "notrailers" },
 #endif
+#endif
 #ifdef IFF_ALLMULTI
   { IFF_ALLMULTI,      "allmulti" },
 #endif
@@ -3922,7 +3718,7 @@ DEFUN ("network-interface-info", Fnetwork_interface_info, Snetwork_interface_inf
        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 addres, and
+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)
 {
@@ -3931,6 +3727,10 @@ FLAGS is the current flags of the interface.  */)
   Lisp_Object elt;
   int s;
   int any = 0;
+#if (! (defined SIOCGIFHWADDR && defined HAVE_STRUCT_IFREQ_IFR_HWADDR) \
+     && defined HAVE_GETIFADDRS && defined LLADDR)
+  struct ifaddrs *ifap;
+#endif
 
   CHECK_STRING (ifname);
 
@@ -3942,13 +3742,19 @@ FLAGS is the current flags of the interface.  */)
     return Qnil;
 
   elt = Qnil;
-#if defined(SIOCGIFFLAGS) && defined(HAVE_STRUCT_IFREQ_IFR_FLAGS)
+#if defined (SIOCGIFFLAGS) && defined (HAVE_STRUCT_IFREQ_IFR_FLAGS)
   if (ioctl (s, SIOCGIFFLAGS, &rq) == 0)
     {
       int flags = rq.ifr_flags;
       const struct ifflag_def *fp;
       int fnum;
 
+      /* If flags is smaller than int (i.e. short) it may have the high bit set
+         due to IFF_MULTICAST.  In that case, sign extending it into
+         an int is wrong.  */
+      if (flags < 0 && sizeof (rq.ifr_flags) < sizeof (flags))
+        flags = (unsigned short) rq.ifr_flags;
+
       any = 1;
       for (fp = ifflag_table; flags != 0 && fp->flag_sym; fp++)
        {
@@ -3958,9 +3764,9 @@ FLAGS is the current flags of the interface.  */)
              flags -= fp->flag_bit;
            }
        }
-      for (fnum = 0; flags && fnum < 32; fnum++)
+      for (fnum = 0; flags && fnum < 32; flags >>= 1, fnum++)
        {
-         if (flags & (1 << fnum))
+         if (flags & 1)
            {
              elt = Fcons (make_number (fnum), elt);
            }
@@ -3970,7 +3776,7 @@ FLAGS is the current flags of the interface.  */)
   res = Fcons (elt, res);
 
   elt = Qnil;
-#if defined(SIOCGIFHWADDR) && defined(HAVE_STRUCT_IFREQ_IFR_HWADDR)
+#if defined (SIOCGIFHWADDR) && defined (HAVE_STRUCT_IFREQ_IFR_HWADDR)
   if (ioctl (s, SIOCGIFHWADDR, &rq) == 0)
     {
       Lisp_Object hwaddr = Fmake_vector (make_number (6), Qnil);
@@ -3982,11 +3788,42 @@ FLAGS is the current flags of the interface.  */)
        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)
+  if (getifaddrs (&ifap) != -1)
+    {
+      Lisp_Object hwaddr = Fmake_vector (make_number (6), Qnil);
+      register struct Lisp_Vector *p = XVECTOR (hwaddr);
+      struct ifaddrs *it;
+
+      for (it = ifap; it != NULL; it = it->ifa_next)
+        {
+          struct sockaddr_dl *sdl = (struct sockaddr_dl*) it->ifa_addr;
+          unsigned char linkaddr[6];
+          int n;
+
+          if (it->ifa_addr->sa_family != AF_LINK
+              || strcmp (it->ifa_name, SSDATA (ifname)) != 0
+              || sdl->sdl_alen != 6)
+            continue;
+
+          memcpy (linkaddr, LLADDR (sdl), sdl->sdl_alen);
+          for (n = 0; n < 6; n++)
+            p->contents[n] = make_number (linkaddr[n]);
+
+          elt = Fcons (make_number (it->ifa_addr->sa_family), hwaddr);
+          break;
+        }
+    }
+#ifdef HAVE_FREEIFADDRS
+  freeifaddrs (ifap);
 #endif
+
+#endif /* HAVE_GETIFADDRS && LLADDR */
+
   res = Fcons (elt, res);
 
   elt = Qnil;
-#if defined(SIOCGIFNETMASK) && (defined(HAVE_STRUCT_IFREQ_IFR_NETMASK) || defined(HAVE_STRUCT_IFREQ_IFR_ADDR))
+#if defined (SIOCGIFNETMASK) && (defined (HAVE_STRUCT_IFREQ_IFR_NETMASK) || defined (HAVE_STRUCT_IFREQ_IFR_ADDR))
   if (ioctl (s, SIOCGIFNETMASK, &rq) == 0)
     {
       any = 1;
@@ -4000,7 +3837,7 @@ FLAGS is the current flags of the interface.  */)
   res = Fcons (elt, res);
 
   elt = Qnil;
-#if defined(SIOCGIFBRDADDR) && defined(HAVE_STRUCT_IFREQ_IFR_BROADADDR)
+#if defined (SIOCGIFBRDADDR) && defined (HAVE_STRUCT_IFREQ_IFR_BROADADDR)
   if (ioctl (s, SIOCGIFBRDADDR, &rq) == 0)
     {
       any = 1;
@@ -4010,7 +3847,7 @@ FLAGS is the current flags of the interface.  */)
   res = Fcons (elt, res);
 
   elt = Qnil;
-#if defined(SIOCGIFADDR) && defined(HAVE_STRUCT_IFREQ_IFR_ADDR)
+#if defined (SIOCGIFADDR) && defined (HAVE_STRUCT_IFREQ_IFR_ADDR)
   if (ioctl (s, SIOCGIFADDR, &rq) == 0)
     {
       any = 1;
@@ -4024,16 +3861,21 @@ FLAGS is the current flags of the interface.  */)
   return any ? res : Qnil;
 }
 #endif
-#endif /* defined(HAVE_NET_IF_H) */
+#endif /* defined (HAVE_NET_IF_H) */
 
 /* Turn off input and output for process PROC.  */
 
-void
+static void
 deactivate_process (Lisp_Object proc)
 {
   register int inchannel, outchannel;
   register struct Lisp_Process *p = XPROCESS (proc);
 
+#ifdef HAVE_GNUTLS
+  /* Delete GnuTLS structures in PROC, if any.  */
+  emacs_gnutls_deinit (proc);
+#endif /* HAVE_GNUTLS */
+
   inchannel  = p->infd;
   outchannel = p->outfd;
 
@@ -4398,7 +4240,7 @@ wait_reading_process_output_1 (void)
    impossible to step through wait_reading_process_output.  */
 
 #ifndef select
-static INLINE int
+static inline int
 select_wrapper (int n, fd_set *rfd, fd_set *wfd, fd_set *xfd, struct timeval *tmo)
 {
   return select (n, rfd, wfd, xfd, tmo);
@@ -4714,13 +4556,19 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
            set_waiting_for_input (&timeout);
        }
 
+      /* Skip the `select' call if input is available and we're
+        waiting for keyboard input or a cell change (which can be
+        triggered by processing X events).  In the latter case, set
+        nfds to 1 to avoid breaking the loop.  */
       no_avail = 0;
-      if (read_kbd && detect_input_pending ())
+      if ((read_kbd || !NILP (wait_for_cell))
+         && detect_input_pending ())
        {
-         nfds = 0;
+         nfds = read_kbd ? 0 : 1;
          no_avail = 1;
        }
-      else
+
+      if (!no_avail)
        {
 
 #ifdef ADAPTIVE_READ_BUFFERING
@@ -4756,7 +4604,7 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
              process_output_skip = 0;
            }
 #endif
-#if defined (USE_GTK) || defined (HAVE_GCONF)
+#if defined (USE_GTK) || defined (HAVE_GCONF) || defined (HAVE_GSETTINGS)
           nfds = xg_select
 #elif defined (HAVE_NS)
          nfds = ns_select
@@ -4767,6 +4615,53 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
              &Available,
              (check_write ? &Writeok : (SELECT_TYPE *)0),
              (SELECT_TYPE *)0, &timeout);
+
+#ifdef HAVE_GNUTLS
+          /* GnuTLS buffers data internally.  In lowat mode it leaves
+             some data in the TCP buffers so that select works, but
+             with custom pull/push functions we need to check if some
+             data is available in the buffers manually.  */
+          if (nfds == 0)
+           {
+             if (! wait_proc)
+               {
+                 /* We're not waiting on a specific process, so loop
+                    through all the channels and check for data.
+                    This is a workaround needed for some versions of
+                    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)
+                   if (! NILP (chan_process[channel]))
+                     {
+                       struct Lisp_Process *p =
+                         XPROCESS (chan_process[channel]);
+                       if (p && p->gnutls_p && p->infd
+                           && ((emacs_gnutls_record_check_pending
+                                (p->gnutls_state))
+                               > 0))
+                         {
+                           nfds++;
+                           FD_SET (p->infd, &Available);
+                         }
+                     }
+               }
+             else
+               {
+                 /* Check this specific channel. */
+                 if (wait_proc->gnutls_p /* Check for valid process.  */
+                     /* Do we have pending data?  */
+                     && ((emacs_gnutls_record_check_pending
+                          (wait_proc->gnutls_state))
+                         > 0))
+                   {
+                     nfds = 1;
+                     /* Set to Available.  */
+                     FD_SET (wait_proc->infd, &Available);
+                   }
+               }
+           }
+#endif
        }
 
       xerrno = errno;
@@ -4993,16 +4888,11 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
                 It can't hurt.  */
              else if (nread == -1 && errno == EIO)
                {
-                 /* Clear the descriptor now, so we only raise the
-                    signal once.  Don't do this if `process' is only
-                    a pty.  */
-                 if (XPROCESS (proc)->pid != -2)
-                   {
-                     FD_CLR (channel, &input_wait_mask);
-                     FD_CLR (channel, &non_keyboard_wait_mask);
+                 /* Clear the descriptor now, so we only raise the signal once.  */
+                 FD_CLR (channel, &input_wait_mask);
+                 FD_CLR (channel, &non_keyboard_wait_mask);
 
-                     kill (getpid (), SIGCHLD);
-                   }
+                 kill (getpid (), SIGCHLD);
                }
 #endif /* HAVE_PTYS */
              /* If we can detect process termination, don't consider the process
@@ -5136,7 +5026,7 @@ read_process_output_error_handler (Lisp_Object error_val)
 static int
 read_process_output (Lisp_Object proc, register int channel)
 {
-  register int nbytes;
+  register ssize_t nbytes;
   char *chars;
   register Lisp_Object outstream;
   register struct Lisp_Process *p = XPROCESS (proc);
@@ -5170,9 +5060,8 @@ read_process_output (Lisp_Object proc, register int channel)
          proc_buffered_char[channel] = -1;
        }
 #ifdef HAVE_GNUTLS
-      if (XPROCESS (proc)->gnutls_p)
-       nbytes = emacs_gnutls_read (channel, XPROCESS (proc),
-                                   chars + carryover + buffered,
+      if (p->gnutls_p)
+       nbytes = emacs_gnutls_read (p, chars + carryover + buffered,
                                    readmax - buffered);
       else
 #endif
@@ -5306,6 +5195,9 @@ read_process_output (Lisp_Object proc, register int channel)
          p->decoding_carryover = coding->carryover_bytes;
        }
       if (SBYTES (text) > 0)
+       /* FIXME: It's wrong to wrap or not based on debug-on-error, and
+          sometimes it's simply wrong to wrap (e.g. when called from
+          accept-process-output).  */
        internal_condition_case_1 (read_process_output_call,
                                   Fcons (outstream,
                                          Fcons (proc, Fcons (text, Qnil))),
@@ -5454,8 +5346,12 @@ read_process_output (Lisp_Object proc, register int channel)
 \f
 /* Sending data to subprocess */
 
-jmp_buf send_process_frame;
-Lisp_Object process_sent_to;
+static jmp_buf send_process_frame;
+static Lisp_Object process_sent_to;
+
+#ifndef FORWARD_SIGNAL_TO_MAIN_THREAD
+static void send_process_trap (int) NO_RETURN;
+#endif
 
 static void
 send_process_trap (int ignore)
@@ -5481,7 +5377,7 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
 {
   /* Use volatile to protect variables from being clobbered by longjmp.  */
   struct Lisp_Process *p = XPROCESS (proc);
-  EMACS_INT rv;
+  ssize_t rv;
   struct coding_system *coding;
   struct gcpro gcpro1;
   void (*volatile old_sigpipe) (int);
@@ -5512,8 +5408,8 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
             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
+            Another reason we come 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;
@@ -5522,6 +5418,7 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
     }
   else
     {
+      coding->src_multibyte = 0;
       /* For sending a unibyte text, character code conversion should
         not take place but EOL conversion should.  So, setup raw-text
         or one of the subsidiary if we have not yet done it.  */
@@ -5597,6 +5494,8 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
      when returning with longjmp despite being declared volatile.  */
   if (!setjmp (send_process_frame))
     {
+      p = XPROCESS (proc);  /* Repair any setjmp clobbering.  */
+
       process_sent_to = proc;
       while (len > 0)
        {
@@ -5605,6 +5504,7 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
          /* Send this batch, using one or more write calls.  */
          while (this > 0)
            {
+             EMACS_INT written = 0;
              int outfd = p->outfd;
              old_sigpipe = (void (*) (int)) signal (SIGPIPE, send_process_trap);
 #ifdef DATAGRAM_SOCKETS
@@ -5613,7 +5513,9 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
                  rv = sendto (outfd, buf, this,
                               0, datagram_address[outfd].sa,
                               datagram_address[outfd].len);
-                 if (rv < 0 && errno == EMSGSIZE)
+                 if (0 <= rv)
+                   written = rv;
+                 else if (errno == EMSGSIZE)
                    {
                      signal (SIGPIPE, old_sigpipe);
                      report_file_error ("sending datagram",
@@ -5624,13 +5526,12 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
 #endif
                {
 #ifdef HAVE_GNUTLS
-                 if (XPROCESS (proc)->gnutls_p)
-                   rv = emacs_gnutls_write (outfd,
-                                            XPROCESS (proc),
-                                            buf, this);
+                 if (p->gnutls_p)
+                   written = emacs_gnutls_write (p, buf, this);
                  else
 #endif
-                   rv = emacs_write (outfd, buf, this);
+                   written = emacs_write (outfd, buf, this);
+                 rv = (written ? 0 : -1);
 #ifdef ADAPTIVE_READ_BUFFERING
                  if (p->read_output_delay > 0
                      && p->adaptive_read_buffering == 1)
@@ -5657,7 +5558,7 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
                       that may allow the program
                       to finish doing output and read more.  */
                    {
-                     int offset = 0;
+                     EMACS_INT offset = 0;
 
 #ifdef BROKEN_PTY_READ_AFTER_EAGAIN
                      /* A gross hack to work around a bug in FreeBSD.
@@ -5703,16 +5604,14 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
                                                         offset);
                      else if (STRINGP (object))
                        buf = offset + SSDATA (object);
-
-                     rv = 0;
                    }
                  else
                    /* This is a real error.  */
                    report_file_error ("writing to process", Fcons (proc, Qnil));
                }
-             buf += rv;
-             len -= rv;
-             this -= rv;
+             buf += written;
+             len -= written;
+             this -= written;
            }
        }
     }
@@ -6806,6 +6705,8 @@ DEFUN ("process-filter-multibyte-p", Fprocess_filter_multibyte_p,
 
 \f
 
+# ifdef HAVE_GPM
+
 void
 add_gpm_wait_descriptor (int desc)
 {
@@ -6818,6 +6719,10 @@ delete_gpm_wait_descriptor (int desc)
   delete_keyboard_wait_descriptor (desc);
 }
 
+# endif
+
+# ifdef SIGIO
+
 /* Return nonzero if *MASK has a bit set
    that corresponds to one of the keyboard input descriptors.  */
 
@@ -6833,6 +6738,7 @@ keyboard_bit_set (fd_set *mask)
 
   return 0;
 }
+# endif
 
 #else  /* not subprocesses */
 
@@ -7220,8 +7126,8 @@ 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,
+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)
@@ -7408,7 +7314,7 @@ init_process (void)
 #ifdef HAVE_GETSOCKNAME
    ADD_SUBFEATURE (QCservice, Qt);
 #endif
-#if defined(O_NONBLOCK) || defined(O_NDELAY)
+#if defined (O_NONBLOCK) || defined (O_NDELAY)
    ADD_SUBFEATURE (QCserver, Qt);
 #endif
 
@@ -7423,7 +7329,9 @@ init_process (void)
      processes.  As such, we only change the default value.  */
  if (initialized)
   {
-    const char *release = get_operating_system_release ();
+    char const *release = (STRINGP (Voperating_system_release)
+                          ? SSDATA (Voperating_system_release)
+                          : 0);
     if (!release || !release[0] || (release[0] < MIN_PTY_KERNEL_VERSION
                                    && release[1] == '.')) {
       Vprocess_connection_type = Qnil;
@@ -7439,14 +7347,10 @@ syms_of_process (void)
 {
 #ifdef subprocesses
 
-  Qprocessp = intern_c_string ("processp");
-  staticpro (&Qprocessp);
-  Qrun = intern_c_string ("run");
-  staticpro (&Qrun);
-  Qstop = intern_c_string ("stop");
-  staticpro (&Qstop);
-  Qsignal = intern_c_string ("signal");
-  staticpro (&Qsignal);
+  DEFSYM (Qprocessp, "processp");
+  DEFSYM (Qrun, "run");
+  DEFSYM (Qstop, "stop");
+  DEFSYM (Qsignal, "signal");
 
   /* Qexit is already staticpro'd by syms_of_eval; don't staticpro it
      here again.
@@ -7454,92 +7358,52 @@ syms_of_process (void)
      Qexit = intern_c_string ("exit");
      staticpro (&Qexit); */
 
-  Qopen = intern_c_string ("open");
-  staticpro (&Qopen);
-  Qclosed = intern_c_string ("closed");
-  staticpro (&Qclosed);
-  Qconnect = intern_c_string ("connect");
-  staticpro (&Qconnect);
-  Qfailed = intern_c_string ("failed");
-  staticpro (&Qfailed);
-  Qlisten = intern_c_string ("listen");
-  staticpro (&Qlisten);
-  Qlocal = intern_c_string ("local");
-  staticpro (&Qlocal);
-  Qipv4 = intern_c_string ("ipv4");
-  staticpro (&Qipv4);
+  DEFSYM (Qopen, "open");
+  DEFSYM (Qclosed, "closed");
+  DEFSYM (Qconnect, "connect");
+  DEFSYM (Qfailed, "failed");
+  DEFSYM (Qlisten, "listen");
+  DEFSYM (Qlocal, "local");
+  DEFSYM (Qipv4, "ipv4");
 #ifdef AF_INET6
-  Qipv6 = intern_c_string ("ipv6");
-  staticpro (&Qipv6);
-#endif
-  Qdatagram = intern_c_string ("datagram");
-  staticpro (&Qdatagram);
-  Qseqpacket = intern_c_string ("seqpacket");
-  staticpro (&Qseqpacket);
-
-  QCport = intern_c_string (":port");
-  staticpro (&QCport);
-  QCspeed = intern_c_string (":speed");
-  staticpro (&QCspeed);
-  QCprocess = intern_c_string (":process");
-  staticpro (&QCprocess);
-
-  QCbytesize = intern_c_string (":bytesize");
-  staticpro (&QCbytesize);
-  QCstopbits = intern_c_string (":stopbits");
-  staticpro (&QCstopbits);
-  QCparity = intern_c_string (":parity");
-  staticpro (&QCparity);
-  Qodd = intern_c_string ("odd");
-  staticpro (&Qodd);
-  Qeven = intern_c_string ("even");
-  staticpro (&Qeven);
-  QCflowcontrol = intern_c_string (":flowcontrol");
-  staticpro (&QCflowcontrol);
-  Qhw = intern_c_string ("hw");
-  staticpro (&Qhw);
-  Qsw = intern_c_string ("sw");
-  staticpro (&Qsw);
-  QCsummary = intern_c_string (":summary");
-  staticpro (&QCsummary);
-
-  Qreal = intern_c_string ("real");
-  staticpro (&Qreal);
-  Qnetwork = intern_c_string ("network");
-  staticpro (&Qnetwork);
-  Qserial = intern_c_string ("serial");
-  staticpro (&Qserial);
-  QCbuffer = intern_c_string (":buffer");
-  staticpro (&QCbuffer);
-  QChost = intern_c_string (":host");
-  staticpro (&QChost);
-  QCservice = intern_c_string (":service");
-  staticpro (&QCservice);
-  QClocal = intern_c_string (":local");
-  staticpro (&QClocal);
-  QCremote = intern_c_string (":remote");
-  staticpro (&QCremote);
-  QCcoding = intern_c_string (":coding");
-  staticpro (&QCcoding);
-  QCserver = intern_c_string (":server");
-  staticpro (&QCserver);
-  QCnowait = intern_c_string (":nowait");
-  staticpro (&QCnowait);
-  QCsentinel = intern_c_string (":sentinel");
-  staticpro (&QCsentinel);
-  QClog = intern_c_string (":log");
-  staticpro (&QClog);
-  QCnoquery = intern_c_string (":noquery");
-  staticpro (&QCnoquery);
-  QCstop = intern_c_string (":stop");
-  staticpro (&QCstop);
-  QCoptions = intern_c_string (":options");
-  staticpro (&QCoptions);
-  QCplist = intern_c_string (":plist");
-  staticpro (&QCplist);
-
-  Qlast_nonmenu_event = intern_c_string ("last-nonmenu-event");
-  staticpro (&Qlast_nonmenu_event);
+  DEFSYM (Qipv6, "ipv6");
+#endif
+  DEFSYM (Qdatagram, "datagram");
+  DEFSYM (Qseqpacket, "seqpacket");
+
+  DEFSYM (QCport, ":port");
+  DEFSYM (QCspeed, ":speed");
+  DEFSYM (QCprocess, ":process");
+
+  DEFSYM (QCbytesize, ":bytesize");
+  DEFSYM (QCstopbits, ":stopbits");
+  DEFSYM (QCparity, ":parity");
+  DEFSYM (Qodd, "odd");
+  DEFSYM (Qeven, "even");
+  DEFSYM (QCflowcontrol, ":flowcontrol");
+  DEFSYM (Qhw, "hw");
+  DEFSYM (Qsw, "sw");
+  DEFSYM (QCsummary, ":summary");
+
+  DEFSYM (Qreal, "real");
+  DEFSYM (Qnetwork, "network");
+  DEFSYM (Qserial, "serial");
+  DEFSYM (QCbuffer, ":buffer");
+  DEFSYM (QChost, ":host");
+  DEFSYM (QCservice, ":service");
+  DEFSYM (QClocal, ":local");
+  DEFSYM (QCremote, ":remote");
+  DEFSYM (QCcoding, ":coding");
+  DEFSYM (QCserver, ":server");
+  DEFSYM (QCnowait, ":nowait");
+  DEFSYM (QCsentinel, ":sentinel");
+  DEFSYM (QClog, ":log");
+  DEFSYM (QCnoquery, ":noquery");
+  DEFSYM (QCstop, ":stop");
+  DEFSYM (QCoptions, ":options");
+  DEFSYM (QCplist, ":plist");
+
+  DEFSYM (Qlast_nonmenu_event, "last-nonmenu-event");
 
   staticpro (&Vprocess_alist);
 #ifdef SIGCHLD
@@ -7548,73 +7412,40 @@ syms_of_process (void)
 
 #endif /* subprocesses */
 
-  QCname = intern_c_string (":name");
-  staticpro (&QCname);
-  QCtype = intern_c_string (":type");
-  staticpro (&QCtype);
-
-  Qeuid = intern_c_string ("euid");
-  staticpro (&Qeuid);
-  Qegid = intern_c_string ("egid");
-  staticpro (&Qegid);
-  Quser = intern_c_string ("user");
-  staticpro (&Quser);
-  Qgroup = intern_c_string ("group");
-  staticpro (&Qgroup);
-  Qcomm = intern_c_string ("comm");
-  staticpro (&Qcomm);
-  Qstate = intern_c_string ("state");
-  staticpro (&Qstate);
-  Qppid = intern_c_string ("ppid");
-  staticpro (&Qppid);
-  Qpgrp = intern_c_string ("pgrp");
-  staticpro (&Qpgrp);
-  Qsess = intern_c_string ("sess");
-  staticpro (&Qsess);
-  Qttname = intern_c_string ("ttname");
-  staticpro (&Qttname);
-  Qtpgid = intern_c_string ("tpgid");
-  staticpro (&Qtpgid);
-  Qminflt = intern_c_string ("minflt");
-  staticpro (&Qminflt);
-  Qmajflt = intern_c_string ("majflt");
-  staticpro (&Qmajflt);
-  Qcminflt = intern_c_string ("cminflt");
-  staticpro (&Qcminflt);
-  Qcmajflt = intern_c_string ("cmajflt");
-  staticpro (&Qcmajflt);
-  Qutime = intern_c_string ("utime");
-  staticpro (&Qutime);
-  Qstime = intern_c_string ("stime");
-  staticpro (&Qstime);
-  Qtime = intern_c_string ("time");
-  staticpro (&Qtime);
-  Qcutime = intern_c_string ("cutime");
-  staticpro (&Qcutime);
-  Qcstime = intern_c_string ("cstime");
-  staticpro (&Qcstime);
-  Qctime = intern_c_string ("ctime");
-  staticpro (&Qctime);
-  Qpri = intern_c_string ("pri");
-  staticpro (&Qpri);
-  Qnice = intern_c_string ("nice");
-  staticpro (&Qnice);
-  Qthcount = intern_c_string ("thcount");
-  staticpro (&Qthcount);
-  Qstart = intern_c_string ("start");
-  staticpro (&Qstart);
-  Qvsize = intern_c_string ("vsize");
-  staticpro (&Qvsize);
-  Qrss = intern_c_string ("rss");
-  staticpro (&Qrss);
-  Qetime = intern_c_string ("etime");
-  staticpro (&Qetime);
-  Qpcpu = intern_c_string ("pcpu");
-  staticpro (&Qpcpu);
-  Qpmem = intern_c_string ("pmem");
-  staticpro (&Qpmem);
-  Qargs = intern_c_string ("args");
-  staticpro (&Qargs);
+  DEFSYM (QCname, ":name");
+  DEFSYM (QCtype, ":type");
+
+  DEFSYM (Qeuid, "euid");
+  DEFSYM (Qegid, "egid");
+  DEFSYM (Quser, "user");
+  DEFSYM (Qgroup, "group");
+  DEFSYM (Qcomm, "comm");
+  DEFSYM (Qstate, "state");
+  DEFSYM (Qppid, "ppid");
+  DEFSYM (Qpgrp, "pgrp");
+  DEFSYM (Qsess, "sess");
+  DEFSYM (Qttname, "ttname");
+  DEFSYM (Qtpgid, "tpgid");
+  DEFSYM (Qminflt, "minflt");
+  DEFSYM (Qmajflt, "majflt");
+  DEFSYM (Qcminflt, "cminflt");
+  DEFSYM (Qcmajflt, "cmajflt");
+  DEFSYM (Qutime, "utime");
+  DEFSYM (Qstime, "stime");
+  DEFSYM (Qtime, "time");
+  DEFSYM (Qcutime, "cutime");
+  DEFSYM (Qcstime, "cstime");
+  DEFSYM (Qctime, "ctime");
+  DEFSYM (Qpri, "pri");
+  DEFSYM (Qnice, "nice");
+  DEFSYM (Qthcount, "thcount");
+  DEFSYM (Qstart, "start");
+  DEFSYM (Qvsize, "vsize");
+  DEFSYM (Qrss, "rss");
+  DEFSYM (Qetime, "etime");
+  DEFSYM (Qpcpu, "pcpu");
+  DEFSYM (Qpmem, "pmem");
+  DEFSYM (Qargs, "args");
 
   DEFVAR_BOOL ("delete-exited-processes", delete_exited_processes,
               doc: /* *Non-nil means delete processes immediately when they exit.
@@ -7668,7 +7499,6 @@ The variable takes effect when `start-process' is called.  */);
   defsubr (&Sprocess_contact);
   defsubr (&Sprocess_plist);
   defsubr (&Sset_process_plist);
-  defsubr (&Slist_processes);
   defsubr (&Sprocess_list);
   defsubr (&Sstart_process);
   defsubr (&Sserial_process_configure);
@@ -7676,14 +7506,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)
+#if defined (HAVE_NET_IF_H)
 #ifdef SIOCGIFCONF
   defsubr (&Snetwork_interface_list);
 #endif
-#if defined(SIOCGIFADDR) || defined(SIOCGIFHWADDR) || defined(SIOCGIFFLAGS)
+#if defined (SIOCGIFADDR) || defined (SIOCGIFHWADDR) || defined (SIOCGIFFLAGS)
   defsubr (&Snetwork_interface_info);
 #endif
-#endif /* defined(HAVE_NET_IF_H) */
+#endif /* defined (HAVE_NET_IF_H) */
 #ifdef DATAGRAM_SOCKETS
   defsubr (&Sprocess_datagram_address);
   defsubr (&Sset_process_datagram_address);