]> code.delx.au - gnu-emacs/blobdiff - src/process.c
merge from trunk
[gnu-emacs] / src / process.c
index 1eefae1adc910421fb270425a58b8e8dea261c0c..4a6586230775bac62d5fac2367071611f0ab44a4 100644 (file)
@@ -21,17 +21,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include <signal.h>
-
-/* This file is split into two parts by the following preprocessor
-   conditional.  The 'then' clause contains all of the support for
-   asynchronous subprocesses.  The 'else' clause contains stub
-   versions of some of the asynchronous subprocess routines that are
-   often called elsewhere in Emacs, so we don't have to #ifdef the
-   sections that call them.  */
-
-\f
-#ifdef subprocesses
-
 #include <stdio.h>
 #include <errno.h>
 #include <setjmp.h>
@@ -51,7 +40,9 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #endif
 #include <fcntl.h>
 
-#ifdef HAVE_SOCKETS    /* TCP connection support, if kernel can do it */
+/* Only MS-DOS does not define `subprocesses'.  */
+#ifdef subprocesses
+
 #include <sys/socket.h>
 #include <netdb.h>
 #include <netinet/in.h>
@@ -67,30 +58,21 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <sys/un.h>
 #endif
 #endif
-#endif /* HAVE_SOCKETS */
 
 #if defined(HAVE_SYS_IOCTL_H)
 #include <sys/ioctl.h>
 #if !defined (O_NDELAY) && defined (HAVE_PTYS) && !defined(USG5)
 #include <fcntl.h>
 #endif /* HAVE_PTYS and no O_NDELAY */
+#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
 
-/* Can we use SIOCGIFCONF and/or SIOCGIFADDR */
-#ifdef HAVE_SOCKETS
-#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H)
-/* sys/ioctl.h may have been included already */
-#ifndef SIOCGIFADDR
-#include <sys/ioctl.h>
-#endif
-#include <net/if.h>
-#endif
-#endif
-
 #ifdef HAVE_SYS_WAIT
 #include <sys/wait.h>
 #endif
@@ -101,6 +83,12 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <resolv.h>
 #endif
 
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+
+#endif /* subprocesses */
+
 #include "lisp.h"
 #include "systime.h"
 #include "systty.h"
@@ -119,10 +107,36 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "dispextern.h"
 #include "composite.h"
 #include "atimer.h"
+#include "sysselect.h"
+#include "syssignal.h"
+#include "syswait.h"
 
 #if defined (USE_GTK) || defined (HAVE_GCONF)
 #include "xgselect.h"
 #endif /* defined (USE_GTK) || defined (HAVE_GCONF) */
+#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;
+Lisp_Object Qcutime, Qpri, Qnice, Qthcount, Qstart, Qvsize, Qrss, Qargs;
+Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem, Qtime, Qctime;
+Lisp_Object QCname, QCtype;
+\f
+/* Non-zero if keyboard input is on hold, zero otherwise.  */
+
+static int kbd_is_on_hold;
+
+/* Nonzero means delete a process right away if it exits.  */
+static int delete_exited_processes;
+
+/* Nonzero means don't run process sentinels.  This is used
+   when exiting.  */
+int inhibit_sentinels;
+
+#ifdef subprocesses
 
 Lisp_Object Qprocessp;
 Lisp_Object Qrun, Qstop, Qsignal;
@@ -135,7 +149,7 @@ Lisp_Object Qipv6;
 Lisp_Object QCport, QCspeed, QCprocess;
 Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven;
 Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary;
-Lisp_Object QCname, QCbuffer, QChost, QCservice, QCtype;
+Lisp_Object QCbuffer, QChost, QCservice;
 Lisp_Object QClocal, QCremote, QCcoding;
 Lisp_Object QCserver, QCnowait, QCnoquery, QCstop;
 Lisp_Object QCsentinel, QClog, QCoptions, QCplist;
@@ -151,22 +165,10 @@ extern Lisp_Object QCfamily;
 /* QCfilter is defined in keyboard.c.  */
 extern Lisp_Object QCfilter;
 
-Lisp_Object Qeuid, Qegid, Qcomm, Qstate, Qppid, Qpgrp, Qsess, Qttname, Qtpgid;
-Lisp_Object Qminflt, Qmajflt, Qcminflt, Qcmajflt, Qutime, Qstime, Qcstime;
-Lisp_Object Qcutime, Qpri, Qnice, Qthcount, Qstart, Qvsize, Qrss, Qargs;
-Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem, Qtime, Qctime;
-
-#ifdef HAVE_SOCKETS
 #define NETCONN_P(p) (EQ (XPROCESS (p)->type, Qnetwork))
 #define NETCONN1_P(p) (EQ ((p)->type, Qnetwork))
 #define SERIALCONN_P(p) (EQ (XPROCESS (p)->type, Qserial))
 #define SERIALCONN1_P(p) (EQ ((p)->type, Qserial))
-#else
-#define NETCONN_P(p) 0
-#define NETCONN1_P(p) 0
-#define SERIALCONN_P(p) 0
-#define SERIALCONN1_P(p) 0
-#endif /* HAVE_SOCKETS */
 
 /* Define first descriptor number available for subprocesses.  */
 #define FIRST_PROC_DESC 3
@@ -178,11 +180,7 @@ Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem, Qtime, Qctime;
 #define SIGCHLD SIGCLD
 #endif /* SIGCLD */
 
-#include "syssignal.h"
-
-#include "syswait.h"
-
-extern char *get_operating_system_release (void);
+extern const char *get_operating_system_release (void);
 
 /* Serial processes require termios or Windows.  */
 #if defined (HAVE_TERMIOS) || defined (WINDOWSNT)
@@ -216,7 +214,6 @@ int update_tick;
 #undef NON_BLOCKING_CONNECT
 #else
 #ifndef NON_BLOCKING_CONNECT
-#ifdef HAVE_SOCKETS
 #ifdef HAVE_SELECT
 #if defined (HAVE_GETPEERNAME) || defined (GNU_LINUX)
 #if defined (O_NONBLOCK) || defined (O_NDELAY)
@@ -226,7 +223,6 @@ int update_tick;
 #endif /* O_NONBLOCK || O_NDELAY */
 #endif /* HAVE_GETPEERNAME || GNU_LINUX */
 #endif /* HAVE_SELECT */
-#endif /* HAVE_SOCKETS */
 #endif /* NON_BLOCKING_CONNECT */
 #endif /* BROKEN_NON_BLOCKING_CONNECT */
 
@@ -239,13 +235,11 @@ int update_tick;
 #undef DATAGRAM_SOCKETS
 #else
 #ifndef DATAGRAM_SOCKETS
-#ifdef HAVE_SOCKETS
 #if defined (HAVE_SELECT) || defined (FIONREAD)
 #if defined (HAVE_SENDTO) && defined (HAVE_RECVFROM) && defined (EMSGSIZE)
 #define DATAGRAM_SOCKETS
 #endif /* HAVE_SENDTO && HAVE_RECVFROM && EMSGSIZE */
 #endif /* HAVE_SELECT || FIONREAD */
-#endif /* HAVE_SOCKETS */
 #endif /* DATAGRAM_SOCKETS */
 #endif /* BROKEN_DATAGRAM_SOCKETS */
 
@@ -282,9 +276,6 @@ static Lisp_Object Vprocess_adaptive_read_buffering;
 #define process_output_delay_count 0
 #endif
 
-
-#include "sysselect.h"
-
 static int keyboard_bit_set (SELECT_TYPE *);
 static void deactivate_process (Lisp_Object);
 static void status_notify (struct Lisp_Process *);
@@ -300,16 +291,10 @@ static void create_pty (Lisp_Object);
 static Lisp_Object get_process (register Lisp_Object name);
 static void exec_sentinel (Lisp_Object proc, Lisp_Object reason);
 
-extern int timers_run;
-\f
 /* Mask of bits indicating the descriptors that we wait for input on.  */
 
 static SELECT_TYPE input_wait_mask;
 
-/* Non-zero if keyboard input is on hold, zero otherwise.  */
-
-static int kbd_is_on_hold;
-
 /* Mask that excludes keyboard input descriptor(s).  */
 
 static SELECT_TYPE non_keyboard_wait_mask;
@@ -333,9 +318,9 @@ static SELECT_TYPE connect_wait_mask;
 static int num_pending_connects;
 
 #define IF_NON_BLOCKING_CONNECT(s) s
-#else
+#else  /* NON_BLOCKING_CONNECT */
 #define IF_NON_BLOCKING_CONNECT(s)
-#endif
+#endif /* NON_BLOCKING_CONNECT */
 
 /* The largest descriptor currently in use for a process object.  */
 static int max_process_desc;
@@ -346,9 +331,6 @@ static int max_keyboard_desc;
 /* The largest descriptor currently in use for gpm mouse input.  */
 static int max_gpm_desc;
 
-/* Nonzero means delete a process right away if it exits.  */
-static int delete_exited_processes;
-
 /* Indexed by descriptor, gives the process (if any) for that descriptor */
 Lisp_Object chan_process[MAXDESC];
 
@@ -384,10 +366,6 @@ struct sockaddr_and_len {
 /* Maximum number of bytes to send to a pty without an eof.  */
 static int pty_max_bytes;
 
-/* Nonzero means don't run process sentinels.  This is used
-   when exiting.  */
-int inhibit_sentinels;
-
 #ifdef HAVE_PTYS
 #ifdef HAVE_PTY_H
 #include <pty.h>
@@ -645,38 +623,6 @@ remove_process (register Lisp_Object proc)
   deactivate_process (proc);
 }
 
-/* Setup coding systems of PROCESS.  */
-
-void
-setup_process_coding_systems (Lisp_Object process)
-{
-  struct Lisp_Process *p = XPROCESS (process);
-  int inch = p->infd;
-  int outch = p->outfd;
-  Lisp_Object coding_system;
-
-  if (inch < 0 || outch < 0)
-    return;
-
-  if (!proc_decode_coding_system[inch])
-    proc_decode_coding_system[inch]
-      = (struct coding_system *) xmalloc (sizeof (struct coding_system));
-  coding_system = p->decode_coding_system;
-  if (! NILP (p->filter))
-    ;
-  else if (BUFFERP (p->buffer))
-    {
-      if (NILP (XBUFFER (p->buffer)->enable_multibyte_characters))
-       coding_system = raw_text_coding_system (coding_system);
-    }
-  setup_coding_system (coding_system, proc_decode_coding_system[inch]);
-
-  if (!proc_encode_coding_system[outch])
-    proc_encode_coding_system[outch]
-      = (struct coding_system *) xmalloc (sizeof (struct coding_system));
-  setup_coding_system (p->encode_coding_system,
-                      proc_encode_coding_system[outch]);
-}
 \f
 DEFUN ("processp", Fprocessp, Sprocessp, 1, 1, 0,
        doc: /* Return t if OBJECT is a process.  */)
@@ -695,26 +641,6 @@ DEFUN ("get-process", Fget_process, Sget_process, 1, 1, 0,
   return Fcdr (Fassoc (name, Vprocess_alist));
 }
 
-DEFUN ("get-buffer-process", Fget_buffer_process, Sget_buffer_process, 1, 1, 0,
-       doc: /* Return the (or a) process associated with BUFFER.
-BUFFER may be a buffer or the name of one.  */)
-  (register Lisp_Object buffer)
-{
-  register Lisp_Object buf, tail, proc;
-
-  if (NILP (buffer)) return Qnil;
-  buf = Fget_buffer (buffer);
-  if (NILP (buf)) return Qnil;
-
-  for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
-    {
-      proc = Fcdr (XCAR (tail));
-      if (PROCESSP (proc) && EQ (XPROCESS (proc)->buffer, buf))
-       return proc;
-    }
-  return Qnil;
-}
-
 /* This is how commands for the user decode process arguments.  It
    accepts a process, a process name, a buffer, a buffer name, or nil.
    Buffers denote the first process in the buffer, and nil denotes the
@@ -1096,19 +1022,6 @@ for the process which will run.  */)
   return flag;
 }
 
-DEFUN ("process-inherit-coding-system-flag",
-       Fprocess_inherit_coding_system_flag, Sprocess_inherit_coding_system_flag,
-       1, 1, 0,
-       doc: /* Return the value of inherit-coding-system flag for PROCESS.
-If this flag is t, `buffer-file-coding-system' of the buffer
-associated with PROCESS will inherit the coding system used to decode
-the process output.  */)
-  (register Lisp_Object process)
-{
-  CHECK_PROCESS (process);
-  return XPROCESS (process)->inherit_coding_system_flag ? Qt : Qnil;
-}
-
 DEFUN ("set-process-query-on-exit-flag",
        Fset_process_query_on_exit_flag, Sset_process_query_on_exit_flag,
        2, 2, 0,
@@ -1216,7 +1129,6 @@ nil, indicating the current buffer's process.  */)
   return XPROCESS (proc)->type;
 }
 
-#ifdef HAVE_SOCKETS
 DEFUN ("format-network-address", Fformat_network_address, Sformat_network_address,
        1, 2, 0,
        doc: /* Convert network ADDRESS from internal format to a string.
@@ -1290,7 +1202,6 @@ Returns nil if format of ADDRESS is invalid.  */)
 
   return Qnil;
 }
-#endif
 \f
 static Lisp_Object
 list_processes_1 (Lisp_Object query_only)
@@ -1795,25 +1706,6 @@ create_process_1 (struct atimer *timer)
 }
 
 
-#if 0  /* This doesn't work; see the note before sigchld_handler.  */
-#ifdef USG
-#ifdef SIGCHLD
-/* Mimic blocking of signals on system V, which doesn't really have it.  */
-
-/* Nonzero means we got a SIGCHLD when it was supposed to be blocked.  */
-int sigchld_deferred;
-
-SIGTYPE
-create_process_sigchld ()
-{
-  signal (SIGCHLD, create_process_sigchld);
-
-  sigchld_deferred = 1;
-}
-#endif
-#endif
-#endif
-
 void
 create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
 {
@@ -2283,8 +2175,6 @@ create_pty (Lisp_Object process)
 }
 
 \f
-#ifdef HAVE_SOCKETS
-
 /* Convert an internal struct sockaddr to a lisp object (vector or string).
    The address family of sa is not included in the result.  */
 
@@ -2299,7 +2189,7 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, int len)
   /* Workaround for a bug in getsockname on BSD: Names bound to
      sockets in the UNIX domain are inaccessible; getsockname returns
      a zero length name.  */
-  if (len < OFFSETOF (struct sockaddr, sa_family) + sizeof (sa->sa_family))
+  if (len < offsetof (struct sockaddr, sa_family) + sizeof (sa->sa_family))
     return empty_unibyte_string;
 
   switch (sa->sa_family)
@@ -2339,7 +2229,7 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, int len)
       }
 #endif
     default:
-      len -= OFFSETOF (struct sockaddr, sa_family) + sizeof (sa->sa_family);
+      len -= offsetof (struct sockaddr, sa_family) + sizeof (sa->sa_family);
       address = Fcons (make_number (sa->sa_family),
                       Fmake_vector (make_number (len), Qnil));
       p = XVECTOR (XCDR (address));
@@ -2515,7 +2405,7 @@ Returns nil upon error setting address, ADDRESS otherwise.  */)
 static const struct socket_options {
   /* The name of this option.  Should be lowercase version of option
      name without SO_ prefix. */
-  char *name;
+  const char *name;
   /* Option level SOL_... */
   int optlevel;
   /* Option number SO_... */
@@ -3143,7 +3033,8 @@ usage: (make-network-process &rest ARGS)  */)
 #ifdef HAVE_GETADDRINFO
   struct addrinfo ai, *res, *lres;
   struct addrinfo hints;
-  char *portstring, portbuf[128];
+  const char *portstring;
+  char portbuf[128];
 #else /* HAVE_GETADDRINFO */
   struct _emacs_addrinfo
   {
@@ -3838,10 +3729,9 @@ usage: (make-network-process &rest ARGS)  */)
   UNGCPRO;
   return proc;
 }
-#endif /* HAVE_SOCKETS */
 
 \f
-#if defined(HAVE_SOCKETS) && defined(HAVE_NET_IF_H) && defined(HAVE_SYS_IOCTL_H)
+#if defined(HAVE_NET_IF_H) && defined(HAVE_SYS_IOCTL_H)
 
 #ifdef SIOCGIFCONF
 DEFUN ("network-interface-list", Fnetwork_interface_list, Snetwork_interface_list, 0, 0, 0,
@@ -4084,7 +3974,7 @@ FLAGS is the current flags of the interface.  */)
   return any ? res : Qnil;
 }
 #endif
-#endif /* HAVE_SOCKETS */
+#endif /* defined(HAVE_NET_IF_H) && defined(HAVE_SYS_IOCTL_H) */
 
 /* Turn off input and output for process PROC.  */
 
@@ -4149,31 +4039,6 @@ deactivate_process (Lisp_Object proc)
     }
 }
 
-/* Close all descriptors currently in use for communication
-   with subprocess.  This is used in a newly-forked subprocess
-   to get rid of irrelevant descriptors.  */
-
-void
-close_process_descs (void)
-{
-#ifndef WINDOWSNT
-  int i;
-  for (i = 0; i < MAXDESC; i++)
-    {
-      Lisp_Object process;
-      process = chan_process[i];
-      if (!NILP (process))
-       {
-         int in  = XPROCESS (process)->infd;
-         int out = XPROCESS (process)->outfd;
-         if (in >= 0)
-           emacs_close (in);
-         if (out >= 0 && in != out)
-           emacs_close (out);
-       }
-    }
-#endif
-}
 \f
 DEFUN ("accept-process-output", Faccept_process_output, Saccept_process_output,
        0, 4, 0,
@@ -4528,12 +4393,10 @@ select_wrapper (int n, fd_set *rfd, fd_set *wfd, fd_set *xfd, struct timeval *tm
    Otherwise, return true if we received input from any process.  */
 
 int
-wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
-                            wait_for_cell, wait_proc, just_wait_proc)
-     int time_limit, microsecs, read_kbd, do_display;
-     Lisp_Object wait_for_cell;
-     struct Lisp_Process *wait_proc;
-     int just_wait_proc;
+wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
+                            int do_display,
+                            Lisp_Object wait_for_cell,
+                            struct Lisp_Process *wait_proc, int just_wait_proc)
 {
   register int channel, nfds;
   SELECT_TYPE Available;
@@ -5528,15 +5391,6 @@ read_process_output (Lisp_Object proc, register int channel)
   unbind_to (count, Qnil);
   return nbytes;
 }
-
-DEFUN ("waiting-for-user-input-p", Fwaiting_for_user_input_p, Swaiting_for_user_input_p,
-       0, 0, 0,
-       doc: /* Returns non-nil if Emacs is waiting for input from the user.
-This is intended for use by asynchronous process output filters and sentinels.  */)
-  (void)
-{
-  return (waiting_for_user_input_p ? Qt : Qnil);
-}
 \f
 /* Sending data to subprocess */
 
@@ -5562,7 +5416,7 @@ send_process_trap (int ignore)
    This function can evaluate Lisp code and can garbage collect.  */
 
 static void
-send_process (volatile Lisp_Object proc, unsigned char *volatile buf,
+send_process (volatile Lisp_Object proc, const unsigned char *volatile buf,
              volatile int len, volatile Lisp_Object object)
 {
   /* Use volatile to protect variables from being clobbered by longjmp.  */
@@ -6168,7 +6022,6 @@ If PROCESS is a network or serial process, inhibit handling of incoming
 traffic.  */)
   (Lisp_Object process, Lisp_Object current_group)
 {
-#ifdef HAVE_SOCKETS
   if (PROCESSP (process) && (NETCONN_P (process) || SERIALCONN_P (process)))
     {
       struct Lisp_Process *p;
@@ -6183,7 +6036,6 @@ traffic.  */)
       p->command = Qt;
       return process;
     }
-#endif
 #ifndef SIGTSTP
   error ("No SIGTSTP support");
 #else
@@ -6199,7 +6051,6 @@ If PROCESS is a network or serial process, resume handling of incoming
 traffic.  */)
   (Lisp_Object process, Lisp_Object current_group)
 {
-#ifdef HAVE_SOCKETS
   if (PROCESSP (process) && (NETCONN_P (process) || SERIALCONN_P (process)))
     {
       struct Lisp_Process *p;
@@ -6222,7 +6073,6 @@ traffic.  */)
       p->command = Qnil;
       return process;
     }
-#endif
 #ifdef SIGCONT
     process_send_signal (process, SIGCONT, current_group, 0);
 #else
@@ -6474,28 +6324,6 @@ process has been transmitted to the serial port.  */)
     }
   return process;
 }
-
-/* Kill all processes associated with `buffer'.
-   If `buffer' is nil, kill all processes  */
-
-void
-kill_buffer_processes (Lisp_Object buffer)
-{
-  Lisp_Object tail, proc;
-
-  for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
-    {
-      proc = XCDR (XCAR (tail));
-      if (PROCESSP (proc)
-         && (NILP (buffer) || EQ (XPROCESS (proc)->buffer, buffer)))
-       {
-         if (NETCONN_P (proc) || SERIALCONN_P (proc))
-           Fdelete_process (proc);
-         else if (XPROCESS (proc)->infd >= 0)
-           process_send_signal (proc, SIGHUP, Qnil, 1);
-       }
-    }
-}
 \f
 /* On receipt of a signal that a child status has changed, loop asking
    about children with changed statuses until the system says there
@@ -6528,8 +6356,7 @@ sigchld_handler (int signo)
 {
   int old_errno = errno;
   Lisp_Object proc;
-  register struct Lisp_Process *p;
-  extern EMACS_TIME *input_available_clear_time;
+  struct Lisp_Process *p;
 
   SIGNAL_THREAD_CHECK (signo);
 
@@ -6960,40 +6787,6 @@ DEFUN ("process-filter-multibyte-p", Fprocess_filter_multibyte_p,
 
 
 \f
-/* Stop reading input from keyboard sources.  */
-
-void
-hold_keyboard_input (void)
-{
-  kbd_is_on_hold = 1;
-}
-
-/* Resume reading input from keyboard sources.  */
-
-void
-unhold_keyboard_input (void)
-{
-  kbd_is_on_hold = 0;
-}
-
-/* Return non-zero if keyboard input is on hold, zero otherwise.  */
-
-int
-kbd_on_hold_p (void)
-{
-  return kbd_is_on_hold;
-}
-
-/* Add DESC to the set of keyboard input descriptors.  */
-
-void
-add_keyboard_wait_descriptor (int desc)
-{
-  FD_SET (desc, &input_wait_mask);
-  FD_SET (desc, &non_process_wait_mask);
-  if (desc > max_keyboard_desc)
-    max_keyboard_desc = desc;
-}
 
 static int add_gpm_wait_descriptor_called_flag;
 
@@ -7009,542 +6802,47 @@ add_gpm_wait_descriptor (int desc)
     max_gpm_desc = desc;
 }
 
-/* From now on, do not expect DESC to give keyboard input.  */
-
 void
-delete_keyboard_wait_descriptor (int desc)
+delete_gpm_wait_descriptor (int desc)
 {
   int fd;
-  int lim = max_keyboard_desc;
+  int lim = max_gpm_desc;
 
   FD_CLR (desc, &input_wait_mask);
   FD_CLR (desc, &non_process_wait_mask);
 
-  if (desc == max_keyboard_desc)
+  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, &gpm_wait_mask))
-       max_keyboard_desc = fd;
+         && !FD_ISSET (fd, &non_process_wait_mask))
+       max_gpm_desc = fd;
 }
 
-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;
-}
-
-/* Return nonzero if *MASK has a bit set
-   that corresponds to one of the keyboard input descriptors.  */
-
-static int
-keyboard_bit_set (fd_set *mask)
-{
-  int fd;
-
-  for (fd = 0; fd <= max_keyboard_desc; fd++)
-    if (FD_ISSET (fd, mask) && FD_ISSET (fd, &input_wait_mask)
-       && !FD_ISSET (fd, &non_keyboard_wait_mask))
-      return 1;
-
-  return 0;
-}
-\f
-/* Enumeration of and access to system processes a-la ps(1).  */
-
-DEFUN ("list-system-processes", Flist_system_processes, Slist_system_processes,
-       0, 0, 0,
-       doc: /* Return a list of numerical process IDs of all running processes.
-If this functionality is unsupported, return nil.
-
-See `process-attributes' for getting attributes of a process given its ID.  */)
-  (void)
-{
-  return list_system_processes ();
-}
-
-DEFUN ("process-attributes", Fprocess_attributes,
-       Sprocess_attributes, 1, 1, 0,
-       doc: /* Return attributes of the process given by its PID, a number.
-
-Value is an alist where each element is a cons cell of the form
-
-    \(KEY . VALUE)
-
-If this functionality is unsupported, the value is nil.
-
-See `list-system-processes' for getting a list of all process IDs.
-
-The KEYs of the attributes that this function may return are listed
-below, together with the type of the associated VALUE (in parentheses).
-Not all platforms support all of these attributes; unsupported
-attributes will not appear in the returned alist.
-Unless explicitly indicated otherwise, numbers can have either
-integer or floating point values.
-
- euid    -- Effective user User ID of the process (number)
- user    -- User name corresponding to euid (string)
- egid    -- Effective user Group ID of the process (number)
- group   -- Group name corresponding to egid (string)
- comm    -- Command name (executable name only) (string)
- state   -- Process state code, such as "S", "R", or "T" (string)
- ppid    -- Parent process ID (number)
- pgrp    -- Process group ID (number)
- sess    -- Session ID, i.e. process ID of session leader (number)
- ttname  -- Controlling tty name (string)
- tpgid   -- ID of foreground process group on the process's tty (number)
- minflt  -- number of minor page faults (number)
- majflt  -- number of major page faults (number)
- cminflt -- cumulative number of minor page faults (number)
- cmajflt -- cumulative number of major page faults (number)
- utime   -- user time used by the process, in the (HIGH LOW USEC) format
- stime   -- system time used by the process, in the (HIGH LOW USEC) format
- time    -- sum of utime and stime, in the (HIGH LOW USEC) format
- cutime  -- user time used by the process and its children, (HIGH LOW USEC)
- cstime  -- system time used by the process and its children, (HIGH LOW USEC)
- ctime   -- sum of cutime and cstime, in the (HIGH LOW USEC) format
- pri     -- priority of the process (number)
- nice    -- nice value of the process (number)
- thcount -- process thread count (number)
- start   -- time the process started, in the (HIGH LOW USEC) format
- vsize   -- virtual memory size of the process in KB's (number)
- rss     -- resident set size of the process in KB's (number)
- etime   -- elapsed time the process is running, in (HIGH LOW USEC) format
- pcpu    -- percents of CPU time used by the process (floating-point number)
- pmem    -- percents of total physical memory used by process's resident set
-              (floating-point number)
- args    -- command line which invoked the process (string).  */)
-  ( Lisp_Object pid)
-{
-  return system_process_attributes (pid);
-}
-\f
-void
-init_process (void)
-{
-  register int i;
-
-  inhibit_sentinels = 0;
-
-#ifdef SIGCHLD
-#ifndef CANNOT_DUMP
-  if (! noninteractive || initialized)
-#endif
-    signal (SIGCHLD, sigchld_handler);
-#endif
-
-  FD_ZERO (&input_wait_mask);
-  FD_ZERO (&non_keyboard_wait_mask);
-  FD_ZERO (&non_process_wait_mask);
-  max_process_desc = 0;
-
-#ifdef NON_BLOCKING_CONNECT
-  FD_ZERO (&connect_wait_mask);
-  num_pending_connects = 0;
-#endif
-
-#ifdef ADAPTIVE_READ_BUFFERING
-  process_output_delay_count = 0;
-  process_output_skip = 0;
-#endif
-
-  /* Don't do this, it caused infinite select loops.  The display
-     method should call add_keyboard_wait_descriptor on stdin if it
-     needs that.  */
-#if 0
-  FD_SET (0, &input_wait_mask);
-#endif
-
-  Vprocess_alist = Qnil;
-#ifdef SIGCHLD
-  deleted_pid_list = Qnil;
-#endif
-  for (i = 0; i < MAXDESC; i++)
-    {
-      chan_process[i] = Qnil;
-      proc_buffered_char[i] = -1;
-    }
-  memset (proc_decode_coding_system, 0, sizeof proc_decode_coding_system);
-  memset (proc_encode_coding_system, 0, sizeof proc_encode_coding_system);
-#ifdef DATAGRAM_SOCKETS
-  memset (datagram_address, 0, sizeof datagram_address);
-#endif
-
-#ifdef HAVE_SOCKETS
- {
-   Lisp_Object subfeatures = Qnil;
-   const struct socket_options *sopt;
-
-#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
-#ifdef HAVE_SEQPACKET
-   ADD_SUBFEATURE (QCtype, Qseqpacket);
-#endif
-#ifdef HAVE_LOCAL_SOCKETS
-   ADD_SUBFEATURE (QCfamily, Qlocal);
-#endif
-   ADD_SUBFEATURE (QCfamily, Qipv4);
-#ifdef AF_INET6
-   ADD_SUBFEATURE (QCfamily, Qipv6);
-#endif
-#ifdef HAVE_GETSOCKNAME
-   ADD_SUBFEATURE (QCservice, Qt);
-#endif
-#if defined(O_NONBLOCK) || defined(O_NDELAY)
-   ADD_SUBFEATURE (QCserver, Qt);
-#endif
-
-   for (sopt = socket_options; sopt->name; sopt++)
-     subfeatures = pure_cons (intern_c_string (sopt->name), subfeatures);
-
-   Fprovide (intern_c_string ("make-network-process"), subfeatures);
- }
-#endif /* HAVE_SOCKETS */
-
-#if defined (DARWIN_OS)
-  /* PTYs are broken on Darwin < 6, but are sometimes useful for interactive
-     processes.  As such, we only change the default value.  */
- if (initialized)
-  {
-    char *release = get_operating_system_release ();
-    if (!release || !release[0] || (release[0] < MIN_PTY_KERNEL_VERSION
-                                   && release[1] == '.')) {
-      Vprocess_connection_type = Qnil;
-    }
-  }
-#endif
-}
-
-void
-syms_of_process (void)
-{
-  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);
-
-  /* Qexit is already staticpro'd by syms_of_eval; don't staticpro it
-     here again.
-
-     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);
-#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);
-
-  QCname = intern_c_string (":name");
-  staticpro (&QCname);
-  QCbuffer = intern_c_string (":buffer");
-  staticpro (&QCbuffer);
-  QChost = intern_c_string (":host");
-  staticpro (&QChost);
-  QCservice = intern_c_string (":service");
-  staticpro (&QCservice);
-  QCtype = intern_c_string (":type");
-  staticpro (&QCtype);
-  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);
-
-  staticpro (&Vprocess_alist);
-#ifdef SIGCHLD
-  staticpro (&deleted_pid_list);
-#endif
-
-  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);
-
-  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;
+/* Return nonzero if *MASK has a bit set
+   that corresponds to one of the keyboard input descriptors.  */
 
-  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:
-then a pipe is used in any case.
-The value takes effect when `start-process' is called.  */);
-  Vprocess_connection_type = Qt;
+static int
+keyboard_bit_set (fd_set *mask)
+{
+  int fd;
 
-#ifdef 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.
-This behavior can be remedied to some extent by setting this variable to a
-non-nil value, as it will automatically delay reading from such processes, to
-allow them to produce more output before Emacs tries to read it.
-If the value is t, the delay is reset after each write to the process; any other
-non-nil value means that the delay is not reset on write.
-The variable takes effect when `start-process' is called.  */);
-  Vprocess_adaptive_read_buffering = Qt;
-#endif
+  for (fd = 0; fd <= max_keyboard_desc; fd++)
+    if (FD_ISSET (fd, mask) && FD_ISSET (fd, &input_wait_mask)
+       && !FD_ISSET (fd, &non_keyboard_wait_mask))
+      return 1;
 
-  defsubr (&Sprocessp);
-  defsubr (&Sget_process);
-  defsubr (&Sget_buffer_process);
-  defsubr (&Sdelete_process);
-  defsubr (&Sprocess_status);
-  defsubr (&Sprocess_exit_status);
-  defsubr (&Sprocess_id);
-  defsubr (&Sprocess_name);
-  defsubr (&Sprocess_tty_name);
-  defsubr (&Sprocess_command);
-  defsubr (&Sset_process_buffer);
-  defsubr (&Sprocess_buffer);
-  defsubr (&Sprocess_mark);
-  defsubr (&Sset_process_filter);
-  defsubr (&Sprocess_filter);
-  defsubr (&Sset_process_sentinel);
-  defsubr (&Sprocess_sentinel);
-  defsubr (&Sset_process_window_size);
-  defsubr (&Sset_process_inherit_coding_system_flag);
-  defsubr (&Sprocess_inherit_coding_system_flag);
-  defsubr (&Sset_process_query_on_exit_flag);
-  defsubr (&Sprocess_query_on_exit_flag);
-  defsubr (&Sprocess_contact);
-  defsubr (&Sprocess_plist);
-  defsubr (&Sset_process_plist);
-  defsubr (&Slist_processes);
-  defsubr (&Sprocess_list);
-  defsubr (&Sstart_process);
-#ifdef HAVE_SERIAL
-  defsubr (&Sserial_process_configure);
-  defsubr (&Smake_serial_process);
-#endif /* HAVE_SERIAL  */
-#ifdef HAVE_SOCKETS
-  defsubr (&Sset_network_process_option);
-  defsubr (&Smake_network_process);
-  defsubr (&Sformat_network_address);
-#endif /* HAVE_SOCKETS */
-#if defined(HAVE_SOCKETS) && defined(HAVE_NET_IF_H) && defined(HAVE_SYS_IOCTL_H)
-#ifdef SIOCGIFCONF
-  defsubr (&Snetwork_interface_list);
-#endif
-#if defined(SIOCGIFADDR) || defined(SIOCGIFHWADDR) || defined(SIOCGIFFLAGS)
-  defsubr (&Snetwork_interface_info);
-#endif
-#endif /* HAVE_SOCKETS ... */
-#ifdef DATAGRAM_SOCKETS
-  defsubr (&Sprocess_datagram_address);
-  defsubr (&Sset_process_datagram_address);
-#endif
-  defsubr (&Saccept_process_output);
-  defsubr (&Sprocess_send_region);
-  defsubr (&Sprocess_send_string);
-  defsubr (&Sinterrupt_process);
-  defsubr (&Skill_process);
-  defsubr (&Squit_process);
-  defsubr (&Sstop_process);
-  defsubr (&Scontinue_process);
-  defsubr (&Sprocess_running_child_p);
-  defsubr (&Sprocess_send_eof);
-  defsubr (&Ssignal_process);
-  defsubr (&Swaiting_for_user_input_p);
-  defsubr (&Sprocess_type);
-  defsubr (&Sset_process_coding_system);
-  defsubr (&Sprocess_coding_system);
-  defsubr (&Sset_process_filter_multibyte);
-  defsubr (&Sprocess_filter_multibyte_p);
-  defsubr (&Slist_system_processes);
-  defsubr (&Sprocess_attributes);
+  return 0;
 }
 
-\f
-#else /* not subprocesses */
-
-#include <sys/types.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <setjmp.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "lisp.h"
-#include "systime.h"
-#include "character.h"
-#include "coding.h"
-#include "termopts.h"
-#include "sysselect.h"
-
-extern int frame_garbaged;
-
-extern EMACS_TIME timer_check ();
-extern int timers_run;
-
-Lisp_Object QCtype, QCname;
-
-Lisp_Object Qeuid, Qegid, Qcomm, Qstate, Qppid, Qpgrp, Qsess, Qttname, Qtpgid;
-Lisp_Object Qminflt, Qmajflt, Qcminflt, Qcmajflt, Qutime, Qstime, Qcstime;
-Lisp_Object Qcutime, Qpri, Qnice, Qthcount, Qstart, Qvsize, Qrss, Qargs;
-Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem, Qtime, Qctime;
+#else  /* not subprocesses */
 
-/* Non-zero if keyboard input is on hold, zero otherwise.  */
-static int kbd_is_on_hold;
+/* Defined on msdos.c.  */
+extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
+                      EMACS_TIME *);
 
-/* As described above, except assuming that there are no subprocesses:
+/* Implementation of wait_reading_process_output, assuming that there
+   are no subprocesses.  Used only by the MS-DOS build.
 
    Wait for timeout to elapse and/or keyboard input to be available.
 
@@ -7568,12 +6866,10 @@ static int kbd_is_on_hold;
    Return true if we received input from any process.  */
 
 int
-wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
-                            wait_for_cell, wait_proc, just_wait_proc)
-     int time_limit, microsecs, read_kbd, do_display;
-     Lisp_Object wait_for_cell;
-     struct Lisp_Process *wait_proc;
-     int just_wait_proc;
+wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
+                            int do_display,
+                            Lisp_Object wait_for_cell,
+                            struct Lisp_Process *wait_proc, int just_wait_proc)
 {
   register int nfds;
   EMACS_TIME end_time, timeout;
@@ -7720,15 +7016,6 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
          else
            error ("select error: %s", emacs_strerror (xerrno));
        }
-#ifdef SOLARIS2
-      else if (nfds > 0 && (waitchannels & 1)  && interrupt_input)
-       /* System sometimes fails to deliver SIGIO.  */
-       kill (getpid (), SIGIO);
-#endif
-#ifdef SIGIO
-      if (read_kbd && interrupt_input && (waitchannels & 1))
-       kill (getpid (), SIGIO);
-#endif
 
       /* Check for keyboard input */
 
@@ -7754,55 +7041,201 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
       if (! NILP (wait_for_cell)
          && detect_input_pending ())
        {
-         swallow_events (do_display);
-         if (detect_input_pending ())
-           break;
+         swallow_events (do_display);
+         if (detect_input_pending ())
+           break;
+       }
+
+      /* Exit now if the cell we're waiting for became non-nil.  */
+      if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell)))
+       break;
+    }
+
+  start_polling ();
+
+  return 0;
+}
+
+#endif /* not subprocesses */
+
+/* The following functions are needed even if async subprocesses are
+   not supported.  Some of them are no-op stubs in that case.  */
+
+/* Add DESC to the set of keyboard input descriptors.  */
+
+void
+add_keyboard_wait_descriptor (int desc)
+{
+#ifdef subprocesses
+  FD_SET (desc, &input_wait_mask);
+  FD_SET (desc, &non_process_wait_mask);
+  if (desc > max_keyboard_desc)
+    max_keyboard_desc = desc;
+#endif
+}
+
+/* From now on, do not expect DESC to give keyboard input.  */
+
+void
+delete_keyboard_wait_descriptor (int desc)
+{
+#ifdef subprocesses
+  int fd;
+  int lim = max_keyboard_desc;
+
+  FD_CLR (desc, &input_wait_mask);
+  FD_CLR (desc, &non_process_wait_mask);
+
+  if (desc == max_keyboard_desc)
+    for (fd = 0; fd < lim; fd++)
+      if (FD_ISSET (fd, &input_wait_mask)
+         && !FD_ISSET (fd, &non_keyboard_wait_mask)
+         && !FD_ISSET (fd, &gpm_wait_mask))
+       max_keyboard_desc = fd;
+#endif /* subprocesses */
+}
+
+/* Setup coding systems of PROCESS.  */
+
+void
+setup_process_coding_systems (Lisp_Object process)
+{
+#ifdef subprocesses
+  struct Lisp_Process *p = XPROCESS (process);
+  int inch = p->infd;
+  int outch = p->outfd;
+  Lisp_Object coding_system;
+
+  if (inch < 0 || outch < 0)
+    return;
+
+  if (!proc_decode_coding_system[inch])
+    proc_decode_coding_system[inch]
+      = (struct coding_system *) xmalloc (sizeof (struct coding_system));
+  coding_system = p->decode_coding_system;
+  if (! NILP (p->filter))
+    ;
+  else if (BUFFERP (p->buffer))
+    {
+      if (NILP (XBUFFER (p->buffer)->enable_multibyte_characters))
+       coding_system = raw_text_coding_system (coding_system);
+    }
+  setup_coding_system (coding_system, proc_decode_coding_system[inch]);
+
+  if (!proc_encode_coding_system[outch])
+    proc_encode_coding_system[outch]
+      = (struct coding_system *) xmalloc (sizeof (struct coding_system));
+  setup_coding_system (p->encode_coding_system,
+                      proc_encode_coding_system[outch]);
+#endif
+}
+
+/* Close all descriptors currently in use for communication
+   with subprocess.  This is used in a newly-forked subprocess
+   to get rid of irrelevant descriptors.  */
+
+void
+close_process_descs (void)
+{
+#ifndef DOS_NT
+  int i;
+  for (i = 0; i < MAXDESC; i++)
+    {
+      Lisp_Object process;
+      process = chan_process[i];
+      if (!NILP (process))
+       {
+         int in  = XPROCESS (process)->infd;
+         int out = XPROCESS (process)->outfd;
+         if (in >= 0)
+           emacs_close (in);
+         if (out >= 0 && in != out)
+           emacs_close (out);
        }
-
-      /* Exit now if the cell we're waiting for became non-nil.  */
-      if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell)))
-       break;
     }
-
-  start_polling ();
-
-  return 0;
+#endif
 }
 
-
-/* Don't confuse make-docfile by having two doc strings for this function.
-   make-docfile does not pay attention to #if, for good reason!  */
 DEFUN ("get-buffer-process", Fget_buffer_process, Sget_buffer_process, 1, 1, 0,
-       0)
-  (register Lisp_Object name)
+       doc: /* Return the (or a) process associated with BUFFER.
+BUFFER may be a buffer or the name of one.  */)
+  (register Lisp_Object buffer)
 {
+#ifdef subprocesses
+  register Lisp_Object buf, tail, proc;
+
+  if (NILP (buffer)) return Qnil;
+  buf = Fget_buffer (buffer);
+  if (NILP (buf)) return Qnil;
+
+  for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
+    {
+      proc = Fcdr (XCAR (tail));
+      if (PROCESSP (proc) && EQ (XPROCESS (proc)->buffer, buf))
+       return proc;
+    }
+#endif /* subprocesses */
   return Qnil;
 }
 
-  /* Don't confuse make-docfile by having two doc strings for this function.
-     make-docfile does not pay attention to #if, for good reason!  */
 DEFUN ("process-inherit-coding-system-flag",
        Fprocess_inherit_coding_system_flag, Sprocess_inherit_coding_system_flag,
        1, 1, 0,
-       0)
+       doc: /* Return the value of inherit-coding-system flag for PROCESS.
+If this flag is t, `buffer-file-coding-system' of the buffer
+associated with PROCESS will inherit the coding system used to decode
+the process output.  */)
   (register Lisp_Object process)
 {
+#ifdef subprocesses
+  CHECK_PROCESS (process);
+  return XPROCESS (process)->inherit_coding_system_flag ? Qt : Qnil;
+#else
   /* Ignore the argument and return the value of
      inherit-process-coding-system.  */
   return inherit_process_coding_system ? Qt : Qnil;
+#endif
 }
 
 /* Kill all processes associated with `buffer'.
-   If `buffer' is nil, kill all processes.
-   Since we have no subprocesses, this does nothing.  */
+   If `buffer' is nil, kill all processes  */
 
 void
-kill_buffer_processes (buffer)
-     Lisp_Object buffer;
+kill_buffer_processes (Lisp_Object buffer)
+{
+#ifdef subprocesses
+  Lisp_Object tail, proc;
+
+  for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
+    {
+      proc = XCDR (XCAR (tail));
+      if (PROCESSP (proc)
+         && (NILP (buffer) || EQ (XPROCESS (proc)->buffer, buffer)))
+       {
+         if (NETCONN_P (proc) || SERIALCONN_P (proc))
+           Fdelete_process (proc);
+         else if (XPROCESS (proc)->infd >= 0)
+           process_send_signal (proc, SIGHUP, Qnil, 1);
+       }
+    }
+#else  /* subprocesses */
+  /* Since we have no subprocesses, this does nothing.  */
+#endif /* subprocesses */
+}
+
+DEFUN ("waiting-for-user-input-p", Fwaiting_for_user_input_p, Swaiting_for_user_input_p,
+       0, 0, 0,
+       doc: /* Returns non-nil if Emacs is waiting for input from the user.
+This is intended for use by asynchronous process output filters and sentinels.  */)
+  (void)
 {
+#ifdef subprocesses
+  return (waiting_for_user_input_p ? Qt : Qnil);
+#else
+  return Qnil;
+#endif
 }
 
-\f
 /* Stop reading input from keyboard sources.  */
 
 void
@@ -7827,6 +7260,9 @@ kbd_on_hold_p (void)
   return kbd_is_on_hold;
 }
 
+\f
+/* Enumeration of and access to system processes a-la ps(1).  */
+
 DEFUN ("list-system-processes", Flist_system_processes, Slist_system_processes,
        0, 0, 0,
        doc: /* Return a list of numerical process IDs of all running processes.
@@ -7835,82 +7271,289 @@ If this functionality is unsupported, return nil.
 See `process-attributes' for getting attributes of a process given its ID.  */)
   (void)
 {
-  return list_system_processes ();
-}
+  return list_system_processes ();
+}
+
+DEFUN ("process-attributes", Fprocess_attributes,
+       Sprocess_attributes, 1, 1, 0,
+       doc: /* Return attributes of the process given by its PID, a number.
+
+Value is an alist where each element is a cons cell of the form
+
+    \(KEY . VALUE)
+
+If this functionality is unsupported, the value is nil.
+
+See `list-system-processes' for getting a list of all process IDs.
+
+The KEYs of the attributes that this function may return are listed
+below, together with the type of the associated VALUE (in parentheses).
+Not all platforms support all of these attributes; unsupported
+attributes will not appear in the returned alist.
+Unless explicitly indicated otherwise, numbers can have either
+integer or floating point values.
+
+ euid    -- Effective user User ID of the process (number)
+ user    -- User name corresponding to euid (string)
+ egid    -- Effective user Group ID of the process (number)
+ group   -- Group name corresponding to egid (string)
+ comm    -- Command name (executable name only) (string)
+ state   -- Process state code, such as "S", "R", or "T" (string)
+ ppid    -- Parent process ID (number)
+ pgrp    -- Process group ID (number)
+ sess    -- Session ID, i.e. process ID of session leader (number)
+ ttname  -- Controlling tty name (string)
+ tpgid   -- ID of foreground process group on the process's tty (number)
+ minflt  -- number of minor page faults (number)
+ majflt  -- number of major page faults (number)
+ cminflt -- cumulative number of minor page faults (number)
+ cmajflt -- cumulative number of major page faults (number)
+ utime   -- user time used by the process, in the (HIGH LOW USEC) format
+ stime   -- system time used by the process, in the (HIGH LOW USEC) format
+ time    -- sum of utime and stime, in the (HIGH LOW USEC) format
+ cutime  -- user time used by the process and its children, (HIGH LOW USEC)
+ cstime  -- system time used by the process and its children, (HIGH LOW USEC)
+ ctime   -- sum of cutime and cstime, in the (HIGH LOW USEC) format
+ pri     -- priority of the process (number)
+ nice    -- nice value of the process (number)
+ thcount -- process thread count (number)
+ start   -- time the process started, in the (HIGH LOW USEC) format
+ vsize   -- virtual memory size of the process in KB's (number)
+ rss     -- resident set size of the process in KB's (number)
+ etime   -- elapsed time the process is running, in (HIGH LOW USEC) format
+ pcpu    -- percents of CPU time used by the process (floating-point number)
+ pmem    -- percents of total physical memory used by process's resident set
+              (floating-point number)
+ args    -- command line which invoked the process (string).  */)
+  ( Lisp_Object pid)
+{
+  return system_process_attributes (pid);
+}
+
+\f
+void
+init_process (void)
+{
+#ifdef subprocesses
+  register int i;
+
+  inhibit_sentinels = 0;
+
+#ifdef SIGCHLD
+#ifndef CANNOT_DUMP
+  if (! noninteractive || initialized)
+#endif
+    signal (SIGCHLD, sigchld_handler);
+#endif
+
+  FD_ZERO (&input_wait_mask);
+  FD_ZERO (&non_keyboard_wait_mask);
+  FD_ZERO (&non_process_wait_mask);
+  max_process_desc = 0;
+
+#ifdef NON_BLOCKING_CONNECT
+  FD_ZERO (&connect_wait_mask);
+  num_pending_connects = 0;
+#endif
+
+#ifdef ADAPTIVE_READ_BUFFERING
+  process_output_delay_count = 0;
+  process_output_skip = 0;
+#endif
+
+  /* Don't do this, it caused infinite select loops.  The display
+     method should call add_keyboard_wait_descriptor on stdin if it
+     needs that.  */
+#if 0
+  FD_SET (0, &input_wait_mask);
+#endif
+
+  Vprocess_alist = Qnil;
+#ifdef SIGCHLD
+  deleted_pid_list = Qnil;
+#endif
+  for (i = 0; i < MAXDESC; i++)
+    {
+      chan_process[i] = Qnil;
+      proc_buffered_char[i] = -1;
+    }
+  memset (proc_decode_coding_system, 0, sizeof proc_decode_coding_system);
+  memset (proc_encode_coding_system, 0, sizeof proc_encode_coding_system);
+#ifdef DATAGRAM_SOCKETS
+  memset (datagram_address, 0, sizeof datagram_address);
+#endif
+
+ {
+   Lisp_Object subfeatures = Qnil;
+   const struct socket_options *sopt;
+
+#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
+#ifdef HAVE_SEQPACKET
+   ADD_SUBFEATURE (QCtype, Qseqpacket);
+#endif
+#ifdef HAVE_LOCAL_SOCKETS
+   ADD_SUBFEATURE (QCfamily, Qlocal);
+#endif
+   ADD_SUBFEATURE (QCfamily, Qipv4);
+#ifdef AF_INET6
+   ADD_SUBFEATURE (QCfamily, Qipv6);
+#endif
+#ifdef HAVE_GETSOCKNAME
+   ADD_SUBFEATURE (QCservice, Qt);
+#endif
+#if defined(O_NONBLOCK) || defined(O_NDELAY)
+   ADD_SUBFEATURE (QCserver, Qt);
+#endif
+
+   for (sopt = socket_options; sopt->name; sopt++)
+     subfeatures = pure_cons (intern_c_string (sopt->name), subfeatures);
+
+   Fprovide (intern_c_string ("make-network-process"), subfeatures);
+ }
+
+#if defined (DARWIN_OS)
+  /* PTYs are broken on Darwin < 6, but are sometimes useful for interactive
+     processes.  As such, we only change the default value.  */
+ if (initialized)
+  {
+    const char *release = get_operating_system_release ();
+    if (!release || !release[0] || (release[0] < MIN_PTY_KERNEL_VERSION
+                                   && release[1] == '.')) {
+      Vprocess_connection_type = Qnil;
+    }
+  }
+#endif
+#endif /* subprocesses */
+  kbd_is_on_hold = 0;
+}
+
+void
+syms_of_process (void)
+{
+#ifdef subprocesses
 
-DEFUN ("process-attributes", Fprocess_attributes,
-       Sprocess_attributes, 1, 1, 0,
-       doc: /* Return attributes of the process given by its PID, a number.
+  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);
 
-Value is an alist where each element is a cons cell of the form
+  /* Qexit is already staticpro'd by syms_of_eval; don't staticpro it
+     here again.
 
-    \(KEY . VALUE)
+     Qexit = intern_c_string ("exit");
+     staticpro (&Qexit); */
 
-If this functionality is unsupported, the value is nil.
+  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);
+#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);
 
-See `list-system-processes' for getting a list of all process IDs.
+  QCport = intern_c_string (":port");
+  staticpro (&QCport);
+  QCspeed = intern_c_string (":speed");
+  staticpro (&QCspeed);
+  QCprocess = intern_c_string (":process");
+  staticpro (&QCprocess);
 
-The KEYs of the attributes that this function may return are listed
-below, together with the type of the associated VALUE (in parentheses).
-Not all platforms support all of these attributes; unsupported
-attributes will not appear in the returned alist.
-Unless explicitly indicated otherwise, numbers can have either
-integer or floating point values.
+  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);
 
- euid    -- Effective user User ID of the process (number)
- user    -- User name corresponding to euid (string)
- egid    -- Effective user Group ID of the process (number)
- group   -- Group name corresponding to egid (string)
- comm    -- Command name (executable name only) (string)
- state   -- Process state code, such as "S", "R", or "T" (string)
- ppid    -- Parent process ID (number)
- pgrp    -- Process group ID (number)
- sess    -- Session ID, i.e. process ID of session leader (number)
- ttname  -- Controlling tty name (string)
- tpgid   -- ID of foreground process group on the process's tty (number)
- minflt  -- number of minor page faults (number)
- majflt  -- number of major page faults (number)
- cminflt -- cumulative number of minor page faults (number)
- cmajflt -- cumulative number of major page faults (number)
- utime   -- user time used by the process, in the (HIGH LOW USEC) format
- stime   -- system time used by the process, in the (HIGH LOW USEC) format
- time    -- sum of utime and stime, in the (HIGH LOW USEC) format
- cutime  -- user time used by the process and its children, (HIGH LOW USEC)
- cstime  -- system time used by the process and its children, (HIGH LOW USEC)
- ctime   -- sum of cutime and cstime, in the (HIGH LOW USEC) format
- pri     -- priority of the process (number)
- nice    -- nice value of the process (number)
- thcount -- process thread count (number)
- start   -- time the process started, in the (HIGH LOW USEC) format
- vsize   -- virtual memory size of the process in KB's (number)
- rss     -- resident set size of the process in KB's (number)
- etime   -- elapsed time the process is running, in (HIGH LOW USEC) format
- pcpu    -- percents of CPU time used by the process (floating-point number)
- pmem    -- percents of total physical memory used by process's resident set
-              (floating-point number)
- args    -- command line which invoked the process (string).   */)
-  ( Lisp_Object pid)
-{
-  return system_process_attributes (pid);
-}
+  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);
 
-void
-init_process ()
-{
-  kbd_is_on_hold = 0;
-}
+  Qlast_nonmenu_event = intern_c_string ("last-nonmenu-event");
+  staticpro (&Qlast_nonmenu_event);
+
+  staticpro (&Vprocess_alist);
+#ifdef SIGCHLD
+  staticpro (&deleted_pid_list);
+#endif
+
+#endif /* subprocesses */
 
-void
-syms_of_process ()
-{
-  QCtype = intern_c_string (":type");
-  staticpro (&QCtype);
   QCname = intern_c_string (":name");
   staticpro (&QCname);
   QCtype = intern_c_string (":type");
   staticpro (&QCtype);
-  QCname = intern_c_string (":name");
-  staticpro (&QCname);
+
   Qeuid = intern_c_string ("euid");
   staticpro (&Qeuid);
   Qegid = intern_c_string ("egid");
@@ -7974,14 +7617,105 @@ syms_of_process ()
   Qargs = intern_c_string ("args");
   staticpro (&Qargs);
 
+  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,
+              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:
+then a pipe is used in any case.
+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,
+              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.
+This behavior can be remedied to some extent by setting this variable to a
+non-nil value, as it will automatically delay reading from such processes, to
+allow them to produce more output before Emacs tries to read it.
+If the value is t, the delay is reset after each write to the process; any other
+non-nil value means that the delay is not reset on write.
+The variable takes effect when `start-process' is called.  */);
+  Vprocess_adaptive_read_buffering = Qt;
+#endif
+
+  defsubr (&Sprocessp);
+  defsubr (&Sget_process);
+  defsubr (&Sdelete_process);
+  defsubr (&Sprocess_status);
+  defsubr (&Sprocess_exit_status);
+  defsubr (&Sprocess_id);
+  defsubr (&Sprocess_name);
+  defsubr (&Sprocess_tty_name);
+  defsubr (&Sprocess_command);
+  defsubr (&Sset_process_buffer);
+  defsubr (&Sprocess_buffer);
+  defsubr (&Sprocess_mark);
+  defsubr (&Sset_process_filter);
+  defsubr (&Sprocess_filter);
+  defsubr (&Sset_process_sentinel);
+  defsubr (&Sprocess_sentinel);
+  defsubr (&Sset_process_window_size);
+  defsubr (&Sset_process_inherit_coding_system_flag);
+  defsubr (&Sset_process_query_on_exit_flag);
+  defsubr (&Sprocess_query_on_exit_flag);
+  defsubr (&Sprocess_contact);
+  defsubr (&Sprocess_plist);
+  defsubr (&Sset_process_plist);
+  defsubr (&Slist_processes);
+  defsubr (&Sprocess_list);
+  defsubr (&Sstart_process);
+#ifdef HAVE_SERIAL
+  defsubr (&Sserial_process_configure);
+  defsubr (&Smake_serial_process);
+#endif /* HAVE_SERIAL  */
+  defsubr (&Sset_network_process_option);
+  defsubr (&Smake_network_process);
+  defsubr (&Sformat_network_address);
+#if defined(HAVE_NET_IF_H) && defined(HAVE_SYS_IOCTL_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) */
+#ifdef DATAGRAM_SOCKETS
+  defsubr (&Sprocess_datagram_address);
+  defsubr (&Sset_process_datagram_address);
+#endif
+  defsubr (&Saccept_process_output);
+  defsubr (&Sprocess_send_region);
+  defsubr (&Sprocess_send_string);
+  defsubr (&Sinterrupt_process);
+  defsubr (&Skill_process);
+  defsubr (&Squit_process);
+  defsubr (&Sstop_process);
+  defsubr (&Scontinue_process);
+  defsubr (&Sprocess_running_child_p);
+  defsubr (&Sprocess_send_eof);
+  defsubr (&Ssignal_process);
+  defsubr (&Swaiting_for_user_input_p);
+  defsubr (&Sprocess_type);
+  defsubr (&Sset_process_coding_system);
+  defsubr (&Sprocess_coding_system);
+  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);
 }
 
-\f
-#endif /* not subprocesses */
-
 /* arch-tag: 3706c011-7b9a-4117-bd4f-59e7f701a4c4
    (do not change this comment) */