]> code.delx.au - gnu-emacs/blobdiff - src/process.c
Merge from origin/emacs-25
[gnu-emacs] / src / process.c
index 4359f681b452c305b38495a4c5478edc2edbac73..9f2d379c330f8395b5628d28e8ee9934f32a9497 100644 (file)
@@ -7,8 +7,8 @@ This file is part of GNU Emacs.
 
 GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -193,16 +193,6 @@ static EMACS_INT process_tick;
 /* Number of events for which the user or sentinel has been notified.  */
 static EMACS_INT update_tick;
 
-/* Define NON_BLOCKING_CONNECT if we can support non-blocking connects.
-   The code can be simplified by assuming NON_BLOCKING_CONNECT once
-   Emacs starts assuming POSIX 1003.1-2001 or later.  */
-
-#if (defined HAVE_SELECT                               \
-     && (defined GNU_LINUX || defined HAVE_GETPEERNAME)        \
-     && (defined EWOULDBLOCK || defined EINPROGRESS))
-# define NON_BLOCKING_CONNECT
-#endif
-
 /* Define DATAGRAM_SOCKETS if datagrams can be used safely on
    this system.  We need to read full packets, so we need a
    "non-destructive" select.  So we require either native select,
@@ -262,7 +252,6 @@ static fd_set non_process_wait_mask;
 
 static fd_set write_mask;
 
-#ifdef NON_BLOCKING_CONNECT
 /* Mask of bits indicating the descriptors that we wait for connect to
    complete on.  Once they complete, they are removed from this mask
    and added to the input_wait_mask and non_keyboard_wait_mask.  */
@@ -271,7 +260,6 @@ static fd_set connect_wait_mask;
 
 /* Number of bits set in connect_wait_mask.  */
 static int num_pending_connects;
-#endif /* NON_BLOCKING_CONNECT */
 
 /* The largest descriptor currently in use for a process object; -1 if none.  */
 static int max_process_desc;
@@ -279,6 +267,12 @@ static int max_process_desc;
 /* The largest descriptor currently in use for input; -1 if none.  */
 static int max_input_desc;
 
+/* Set the external socket descriptor for Emacs to use when
+   `make-network-process' is called with a non-nil
+   `:use-external-socket' option.  The value should be either -1, or
+   the file descriptor of a socket that is already bound.  */
+static int external_sock_fd;
+
 /* Indexed by descriptor, gives the process (if any) for that descriptor.  */
 static Lisp_Object chan_process[FD_SETSIZE];
 static void wait_for_socket_fds (Lisp_Object, char const *);
@@ -687,12 +681,7 @@ allocate_process (void)
 static Lisp_Object
 make_process (Lisp_Object name)
 {
-  register Lisp_Object val, tem, name1;
-  register struct Lisp_Process *p;
-  char suffix[sizeof "<>" + INT_STRLEN_BOUND (printmax_t)];
-  printmax_t i;
-
-  p = allocate_process ();
+  struct Lisp_Process *p = allocate_process ();
   /* Initialize Lisp data.  Note that allocate_process initializes all
      Lisp data to nil, so do it only for slots which should not be nil.  */
   pset_status (p, Qrun);
@@ -702,7 +691,7 @@ make_process (Lisp_Object name)
      non-Lisp data, so do it only for slots which should not be zero.  */
   p->infd = -1;
   p->outfd = -1;
-  for (i = 0; i < PROCESS_OPEN_FDS; i++)
+  for (int i = 0; i < PROCESS_OPEN_FDS; i++)
     p->open_fd[i] = -1;
 
 #ifdef HAVE_GNUTLS
@@ -712,17 +701,22 @@ make_process (Lisp_Object name)
 
   /* If name is already in use, modify it until it is unused.  */
 
-  name1 = name;
-  for (i = 1; ; i++)
+  Lisp_Object name1 = name;
+  for (printmax_t i = 1; ; i++)
     {
-      tem = Fget_process (name1);
-      if (NILP (tem)) break;
-      name1 = concat2 (name, make_formatted_string (suffix, "<%"pMd">", i));
+      Lisp_Object tem = Fget_process (name1);
+      if (NILP (tem))
+       break;
+      char const suffix_fmt[] = "<%"pMd">";
+      char suffix[sizeof suffix_fmt + INT_STRLEN_BOUND (printmax_t)];
+      AUTO_STRING_WITH_LEN (lsuffix, suffix, sprintf (suffix, suffix_fmt, i));
+      name1 = concat2 (name, lsuffix);
     }
   name = name1;
   pset_name (p, name);
   pset_sentinel (p, Qinternal_default_process_sentinel);
   pset_filter (p, Qinternal_default_process_filter);
+  Lisp_Object val;
   XSETPROCESS (val, p);
   Vprocess_alist = Fcons (Fcons (name, val), Vprocess_alist);
   return val;
@@ -845,23 +839,19 @@ nil, indicating the current buffer's process.  */)
 #ifdef HAVE_GETADDRINFO_A
   if (p->dns_request)
     {
-      int ret;
+      /* Cancel the request.  Unless shutting down, wait until
+        completion.  Free the request if completely canceled. */
 
-      gai_cancel (p->dns_request);
-      ret = gai_error (p->dns_request);
-      if (ret == EAI_CANCELED || ret == 0)
-       free_dns_request (process);
-      else
+      bool canceled = gai_cancel (p->dns_request) != EAI_NOTCANCELED;
+      if (!canceled && !inhibit_sentinels)
        {
-         /* If we're called during shutdown, we don't really about
-            freeing all the resources.  Otherwise wait until
-            completion, and then free the request. */
-         if (! inhibit_sentinels)
-           {
-             gai_suspend ((struct gaicb const **) &p->dns_request, 1, NULL);
-             free_dns_request (process);
-           }
+         struct gaicb const *req = p->dns_request;
+         while (gai_suspend (&req, 1, NULL) != 0)
+           continue;
+         canceled = true;
        }
+      if (canceled)
+       free_dns_request (process);
     }
 #endif
 
@@ -986,7 +976,7 @@ DEFUN ("process-command", Fprocess_command, Sprocess_command, 1, 1, 0,
 This is a list of strings, the first string being the program executed
 and the rest of the strings being the arguments given to it.
 For a network or serial process, this is nil (process is running) or t
-(process is stopped).  */)
+\(process is stopped).  */)
   (register Lisp_Object process)
 {
   CHECK_PROCESS (process);
@@ -2730,7 +2720,7 @@ is not given or nil, 1 stopbit is used.
 :flowcontrol FLOWCONTROL -- FLOWCONTROL determines the type of
 flowcontrol to be used, which is either nil (don't use flowcontrol),
 the symbol `hw' (use RTS/CTS hardware flowcontrol), or the symbol `sw'
-(use XON/XOFF software flowcontrol).  If FLOWCONTROL is not given, no
+\(use XON/XOFF software flowcontrol).  If FLOWCONTROL is not given, no
 flowcontrol is used.
 
 `serial-process-configure' is called by `make-serial-process' for the
@@ -2738,12 +2728,12 @@ initial configuration of the serial port.
 
 Examples:
 
-(serial-process-configure :process "/dev/ttyS0" :speed 1200)
+\(serial-process-configure :process "/dev/ttyS0" :speed 1200)
 
-(serial-process-configure
+\(serial-process-configure
     :buffer "COM1" :stopbits 1 :parity \\='odd :flowcontrol \\='hw)
 
-(serial-process-configure :port "\\\\.\\COM13" :bytesize 7)
+\(serial-process-configure :port "\\\\.\\COM13" :bytesize 7)
 
 usage: (serial-process-configure &rest ARGS)  */)
   (ptrdiff_t nargs, Lisp_Object *args)
@@ -2837,13 +2827,13 @@ is available via the function `process-contact'.
 
 Examples:
 
-(make-serial-process :port "/dev/ttyS0" :speed 9600)
+\(make-serial-process :port "/dev/ttyS0" :speed 9600)
 
-(make-serial-process :port "COM1" :speed 115200 :stopbits 2)
+\(make-serial-process :port "COM1" :speed 115200 :stopbits 2)
 
-(make-serial-process :port "\\\\.\\COM13" :speed 1200 :bytesize 7 :parity \\='odd)
+\(make-serial-process :port "\\\\.\\COM13" :speed 1200 :bytesize 7 :parity \\='odd)
 
-(make-serial-process :port "/dev/tty.BlueConsole-SPP-1" :speed nil)
+\(make-serial-process :port "/dev/tty.BlueConsole-SPP-1" :speed nil)
 
 usage:  (make-serial-process &rest ARGS)  */)
   (ptrdiff_t nargs, Lisp_Object *args)
@@ -3091,7 +3081,8 @@ finish_after_tls_connection (Lisp_Object proc)
 #endif
 
 static void
-connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses)
+connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses,
+                        Lisp_Object use_external_socket_p)
 {
   ptrdiff_t count = SPECPDL_INDEX ();
   ptrdiff_t count1;
@@ -3105,6 +3096,15 @@ connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses)
   struct Lisp_Process *p = XPROCESS (proc);
   Lisp_Object contact = p->childp;
   int optbits = 0;
+  int socket_to_use = -1;
+
+  if (!NILP (use_external_socket_p))
+    {
+      socket_to_use = external_sock_fd;
+
+      /* Ensure we don't consume the external socket twice.  */
+      external_sock_fd = -1;
+    }
 
   /* Do this in case we never enter the while-loop below.  */
   count1 = SPECPDL_INDEX ();
@@ -3125,11 +3125,15 @@ connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses)
       sa = xmalloc (addrlen);
       conv_lisp_to_sockaddr (family, ip_address, sa, addrlen);
 
-      s = socket (family, p->socktype | SOCK_CLOEXEC, p->ai_protocol);
+      s = socket_to_use;
       if (s < 0)
        {
-         xerrno = errno;
-         continue;
+         s = socket (family, p->socktype | SOCK_CLOEXEC, p->ai_protocol);
+         if (s < 0)
+           {
+             xerrno = errno;
+             continue;
+           }
        }
 
 #ifdef DATAGRAM_SOCKETS
@@ -3137,7 +3141,6 @@ connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses)
        break;
 #endif /* DATAGRAM_SOCKETS */
 
-#ifdef NON_BLOCKING_CONNECT
       if (p->is_non_blocking_client)
        {
          ret = fcntl (s, F_SETFL, O_NONBLOCK);
@@ -3149,7 +3152,6 @@ connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses)
              continue;
            }
        }
-#endif
 
       /* Make us close S if quit.  */
       record_unwind_protect_int (close_file_unwind, s);
@@ -3186,7 +3188,8 @@ connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses)
                  report_file_error ("Cannot set reuse option on server socket", Qnil);
              }
 
-         if (bind (s, sa, addrlen))
+          /* If passed a socket descriptor, it should be already bound. */
+         if (socket_to_use < 0 && bind (s, sa, addrlen) != 0)
            report_file_error ("Cannot bind server socket", Qnil);
 
 #ifdef HAVE_GETSOCKNAME
@@ -3225,17 +3228,8 @@ connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses)
          break;
        }
 
-#ifdef NON_BLOCKING_CONNECT
-#ifdef EINPROGRESS
       if (p->is_non_blocking_client && xerrno == EINPROGRESS)
        break;
-#else
-#ifdef EWOULDBLOCK
-      if (p->is_non_blocking_client && xerrno == EWOULDBLOCK)
-       break;
-#endif
-#endif
-#endif
 
 #ifndef WINDOWSNT
       if (xerrno == EINTR)
@@ -3370,7 +3364,6 @@ connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses)
                     BUF_ZV (XBUFFER (p->buffer)),
                     BUF_ZV_BYTE (XBUFFER (p->buffer)));
 
-#ifdef NON_BLOCKING_CONNECT
   if (p->is_non_blocking_client)
     {
       /* We may get here if connect did succeed immediately.  However,
@@ -3385,7 +3378,6 @@ connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses)
        }
     }
   else
-#endif
     /* A server may have a client filter setting of Qt, but it must
        still listen for incoming connects unless it is stopped.  */
     if ((!EQ (p->filter, Qt) && !EQ (p->command, Qt))
@@ -3429,21 +3421,6 @@ connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses)
 
 }
 
-#ifndef HAVE_GETADDRINFO
-static Lisp_Object
-conv_numerical_to_lisp (unsigned char *number, int length, int port)
-{
-  Lisp_Object address = Fmake_vector (make_number (length + 1), Qnil);
-  struct Lisp_Vector *p = XVECTOR (address);
-
-  p->contents[length] = make_number (port);
-  for (int i = 0; i < length; i++)
-    p->contents[i] = make_number (number[i]);
-
-  return address;
-}
-#endif
-
 /* Create a network stream/datagram client/server process.  Treated
    exactly like a normal process when reading and writing.  Primary
    differences are in status display and process deletion.  A network
@@ -3479,9 +3456,8 @@ host, and only clients connecting to that address will be accepted.
 
 :service SERVICE -- SERVICE is name of the service desired, or an
 integer specifying a port number to connect to.  If SERVICE is t,
-a random port number is selected for the server.  (If Emacs was
-compiled with getaddrinfo, a port number can also be specified as a
-string, e.g. "80", as well as an integer.  This is not portable.)
+a random port number is selected for the server.  A port number can
+be specified as an integer string, e.g., "80", as well as an integer.
 
 :type TYPE -- TYPE is the type of connection.  The default (nil) is a
 stream type connection, `datagram' creates a datagram type connection,
@@ -3579,6 +3555,11 @@ The following network options can be specified for this connection:
                       (this is allowed by default for a server process).
 :bindtodevice NAME -- bind to interface NAME.  Using this may require
                       special privileges on some systems.
+:use-external-socket BOOL -- Use any pre-allocated sockets that have
+                             been passed to Emacs.  If Emacs wasn't
+                             passed a socket, this option is silently
+                             ignored.
+
 
 Consult the relevant system programmer's manual pages for more
 information on using these options.
@@ -3614,18 +3595,16 @@ usage: (make-network-process &rest ARGS)  */)
   Lisp_Object proc;
   Lisp_Object contact;
   struct Lisp_Process *p;
-#if defined HAVE_GETADDRINFO || defined HAVE_GETADDRINFO_A
   const char *portstring;
   ptrdiff_t portstringlen ATTRIBUTE_UNUSED;
   char portbuf[INT_BUFSIZE_BOUND (EMACS_INT)];
-#endif
 #ifdef HAVE_LOCAL_SOCKETS
   struct sockaddr_un address_un;
 #endif
   EMACS_INT port = 0;
   Lisp_Object tem;
   Lisp_Object name, buffer, host, service, address;
-  Lisp_Object filter, sentinel;
+  Lisp_Object filter, sentinel, use_external_socket_p;
   Lisp_Object ip_addresses = Qnil;
   int socktype;
   int family = -1;
@@ -3665,6 +3644,7 @@ usage: (make-network-process &rest ARGS)  */)
   buffer = Fplist_get (contact, QCbuffer);
   filter = Fplist_get (contact, QCfilter);
   sentinel = Fplist_get (contact, QCsentinel);
+  use_external_socket_p = Fplist_get (contact, QCuse_external_socket);
 
   CHECK_STRING (name);
 
@@ -3689,7 +3669,7 @@ usage: (make-network-process &rest ARGS)  */)
   tem = Fplist_get (contact, QCfamily);
   if (NILP (tem))
     {
-#if defined (HAVE_GETADDRINFO) && defined (AF_INET6)
+#ifdef AF_INET6
       family = AF_UNSPEC;
 #else
       family = AF_INET;
@@ -3761,7 +3741,6 @@ usage: (make-network-process &rest ARGS)  */)
     }
 #endif
 
-#if defined HAVE_GETADDRINFO || defined HAVE_GETADDRINFO_A
   if (!NILP (host))
     {
       /* SERVICE can either be a string or int.
@@ -3783,7 +3762,6 @@ usage: (make-network-process &rest ARGS)  */)
          portstringlen = SBYTES (service);
        }
     }
-#endif
 
 #ifdef HAVE_GETADDRINFO_A
   if (!NILP (host) && !NILP (Fplist_get (contact, QCnowait)))
@@ -3815,7 +3793,6 @@ usage: (make-network-process &rest ARGS)  */)
     }
 #endif /* HAVE_GETADDRINFO_A */
 
-#ifdef HAVE_GETADDRINFO
   /* If we have a host, use getaddrinfo to resolve both host and service.
      Otherwise, use getservbyname to lookup the service.  */
 
@@ -3835,7 +3812,14 @@ usage: (make-network-process &rest ARGS)  */)
       ret = getaddrinfo (SSDATA (host), portstring, &hints, &res);
       if (ret)
 #ifdef HAVE_GAI_STRERROR
-       error ("%s/%s %s", SSDATA (host), portstring, gai_strerror (ret));
+       {
+         synchronize_system_messages_locale ();
+         char const *str = gai_strerror (ret);
+         if (! NILP (Vlocale_coding_system))
+           str = SSDATA (code_convert_string_norecord
+                         (build_string (str), Vlocale_coding_system, 0));
+         error ("%s/%s %s", SSDATA (host), portstring, str);
+       }
 #else
        error ("%s/%s getaddrinfo error %d", SSDATA (host), portstring, ret);
 #endif
@@ -3855,10 +3839,8 @@ usage: (make-network-process &rest ARGS)  */)
 
       goto open_socket;
     }
-#endif /* HAVE_GETADDRINFO */
 
-  /* We end up here if getaddrinfo is not defined, or in case no hostname
-     has been specified (e.g. for a local server process).  */
+  /* No hostname has been specified (e.g., a local server process).  */
 
   if (EQ (service, Qt))
     port = 0;
@@ -3894,43 +3876,6 @@ usage: (make-network-process &rest ARGS)  */)
       xsignal1 (Qerror, CALLN (Fformat, unknown_service, service));
     }
 
-#ifndef HAVE_GETADDRINFO
-  if (!NILP (host))
-    {
-      struct hostent *host_info_ptr;
-      unsigned char *addr;
-      int addrlen;
-
-      /* 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;
-
-      host_info_ptr = gethostbyname ((const char *) SDATA (host));
-      immediate_quit = 0;
-
-      if (host_info_ptr)
-       {
-         addr = (unsigned char *) host_info_ptr->h_addr;
-         addrlen = host_info_ptr->h_length;
-       }
-      else
-       /* Attempt to interpret host as numeric inet address.  This
-          only works for IPv4 addresses. */
-       {
-         unsigned long numeric_addr = inet_addr (SSDATA (host));
-
-         if (numeric_addr == -1)
-           error ("Unknown host \"%s\"", SDATA (host));
-
-         addr = (unsigned char *) &numeric_addr;
-         addrlen = 4;
-       }
-
-      ip_addresses = list1 (conv_numerical_to_lisp (addr, addrlen, port));
-    }
-#endif /* not HAVE_GETADDRINFO */
-
  open_socket:
 
   if (!NILP (buffer))
@@ -3951,8 +3896,8 @@ usage: (make-network-process &rest ARGS)  */)
     pset_command (p, Qt);
   p->pid = 0;
   p->backlog = 5;
-  p->is_non_blocking_client = 0;
-  p->is_server = 0;
+  p->is_non_blocking_client = false;
+  p->is_server = false;
   p->port = port;
   p->socktype = socktype;
   p->ai_protocol = ai_protocol;
@@ -3975,38 +3920,28 @@ 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.  */
-      p->is_server = 1;
+      p->is_server = true;
       if (TYPE_RANGED_INTEGERP (int, tem))
        p->backlog = XINT (tem);
     }
 
   /* :nowait BOOL */
   if (!p->is_server && socktype != SOCK_DGRAM
-      && (tem = Fplist_get (contact, QCnowait), !NILP (tem)))
-    {
-#ifndef NON_BLOCKING_CONNECT
-      error ("Non-blocking connect not supported");
-#else
-      p->is_non_blocking_client = 1;
-#endif
-    }
+      && !NILP (Fplist_get (contact, QCnowait)))
+    p->is_non_blocking_client = true;
 
 #ifdef HAVE_GETADDRINFO_A
-  /* If we're doing async address resolution, the list of addresses
-     here will be nil, so we postpone connecting to the server. */
+  /* With async address resolution, the list of addresses is empty, so
+     postpone connecting to the server. */
   if (!p->is_server && NILP (ip_addresses))
     {
       p->dns_request = dns_request;
       p->status = Qconnect;
+      return proc;
     }
-  else
-    {
-      connect_network_socket (proc, ip_addresses);
-    }
-#else /* HAVE_GETADDRINFO_A */
-  connect_network_socket (proc, ip_addresses);
 #endif
 
+  connect_network_socket (proc, ip_addresses, use_external_socket_p);
   return proc;
 }
 
@@ -4343,19 +4278,6 @@ Data that is unavailable is returned as nil.  */)
 #endif
 }
 
-/* If program file NAME starts with /: for quoting a magic
-   name, remove that, preserving the multibyteness of NAME.  */
-
-Lisp_Object
-remove_slash_colon (Lisp_Object name)
-{
-  return
-    ((SBYTES (name) > 2 && SREF (name, 0) == '/' && SREF (name, 1) == ':')
-     ? make_specified_string (SSDATA (name) + 2, SCHARS (name) - 2,
-                             SBYTES (name) - 2, STRING_MULTIBYTE (name))
-     : name);
-}
-
 /* Turn off input and output for process PROC.  */
 
 static void
@@ -4399,7 +4321,6 @@ deactivate_process (Lisp_Object proc)
       chan_process[inchannel] = Qnil;
       FD_CLR (inchannel, &input_wait_mask);
       FD_CLR (inchannel, &non_keyboard_wait_mask);
-#ifdef NON_BLOCKING_CONNECT
       if (FD_ISSET (inchannel, &connect_wait_mask))
        {
          FD_CLR (inchannel, &connect_wait_mask);
@@ -4407,7 +4328,6 @@ deactivate_process (Lisp_Object proc)
          if (--num_pending_connects < 0)
            emacs_abort ();
        }
-#endif
       if (inchannel == max_process_desc)
        {
          /* We just closed the highest-numbered process input descriptor,
@@ -4717,13 +4637,12 @@ check_for_dns (Lisp_Object proc)
 {
   struct Lisp_Process *p = XPROCESS (proc);
   Lisp_Object ip_addresses = Qnil;
-  int ret = 0;
 
   /* Sanity check. */
   if (! p->dns_request)
     return Qnil;
 
-  ret = gai_error (p->dns_request);
+  int ret = gai_error (p->dns_request);
   if (ret == EAI_INPROGRESS)
     return Qt;
 
@@ -4943,7 +4862,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
                  {
                    Lisp_Object ip_addresses = check_for_dns (aproc);
                    if (!NILP (ip_addresses) && !EQ (ip_addresses, Qt))
-                     connect_network_socket (aproc, ip_addresses);
+                     connect_network_socket (aproc, ip_addresses, Qnil);
                    else
                      retry_for_async = true;
                  }
@@ -5061,11 +4980,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
          timeout = make_timespec (0, 0);
          if ((pselect (max (max_process_desc, max_input_desc) + 1,
                        &Atemp,
-#ifdef NON_BLOCKING_CONNECT
                        (num_pending_connects > 0 ? &Ctemp : NULL),
-#else
-                       NULL,
-#endif
                        NULL, &timeout, NULL)
               <= 0))
            {
@@ -5557,7 +5472,6 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
                                 list2 (Qexit, make_number (256)));
                }
            }
-#ifdef NON_BLOCKING_CONNECT
          if (FD_ISSET (channel, &Writeok)
              && FD_ISSET (channel, &connect_wait_mask))
            {
@@ -5609,7 +5523,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
                {
 #ifdef HAVE_GNUTLS
                  /* If we have an incompletely set up TLS connection,
-                    then defer the sentinel signalling until
+                    then defer the sentinel signaling until
                     later. */
                  if (NILP (p->gnutls_boot_parameters)
                      && !p->gnutls_p)
@@ -5630,7 +5544,6 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
                    }
                }
            }
-#endif /* NON_BLOCKING_CONNECT */
        }                       /* End for each file descriptor.  */
     }                          /* End while exit conditions not met.  */
 
@@ -6464,7 +6377,7 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group,
          break;
 
        case SIGTSTP:
-#if defined (VSWTCH) && !defined (PREFER_VSUSP)
+#ifdef VSWTCH
          sig_char = &t.c_cc[VSWTCH];
 #else
          sig_char = &t.c_cc[VSUSP];
@@ -7557,6 +7470,19 @@ add_timer_wait_descriptor (int fd)
 
 #endif /* HAVE_TIMERFD */
 
+/* If program file NAME starts with /: for quoting a magic
+   name, remove that, preserving the multibyteness of NAME.  */
+
+Lisp_Object
+remove_slash_colon (Lisp_Object name)
+{
+  return
+    ((SBYTES (name) > 2 && SREF (name, 0) == '/' && SREF (name, 1) == ':')
+     ? make_specified_string (SSDATA (name) + 2, SCHARS (name) - 2,
+                             SBYTES (name) - 2, STRING_MULTIBYTE (name))
+     : name);
+}
+
 /* Add DESC to the set of keyboard input descriptors.  */
 
 void
@@ -7814,10 +7740,10 @@ catch_child_signal (void)
 /* This is not called "init_process" because that is the name of a
    Mach system call, so it would cause problems on Darwin systems.  */
 void
-init_process_emacs (void)
+init_process_emacs (int sockfd)
 {
 #ifdef subprocesses
-  register int i;
+  int i;
 
   inhibit_sentinels = 0;
 
@@ -7840,12 +7766,11 @@ init_process_emacs (void)
   FD_ZERO (&non_process_wait_mask);
   FD_ZERO (&write_mask);
   max_process_desc = max_input_desc = -1;
+  external_sock_fd = sockfd;
   memset (fd_callback_info, 0, sizeof (fd_callback_info));
 
-#ifdef NON_BLOCKING_CONNECT
   FD_ZERO (&connect_wait_mask);
   num_pending_connects = 0;
-#endif
 
   process_output_delay_count = 0;
   process_output_skip = 0;
@@ -7940,6 +7865,7 @@ syms_of_process (void)
   DEFSYM (QCserver, ":server");
   DEFSYM (QCnowait, ":nowait");
   DEFSYM (QCsentinel, ":sentinel");
+  DEFSYM (QCuse_external_socket, ":use-external-socket");
   DEFSYM (QCtls_parameters, ":tls-parameters");
   DEFSYM (Qnsm_verify_connection, "nsm-verify-connection");
   DEFSYM (QClog, ":log");
@@ -8084,13 +8010,6 @@ The variable takes effect when `start-process' is called.  */);
   defsubr (&Sset_process_filter_multibyte);
   defsubr (&Sprocess_filter_multibyte_p);
 
-#endif /* subprocesses */
-
-  defsubr (&Sget_buffer_process);
-  defsubr (&Sprocess_inherit_coding_system_flag);
-  defsubr (&Slist_system_processes);
-  defsubr (&Sprocess_attributes);
-
  {
    Lisp_Object subfeatures = Qnil;
    const struct socket_options *sopt;
@@ -8098,9 +8017,7 @@ The variable takes effect when `start-process' is called.  */);
 #define ADD_SUBFEATURE(key, val) \
   subfeatures = pure_cons (pure_cons (key, pure_cons (val, Qnil)), subfeatures)
 
-#ifdef NON_BLOCKING_CONNECT
    ADD_SUBFEATURE (QCnowait, Qt);
-#endif
 #ifdef DATAGRAM_SOCKETS
    ADD_SUBFEATURE (QCtype, Qdatagram);
 #endif
@@ -8125,4 +8042,10 @@ The variable takes effect when `start-process' is called.  */);
    Fprovide (intern_c_string ("make-network-process"), subfeatures);
  }
 
+#endif /* subprocesses */
+
+  defsubr (&Sget_buffer_process);
+  defsubr (&Sprocess_inherit_coding_system_flag);
+  defsubr (&Slist_system_processes);
+  defsubr (&Sprocess_attributes);
 }