changeset 27558:f99efd14b932

(Fstart_process): Doc fix.
author Dave Love <fx@gnu.org>
date Tue, 01 Feb 2000 15:01:28 +0000
parents b6b71cf43a9f
children 282d42ed4ea6
files src/process.c src/process.c-dl
diffstat 2 files changed, 4978 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/process.c	Tue Feb 01 14:57:24 2000 +0000
+++ b/src/process.c	Tue Feb 01 15:01:28 2000 +0000
@@ -1023,7 +1023,6 @@
 
 DEFUN ("start-process", Fstart_process, Sstart_process, 3, MANY, 0,
   "Start a program in a subprocess.  Return the process object for it.\n\
-Args are NAME BUFFER PROGRAM &rest PROGRAM-ARGS\n\
 NAME is name for process.  It is modified if necessary to make it unique.\n\
 BUFFER is the buffer or (buffer-name) to associate with the process.\n\
  Process output goes at end of that buffer, unless you specify\n\
@@ -2835,6 +2834,7 @@
   Vinhibit_quit = Qt;
   update_echo_area ();
   Fsleep_for (make_number (2), Qnil);
+  return Qt;
 }
 
 /* Read pending output from the process channel,
@@ -4263,6 +4263,7 @@
   Vinhibit_quit = Qt;
   update_echo_area ();
   Fsleep_for (make_number (2), Qnil);
+  return Qt;
 }
 
 static void
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/process.c-dl	Tue Feb 01 15:01:28 2000 +0000
@@ -0,0 +1,4976 @@
+/* Asynchronous subprocess control for GNU Emacs.
+   Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 96, 98, 1999
+      Free Software Foundation, Inc.
+
+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 2, 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
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#define _GNU_SOURCE		/* to get strsignal declared with glibc 2 */
+#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.  */
+
+
+#ifdef subprocesses
+
+#include <stdio.h>
+#include <errno.h>
+#include <setjmp.h>
+#include <sys/types.h>		/* some typedefs are used in sys/file.h */
+#include <sys/file.h>
+#include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef WINDOWSNT
+#include <stdlib.h>
+#include <fcntl.h>
+#endif /* not WINDOWSNT */
+
+#ifdef HAVE_SOCKETS	/* TCP connection support, if kernel can do it */
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#ifdef NEED_NET_ERRNO_H
+#include <net/errno.h>
+#endif /* NEED_NET_ERRNO_H */
+#endif /* HAVE_SOCKETS */
+
+/* TERM is a poor-man's SLIP, used on GNU/Linux.  */
+#ifdef TERM
+#include <client.h>
+#endif
+
+/* On some systems, e.g. DGUX, inet_addr returns a 'struct in_addr'. */
+#ifdef HAVE_BROKEN_INET_ADDR
+#define IN_ADDR struct in_addr
+#define NUMERIC_ADDR_ERROR (numeric_addr.s_addr == -1)
+#else
+#define IN_ADDR unsigned long
+#define NUMERIC_ADDR_ERROR (numeric_addr == -1)
+#endif
+
+#if defined(BSD_SYSTEM) || defined(STRIDE)
+#include <sys/ioctl.h>
+#if !defined (O_NDELAY) && defined (HAVE_PTYS) && !defined(USG5)
+#include <fcntl.h>
+#endif /* HAVE_PTYS and no O_NDELAY */
+#endif /* BSD_SYSTEM || STRIDE */
+
+#ifdef BROKEN_O_NONBLOCK
+#undef O_NONBLOCK
+#endif /* BROKEN_O_NONBLOCK */
+
+#ifdef NEED_BSDTTY
+#include <bsdtty.h>
+#endif
+
+#ifdef IRIS
+#include <sys/sysmacros.h>	/* for "minor" */
+#endif /* not IRIS */
+
+#include "systime.h"
+#include "systty.h"
+
+#include "lisp.h"
+#include "window.h"
+#include "buffer.h"
+#include "charset.h"
+#include "coding.h"
+#include "process.h"
+#include "termhooks.h"
+#include "termopts.h"
+#include "commands.h"
+#include "frame.h"
+#include "blockinput.h"
+#include "keyboard.h"
+#include "dispextern.h"
+#include "composite.h"
+#include "atimer.h"
+
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+Lisp_Object Qprocessp;
+Lisp_Object Qrun, Qstop, Qsignal, Qopen, Qclosed;
+Lisp_Object Qlast_nonmenu_event;
+/* Qexit is declared and initialized in eval.c.  */
+
+/* a process object is a network connection when its childp field is neither
+   Qt nor Qnil but is instead a cons cell (HOSTNAME PORTNUM).  */
+
+#ifdef HAVE_SOCKETS
+#define NETCONN_P(p) (GC_CONSP (XPROCESS (p)->childp))
+#else
+#define NETCONN_P(p) 0
+#endif /* HAVE_SOCKETS */
+
+/* Define first descriptor number available for subprocesses.  */
+#ifdef VMS
+#define FIRST_PROC_DESC 1
+#else /* Not VMS */
+#define FIRST_PROC_DESC 3
+#endif
+
+/* Define SIGCHLD as an alias for SIGCLD.  There are many conditionals
+   testing SIGCHLD.  */
+
+#if !defined (SIGCHLD) && defined (SIGCLD)
+#define SIGCHLD SIGCLD
+#endif /* SIGCLD */
+
+#include "syssignal.h"
+
+#include "syswait.h"
+
+extern void set_waiting_for_input P_ ((EMACS_TIME *));
+
+extern int errno;
+#ifdef VMS
+extern char *sys_errlist[];
+#endif
+
+#ifndef HAVE_H_ERRNO
+extern int h_errno;
+#endif
+
+/* t means use pty, nil means use a pipe,
+   maybe other values to come.  */
+static Lisp_Object Vprocess_connection_type;
+
+#ifdef SKTPAIR
+#ifndef HAVE_SOCKETS
+#include <sys/socket.h>
+#endif
+#endif /* SKTPAIR */
+
+/* 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;
+/* Number of events for which the user or sentinel has been notified.  */
+int update_tick;
+
+#include "sysselect.h"
+
+extern int keyboard_bit_set P_ ((SELECT_TYPE *));
+
+/* 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
+#define POLL_FOR_INPUT
+#endif
+
+/* Mask of bits indicating the descriptors that we wait for input on.  */
+
+static SELECT_TYPE input_wait_mask;
+
+/* Mask that excludes keyboard input descriptor (s).  */
+
+static SELECT_TYPE non_keyboard_wait_mask;
+
+/* Mask that excludes process input descriptor (s).  */
+
+static SELECT_TYPE non_process_wait_mask;
+
+/* The largest descriptor currently in use for a process object.  */
+static int max_process_desc;
+
+/* The largest descriptor currently in use for keyboard input.  */
+static int max_keyboard_desc;
+
+/* 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];
+
+/* Alist of elements (NAME . PROCESS) */
+Lisp_Object Vprocess_alist;
+
+/* Buffered-ahead input char from process, indexed by channel.
+   -1 means empty (no char is buffered).
+   Used on sys V where the only way to tell if there is any
+   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];
+
+/* Table of `struct coding-system' for each process.  */
+static struct coding_system *proc_decode_coding_system[MAXDESC];
+static struct coding_system *proc_encode_coding_system[MAXDESC];
+
+static Lisp_Object get_process ();
+
+extern EMACS_TIME timer_check ();
+extern int timers_run;
+
+/* Maximum number of bytes to send to a pty without an eof.  */
+static int pty_max_bytes;
+
+extern Lisp_Object Vfile_name_coding_system, Vdefault_file_name_coding_system;
+
+#ifdef HAVE_PTYS
+/* The file name of the pty opened by allocate_pty.  */
+
+static char pty_name[24];
+#endif
+
+/* Compute the Lisp form of the process status, p->status, from
+   the numeric status that was returned by `wait'.  */
+
+Lisp_Object status_convert ();
+
+void
+update_status (p)
+     struct Lisp_Process *p;
+{
+  union { int i; WAITTYPE wt; } u;
+  u.i = XFASTINT (p->raw_status_low) + (XFASTINT (p->raw_status_high) << 16);
+  p->status = status_convert (u.wt);
+  p->raw_status_low = Qnil;
+  p->raw_status_high = Qnil;
+}
+
+/*  Convert a process status word in Unix format to 
+    the list that we use internally.  */
+
+Lisp_Object
+status_convert (w)
+     WAITTYPE w;
+{
+  if (WIFSTOPPED (w))
+    return Fcons (Qstop, Fcons (make_number (WSTOPSIG (w)), Qnil));
+  else if (WIFEXITED (w))
+    return Fcons (Qexit, Fcons (make_number (WRETCODE (w)),
+				WCOREDUMP (w) ? Qt : Qnil));
+  else if (WIFSIGNALED (w))
+    return Fcons (Qsignal, Fcons (make_number (WTERMSIG (w)),
+				  WCOREDUMP (w) ? Qt : Qnil));
+  else
+    return Qrun;
+}
+
+/* Given a status-list, extract the three pieces of information
+   and store them individually through the three pointers.  */
+
+void
+decode_status (l, symbol, code, coredump)
+     Lisp_Object l;
+     Lisp_Object *symbol;
+     int *code;
+     int *coredump;
+{
+  Lisp_Object tem;
+
+  if (SYMBOLP (l))
+    {
+      *symbol = l;
+      *code = 0;
+      *coredump = 0;
+    }
+  else
+    {
+      *symbol = XCAR (l);
+      tem = XCDR (l);
+      *code = XFASTINT (XCAR (tem));
+      tem = XCDR (tem);
+      *coredump = !NILP (tem);
+    }
+}
+
+/* Return a string describing a process status list.  */
+
+Lisp_Object 
+status_message (status)
+     Lisp_Object status;
+{
+  Lisp_Object symbol;
+  int code, coredump;
+  Lisp_Object string, string2;
+
+  decode_status (status, &symbol, &code, &coredump);
+
+  if (EQ (symbol, Qsignal) || EQ (symbol, Qstop))
+    {
+      char *signame;
+      synchronize_system_messages_locale ();
+      signame = strsignal (code);
+      if (signame == 0)
+	signame = "unknown";
+      string = build_string (signame);
+      string2 = build_string (coredump ? " (core dumped)\n" : "\n");
+      XSTRING (string)->data[0] = DOWNCASE (XSTRING (string)->data[0]);
+      return concat2 (string, string2);
+    }
+  else if (EQ (symbol, Qexit))
+    {
+      if (code == 0)
+	return build_string ("finished\n");
+      string = Fnumber_to_string (make_number (code));
+      string2 = build_string (coredump ? " (core dumped)\n" : "\n");
+      return concat2 (build_string ("exited abnormally with code "),
+		      concat2 (string, string2));
+    }
+  else
+    return Fcopy_sequence (Fsymbol_name (symbol));
+}
+
+#ifdef HAVE_PTYS
+
+/* Open an available pty, returning a file descriptor.
+   Return -1 on failure.
+   The file name of the terminal corresponding to the pty
+   is left in the variable pty_name.  */
+
+int
+allocate_pty ()
+{
+  struct stat stb;
+  register int c, i;
+  int fd;
+
+  /* Some systems name their pseudoterminals so that there are gaps in
+     the usual sequence - for example, on HP9000/S700 systems, there
+     are no pseudoterminals with names ending in 'f'.  So we wait for
+     three failures in a row before deciding that we've reached the
+     end of the ptys.  */
+  int failed_count = 0;
+
+#ifdef PTY_ITERATION
+  PTY_ITERATION
+#else
+  for (c = FIRST_PTY_LETTER; c <= 'z'; c++)
+    for (i = 0; i < 16; i++)
+#endif
+      {
+#ifdef PTY_NAME_SPRINTF
+	PTY_NAME_SPRINTF
+#else
+	sprintf (pty_name, "/dev/pty%c%x", c, i);
+#endif /* no PTY_NAME_SPRINTF */
+
+#ifdef PTY_OPEN
+	PTY_OPEN;
+#else /* no PTY_OPEN */
+#ifdef IRIS
+	/* Unusual IRIS code */
+ 	*ptyv = emacs_open ("/dev/ptc", O_RDWR | O_NDELAY, 0);
+ 	if (fd < 0)
+ 	  return -1;
+	if (fstat (fd, &stb) < 0)
+	  return -1;
+#else /* not IRIS */
+	if (stat (pty_name, &stb) < 0)
+	  {
+	    failed_count++;
+	    if (failed_count >= 3)
+	      return -1;
+	  }
+	else
+	  failed_count = 0;
+#ifdef O_NONBLOCK
+	fd = emacs_open (pty_name, O_RDWR | O_NONBLOCK, 0);
+#else
+	fd = emacs_open (pty_name, O_RDWR | O_NDELAY, 0);
+#endif
+#endif /* not IRIS */
+#endif /* no PTY_OPEN */
+
+	if (fd >= 0)
+	  {
+	    /* check to make certain that both sides are available
+	       this avoids a nasty yet stupid bug in rlogins */
+#ifdef PTY_TTY_NAME_SPRINTF
+	    PTY_TTY_NAME_SPRINTF
+#else
+            sprintf (pty_name, "/dev/tty%c%x", c, i);
+#endif /* no PTY_TTY_NAME_SPRINTF */
+#ifndef UNIPLUS
+	    if (access (pty_name, 6) != 0)
+	      {
+		emacs_close (fd);
+#if !defined(IRIS) && !defined(__sgi)
+		continue;
+#else
+		return -1;
+#endif /* IRIS */
+	      }
+#endif /* not UNIPLUS */
+	    setup_pty (fd);
+	    return fd;
+	  }
+      }
+  return -1;
+}
+#endif /* HAVE_PTYS */
+
+Lisp_Object
+make_process (name)
+     Lisp_Object name;
+{
+  struct Lisp_Vector *vec;
+  register Lisp_Object val, tem, name1;
+  register struct Lisp_Process *p;
+  char suffix[10];
+  register int i;
+
+  vec = allocate_vectorlike ((EMACS_INT) VECSIZE (struct Lisp_Process));
+  for (i = 0; i < VECSIZE (struct Lisp_Process); i++)
+    vec->contents[i] = Qnil;
+  vec->size = VECSIZE (struct Lisp_Process);
+  p = (struct Lisp_Process *)vec;
+
+  XSETINT (p->infd, -1);
+  XSETINT (p->outfd, -1);
+  XSETFASTINT (p->pid, 0);
+  XSETFASTINT (p->tick, 0);
+  XSETFASTINT (p->update_tick, 0);
+  p->raw_status_low = Qnil;
+  p->raw_status_high = Qnil;
+  p->status = Qrun;
+  p->mark = Fmake_marker ();
+
+  /* If name is already in use, modify it until it is unused.  */
+
+  name1 = name;
+  for (i = 1; ; i++)
+    {
+      tem = Fget_process (name1);
+      if (NILP (tem)) break;
+      sprintf (suffix, "<%d>", i);
+      name1 = concat2 (name, build_string (suffix));
+    }
+  name = name1;
+  p->name = name;
+  XSETPROCESS (val, p);
+  Vprocess_alist = Fcons (Fcons (name, val), Vprocess_alist);
+  return val;
+}
+
+void
+remove_process (proc)
+     register Lisp_Object proc;
+{
+  register Lisp_Object pair;
+
+  pair = Frassq (proc, Vprocess_alist);
+  Vprocess_alist = Fdelq (pair, Vprocess_alist);
+
+  deactivate_process (proc);
+}
+
+DEFUN ("processp", Fprocessp, Sprocessp, 1, 1, 0,
+  "Return t if OBJECT is a process.")
+  (object)
+     Lisp_Object object;
+{
+  return PROCESSP (object) ? Qt : Qnil;
+}
+
+DEFUN ("get-process", Fget_process, Sget_process, 1, 1, 0,
+  "Return the process named NAME, or nil if there is none.")
+  (name)
+     register Lisp_Object name;
+{
+  if (PROCESSP (name))
+    return name;
+  CHECK_STRING (name, 0);
+  return Fcdr (Fassoc (name, Vprocess_alist));
+}
+
+DEFUN ("get-buffer-process", Fget_buffer_process, Sget_buffer_process, 1, 1, 0,
+  "Return the (or a) process associated with BUFFER.\n\
+BUFFER may be a buffer or the name of one.")
+  (buffer)
+     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; !NILP (tail); tail = Fcdr (tail))
+    {
+      proc = Fcdr (Fcar (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
+   current buffer.  */
+
+static Lisp_Object
+get_process (name)
+     register Lisp_Object name;
+{
+  register Lisp_Object proc, obj;
+  if (STRINGP (name))
+    {
+      obj = Fget_process (name);
+      if (NILP (obj))
+	obj = Fget_buffer (name);
+      if (NILP (obj))
+	error ("Process %s does not exist", XSTRING (name)->data);
+    }
+  else if (NILP (name))
+    obj = Fcurrent_buffer ();
+  else
+    obj = name;
+
+  /* Now obj should be either a buffer object or a process object.
+   */
+  if (BUFFERP (obj))
+    {
+      proc = Fget_buffer_process (obj);
+      if (NILP (proc))
+	error ("Buffer %s has no process", XSTRING (XBUFFER (obj)->name)->data);
+    }
+  else
+    {
+      CHECK_PROCESS (obj, 0);
+      proc = obj;
+    }
+  return proc;
+}
+
+DEFUN ("delete-process", Fdelete_process, Sdelete_process, 1, 1, 0,
+  "Delete PROCESS: kill it and forget about it immediately.\n\
+PROCESS may be a process, a buffer, the name of a process or buffer, or\n\
+nil, indicating the current buffer's process.")
+  (process)
+     register Lisp_Object process;
+{
+  process = get_process (process);
+  XPROCESS (process)->raw_status_low = Qnil;
+  XPROCESS (process)->raw_status_high = Qnil;
+  if (NETCONN_P (process))
+    {
+      XPROCESS (process)->status = Fcons (Qexit, Fcons (make_number (0), Qnil));
+      XSETINT (XPROCESS (process)->tick, ++process_tick);
+    }
+  else if (XINT (XPROCESS (process)->infd) >= 0)
+    {
+      Fkill_process (process, Qnil);
+      /* Do this now, since remove_process will make sigchld_handler do nothing.  */
+      XPROCESS (process)->status 
+	= Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil));
+      XSETINT (XPROCESS (process)->tick, ++process_tick);
+      status_notify ();
+    }
+  remove_process (process);
+  return Qnil;
+}
+
+DEFUN ("process-status", Fprocess_status, Sprocess_status, 1, 1, 0,
+  "Return the status of PROCESS.\n\
+The returned value is one of the following symbols:\n\
+run  -- for a process that is running.\n\
+stop -- for a process stopped but continuable.\n\
+exit -- for a process that has exited.\n\
+signal -- for a process that has got a fatal signal.\n\
+open -- for a network stream connection that is open.\n\
+closed -- for a network stream connection that is closed.\n\
+nil -- if arg is a process name and no such process exists.\n\
+PROCESS may be a process, a buffer, the name of a process, or\n\
+nil, indicating the current buffer's process.")
+  (process)
+     register Lisp_Object process;
+{
+  register struct Lisp_Process *p;
+  register Lisp_Object status;
+
+  if (STRINGP (process))
+    process = Fget_process (process);
+  else
+    process = get_process (process);
+
+  if (NILP (process))
+    return process;
+
+  p = XPROCESS (process);
+  if (!NILP (p->raw_status_low))
+    update_status (p);
+  status = p->status;
+  if (CONSP (status))
+    status = XCAR (status);
+  if (NETCONN_P (process))
+    {
+      if (EQ (status, Qrun))
+	status = Qopen;
+      else if (EQ (status, Qexit))
+	status = Qclosed;
+    }
+  return status;
+}
+
+DEFUN ("process-exit-status", Fprocess_exit_status, Sprocess_exit_status,
+       1, 1, 0,
+  "Return the exit status of PROCESS or the signal number that killed it.\n\
+If PROCESS has not yet exited or died, return 0.")
+  (process)
+     register Lisp_Object process;
+{
+  CHECK_PROCESS (process, 0);
+  if (!NILP (XPROCESS (process)->raw_status_low))
+    update_status (XPROCESS (process));
+  if (CONSP (XPROCESS (process)->status))
+    return XCAR (XCDR (XPROCESS (process)->status));
+  return make_number (0);
+}
+
+DEFUN ("process-id", Fprocess_id, Sprocess_id, 1, 1, 0,
+  "Return the process id of PROCESS.\n\
+This is the pid of the Unix process which PROCESS uses or talks to.\n\
+For a network connection, this value is nil.")
+  (process)
+     register Lisp_Object process;
+{
+  CHECK_PROCESS (process, 0);
+  return XPROCESS (process)->pid;
+}
+
+DEFUN ("process-name", Fprocess_name, Sprocess_name, 1, 1, 0,
+  "Return the name of PROCESS, as a string.\n\
+This is the name of the program invoked in PROCESS,\n\
+possibly modified to make it unique among process names.")
+  (process)
+     register Lisp_Object process;
+{
+  CHECK_PROCESS (process, 0);
+  return XPROCESS (process)->name;
+}
+
+DEFUN ("process-command", Fprocess_command, Sprocess_command, 1, 1, 0,
+  "Return the command that was executed to start PROCESS.\n\
+This is a list of strings, the first string being the program executed\n\
+and the rest of the strings being the arguments given to it.\n\
+For a non-child channel, this is nil.")
+  (process)
+     register Lisp_Object process;
+{
+  CHECK_PROCESS (process, 0);
+  return XPROCESS (process)->command;
+}
+
+DEFUN ("process-tty-name", Fprocess_tty_name, Sprocess_tty_name, 1, 1, 0,
+  "Return the name of the terminal PROCESS uses, or nil if none.\n\
+This is the terminal that the process itself reads and writes on,\n\
+not the name of the pty that Emacs uses to talk with that terminal.")
+  (process)
+     register Lisp_Object process;
+{
+  CHECK_PROCESS (process, 0);
+  return XPROCESS (process)->tty_name;
+}
+
+DEFUN ("set-process-buffer", Fset_process_buffer, Sset_process_buffer,
+  2, 2, 0,
+  "Set buffer associated with PROCESS to BUFFER (a buffer, or nil).")
+  (process, buffer)
+     register Lisp_Object process, buffer;
+{
+  CHECK_PROCESS (process, 0);
+  if (!NILP (buffer))
+    CHECK_BUFFER (buffer, 1);
+  XPROCESS (process)->buffer = buffer;
+  return buffer;
+}
+
+DEFUN ("process-buffer", Fprocess_buffer, Sprocess_buffer,
+  1, 1, 0,
+  "Return the buffer PROCESS is associated with.\n\
+Output from PROCESS is inserted in this buffer unless PROCESS has a filter.")
+  (process)
+     register Lisp_Object process;
+{
+  CHECK_PROCESS (process, 0);
+  return XPROCESS (process)->buffer;
+}
+
+DEFUN ("process-mark", Fprocess_mark, Sprocess_mark,
+  1, 1, 0,
+  "Return the marker for the end of the last output from PROCESS.")
+  (process)
+     register Lisp_Object process;
+{
+  CHECK_PROCESS (process, 0);
+  return XPROCESS (process)->mark;
+}
+
+DEFUN ("set-process-filter", Fset_process_filter, Sset_process_filter,
+  2, 2, 0,
+  "Give PROCESS the filter function FILTER; nil means no filter.\n\
+t means stop accepting output from the process.\n\
+When a process has a filter, each time it does output\n\
+the entire string of output is passed to the filter.\n\
+The filter gets two arguments: the process and the string of output.\n\
+If the process has a filter, its buffer is not used for output.")
+  (process, filter)
+     register Lisp_Object process, filter;
+{
+  CHECK_PROCESS (process, 0);
+  if (EQ (filter, Qt))
+    {
+      FD_CLR (XINT (XPROCESS (process)->infd), &input_wait_mask);
+      FD_CLR (XINT (XPROCESS (process)->infd), &non_keyboard_wait_mask);
+    }
+  else if (EQ (XPROCESS (process)->filter, Qt))
+    {
+      FD_SET (XINT (XPROCESS (process)->infd), &input_wait_mask);
+      FD_SET (XINT (XPROCESS (process)->infd), &non_keyboard_wait_mask);
+    }
+  XPROCESS (process)->filter = filter;
+  return filter;
+}
+
+DEFUN ("process-filter", Fprocess_filter, Sprocess_filter,
+  1, 1, 0,
+  "Returns the filter function of PROCESS; nil if none.\n\
+See `set-process-filter' for more info on filter functions.")
+  (process)
+     register Lisp_Object process;
+{
+  CHECK_PROCESS (process, 0);
+  return XPROCESS (process)->filter;
+}
+
+DEFUN ("set-process-sentinel", Fset_process_sentinel, Sset_process_sentinel,
+  2, 2, 0,
+  "Give PROCESS the sentinel SENTINEL; nil for none.\n\
+The sentinel is called as a function when the process changes state.\n\
+It gets two arguments: the process, and a string describing the change.")
+  (process, sentinel)
+     register Lisp_Object process, sentinel;
+{
+  CHECK_PROCESS (process, 0);
+  XPROCESS (process)->sentinel = sentinel;
+  return sentinel;
+}
+
+DEFUN ("process-sentinel", Fprocess_sentinel, Sprocess_sentinel,
+  1, 1, 0,
+  "Return the sentinel of PROCESS; nil if none.\n\
+See `set-process-sentinel' for more info on sentinels.")
+  (process)
+     register Lisp_Object process;
+{
+  CHECK_PROCESS (process, 0);
+  return XPROCESS (process)->sentinel;
+}
+
+DEFUN ("set-process-window-size", Fset_process_window_size,
+  Sset_process_window_size, 3, 3, 0,
+  "Tell PROCESS that it has logical window size HEIGHT and WIDTH.")
+  (process, height, width)
+     register Lisp_Object process, height, width;
+{
+  CHECK_PROCESS (process, 0);
+  CHECK_NATNUM (height, 0);
+  CHECK_NATNUM (width, 0);
+  if (set_window_size (XINT (XPROCESS (process)->infd),
+		       XINT (height), XINT (width)) <= 0)
+    return Qnil;
+  else
+    return Qt;
+}
+
+DEFUN ("set-process-inherit-coding-system-flag",
+  Fset_process_inherit_coding_system_flag,
+  Sset_process_inherit_coding_system_flag, 2, 2, 0,
+  "Determine whether buffer of PROCESS will inherit coding-system.\n\
+If the second argument FLAG is non-nil, then the variable\n\
+`buffer-file-coding-system' of the buffer associated with PROCESS\n\
+will be bound to the value of the coding system used to decode\n\
+the process output.\n\
+\n\
+This is useful when the coding system specified for the process buffer\n\
+leaves either the character code conversion or the end-of-line conversion\n\
+unspecified, or if the coding system used to decode the process output\n\
+is more appropriate for saving the process buffer.\n\
+\n\
+Binding the variable `inherit-process-coding-system' to non-nil before\n\
+starting the process is an alternative way of setting the inherit flag\n\
+for the process which will run.")
+  (process, flag)
+     register Lisp_Object process, flag;
+{
+  CHECK_PROCESS (process, 0);
+  XPROCESS (process)->inherit_coding_system_flag = flag;
+  return flag;
+}
+
+DEFUN ("process-inherit-coding-system-flag",
+  Fprocess_inherit_coding_system_flag, Sprocess_inherit_coding_system_flag,
+  1, 1, 0,
+  "Return the value of inherit-coding-system flag for PROCESS.\n\
+If this flag is t, `buffer-file-coding-system' of the buffer\n\
+associated with PROCESS will inherit the coding system used to decode\n\
+the process output.")
+  (process)
+     register Lisp_Object process;
+{
+  CHECK_PROCESS (process, 0);
+  return XPROCESS (process)->inherit_coding_system_flag;
+}
+
+DEFUN ("process-kill-without-query", Fprocess_kill_without_query,
+  Sprocess_kill_without_query, 1, 2, 0,
+  "Say no query needed if PROCESS is running when Emacs is exited.\n\
+Optional second argument if non-nil says to require a query.\n\
+Value is t if a query was formerly required.")
+  (process, value)
+     register Lisp_Object process, value;
+{
+  Lisp_Object tem;
+
+  CHECK_PROCESS (process, 0);
+  tem = XPROCESS (process)->kill_without_query;
+  XPROCESS (process)->kill_without_query = Fnull (value);
+
+  return Fnull (tem);
+}
+
+DEFUN ("process-contact", Fprocess_contact, Sprocess_contact,
+  1, 1, 0,
+  "Return the contact info of PROCESS; t for a real child.\n\
+For a net connection, the value is a cons cell of the form (HOST SERVICE).")
+  (process)
+     register Lisp_Object process;
+{
+  CHECK_PROCESS (process, 0);
+  return XPROCESS (process)->childp;
+}
+
+#if 0 /* Turned off because we don't currently record this info
+	 in the process.  Perhaps add it.  */
+DEFUN ("process-connection", Fprocess_connection, Sprocess_connection, 1, 1, 0,
+ "Return the connection type of PROCESS.\n\
+The value is nil for a pipe, t or `pty' for a pty, or `stream' for\n\
+a socket connection.")
+  (process)
+     Lisp_Object process;
+{
+  return XPROCESS (process)->type;
+}
+#endif
+
+Lisp_Object
+list_processes_1 ()
+{
+  register Lisp_Object tail, tem;
+  Lisp_Object proc, minspace, tem1;
+  register struct Lisp_Process *p;
+  char tembuf[80];
+
+  XSETFASTINT (minspace, 1);
+
+  set_buffer_internal (XBUFFER (Vstandard_output));
+  Fbuffer_disable_undo (Vstandard_output);
+
+  current_buffer->truncate_lines = Qt;
+
+  write_string ("\
+Proc         Status   Buffer         Tty         Command\n\
+----         ------   ------         ---         -------\n", -1);
+
+  for (tail = Vprocess_alist; !NILP (tail); tail = Fcdr (tail))
+    {
+      Lisp_Object symbol;
+
+      proc = Fcdr (Fcar (tail));
+      p = XPROCESS (proc);
+      if (NILP (p->childp))
+	continue;
+
+      Finsert (1, &p->name);
+      Findent_to (make_number (13), minspace);
+
+      if (!NILP (p->raw_status_low))
+	update_status (p);
+      symbol = p->status;
+      if (CONSP (p->status))
+	symbol = XCAR (p->status);
+
+      
+      if (EQ (symbol, Qsignal))
+	{
+	  Lisp_Object tem;
+	  tem = Fcar (Fcdr (p->status));
+#ifdef VMS
+	  if (XINT (tem) < NSIG)
+	    write_string (sys_errlist [XINT (tem)], -1);
+	  else
+#endif
+	    Fprinc (symbol, Qnil);
+	}
+      else if (NETCONN_P (proc))
+	{
+	  if (EQ (symbol, Qrun))
+	    write_string ("open", -1);
+	  else if (EQ (symbol, Qexit))
+	    write_string ("closed", -1);
+	  else
+	    Fprinc (symbol, Qnil);
+	}
+      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))
+	remove_process (proc);
+
+      Findent_to (make_number (22), minspace);
+      if (NILP (p->buffer))
+	insert_string ("(none)");
+      else if (NILP (XBUFFER (p->buffer)->name))
+	insert_string ("(Killed)");
+      else
+	Finsert (1, &XBUFFER (p->buffer)->name);
+
+      Findent_to (make_number (37), minspace);
+
+      if (STRINGP (p->tty_name))
+	Finsert (1, &p->tty_name);
+      else
+	insert_string ("(none)");
+
+      Findent_to (make_number (49), minspace);
+
+      if (NETCONN_P (proc))
+        {
+	  sprintf (tembuf, "(network stream connection to %s)\n",
+		   XSTRING (XCAR (p->childp))->data);
+	  insert_string (tembuf);
+        }
+      else 
+	{
+	  tem = p->command;
+	  while (1)
+	    {
+	      tem1 = Fcar (tem);
+	      Finsert (1, &tem1);
+	      tem = Fcdr (tem);
+	      if (NILP (tem))
+		break;
+	      insert_string (" ");
+	    }
+	  insert_string ("\n");
+       }
+    }
+  return Qnil;
+}
+
+DEFUN ("list-processes", Flist_processes, Slist_processes, 0, 0, "",
+  "Display a list of all processes.\n\
+Any process listed as exited or signaled is actually eliminated\n\
+after the listing is made.")
+  ()
+{
+  internal_with_output_to_temp_buffer ("*Process List*",
+				       list_processes_1, Qnil);
+  return Qnil;
+}
+
+DEFUN ("process-list", Fprocess_list, Sprocess_list, 0, 0, 0,
+  "Return a list of all processes.")
+  ()
+{
+  return Fmapcar (Qcdr, Vprocess_alist);
+}
+
+/* Starting asynchronous inferior processes.  */
+
+static Lisp_Object start_process_unwind ();
+
+DEFUN ("start-process", Fstart_process, Sstart_process, 3, MANY, 0,
+  "Start a program in a subprocess.  Return the process object for it.\n\
+NAME is name for process.  It is modified if necessary to make it unique.\n\
+BUFFER is the buffer or (buffer-name) to associate with the process.\n\
+ Process output goes at end of that buffer, unless you specify\n\
+ an output stream or filter function to handle the output.\n\
+ BUFFER may be also nil, meaning that this process is not associated\n\
+ with any buffer.\n\
+Third arg is program file name.  It is searched for in PATH.\n\
+Remaining arguments are strings to give program as arguments.")
+  (nargs, args)
+     int nargs;
+     register Lisp_Object *args;
+{
+  Lisp_Object buffer, name, program, proc, current_dir, tem;
+#ifdef VMS
+  register unsigned char *new_argv;
+  int len;
+#else
+  register unsigned char **new_argv;
+#endif
+  register int i;
+  int count = specpdl_ptr - specpdl;
+
+  buffer = args[1];
+  if (!NILP (buffer))
+    buffer = Fget_buffer_create (buffer);
+
+  /* Make sure that the child will be able to chdir to the current
+     buffer's current directory, or its unhandled equivalent.  We
+     can't just have the child check for an error when it does the
+     chdir, since it's in a vfork.
+
+     We have to GCPRO around this because Fexpand_file_name and
+     Funhandled_file_name_directory might call a file name handling
+     function.  The argument list is protected by the caller, so all
+     we really have to worry about is buffer.  */
+  {
+    struct gcpro gcpro1, gcpro2;
+
+    current_dir = current_buffer->directory;
+
+    GCPRO2 (buffer, current_dir);
+
+    current_dir 
+      = expand_and_dir_to_file (Funhandled_file_name_directory (current_dir),
+				Qnil);
+    if (NILP (Ffile_accessible_directory_p (current_dir)))
+      report_file_error ("Setting current directory",
+			 Fcons (current_buffer->directory, Qnil));
+
+    UNGCPRO;
+  }
+
+  name = args[0];
+  CHECK_STRING (name, 0);
+
+  program = args[2];
+
+  CHECK_STRING (program, 2);
+
+#ifdef VMS
+  /* Make a one member argv with all args concatenated
+     together separated by a blank.  */
+  len = STRING_BYTES (XSTRING (program)) + 2;
+  for (i = 3; i < nargs; i++)
+    {
+      tem = args[i];
+      CHECK_STRING (tem, i);
+      len += STRING_BYTES (XSTRING (tem)) + 1;	/* count the blank */
+    }
+  new_argv = (unsigned char *) alloca (len);
+  strcpy (new_argv, XSTRING (program)->data);
+  for (i = 3; i < nargs; i++)
+    {
+      tem = args[i];
+      CHECK_STRING (tem, i);
+      strcat (new_argv, " ");
+      strcat (new_argv, XSTRING (tem)->data);
+    }
+  /* Need to add code here to check for program existence on VMS */
+  
+#else /* not VMS */
+  new_argv = (unsigned char **) alloca ((nargs - 1) * sizeof (char *));
+
+  /* If program file name is not absolute, search our path for it */
+  if (!IS_DIRECTORY_SEP (XSTRING (program)->data[0])
+      && !(XSTRING (program)->size > 1
+	   && IS_DEVICE_SEP (XSTRING (program)->data[1])))
+    {
+      struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+
+      tem = Qnil;
+      GCPRO4 (name, program, buffer, current_dir);
+      openp (Vexec_path, program, EXEC_SUFFIXES, &tem, 1);
+      UNGCPRO;
+      if (NILP (tem))
+	report_file_error ("Searching for program", Fcons (program, Qnil));
+      tem = Fexpand_file_name (tem, Qnil);
+      new_argv[0] = XSTRING (tem)->data;
+    }
+  else
+    {
+      if (!NILP (Ffile_directory_p (program)))
+	error ("Specified program for new process is a directory");
+
+      new_argv[0] = XSTRING (program)->data;
+    }
+
+  for (i = 3; i < nargs; i++)
+    {
+      tem = args[i];
+      CHECK_STRING (tem, i);
+      new_argv[i - 2] = XSTRING (tem)->data;
+    }
+  new_argv[i - 2] = 0;
+#endif /* not VMS */
+
+  proc = make_process (name);
+  /* If an error occurs and we can't start the process, we want to
+     remove it from the process list.  This means that each error
+     check in create_process doesn't need to call remove_process
+     itself; it's all taken care of here.  */
+  record_unwind_protect (start_process_unwind, proc);
+
+  XPROCESS (proc)->childp = Qt;
+  XPROCESS (proc)->command_channel_p = Qnil;
+  XPROCESS (proc)->buffer = buffer;
+  XPROCESS (proc)->sentinel = Qnil;
+  XPROCESS (proc)->filter = Qnil;
+  XPROCESS (proc)->command = Flist (nargs - 2, args + 2);
+
+  /* Make the process marker point into the process buffer (if any).  */
+  if (!NILP (buffer))
+    set_marker_both (XPROCESS (proc)->mark, buffer,
+		     BUF_ZV (XBUFFER (buffer)),
+		     BUF_ZV_BYTE (XBUFFER (buffer)));
+
+  {
+    /* Decide coding systems for communicating with the process.  Here
+       we don't setup the structure coding_system nor pay attention to
+       unibyte mode.  They are done in create_process.  */
+
+    /* Qt denotes we have not yet called Ffind_operation_coding_system.  */
+    Lisp_Object coding_systems = Qt;
+    Lisp_Object val, *args2;
+    struct gcpro gcpro1;
+
+    val = Vcoding_system_for_read;
+    if (NILP (val))
+      {
+	args2 = (Lisp_Object *) alloca ((nargs + 1) * sizeof *args2);
+	args2[0] = Qstart_process;
+	for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
+	GCPRO1 (proc);
+	coding_systems = Ffind_operation_coding_system (nargs + 1, args2);
+	UNGCPRO;
+	if (CONSP (coding_systems))
+	  val = XCAR (coding_systems);
+	else if (CONSP (Vdefault_process_coding_system))
+	  val = XCAR (Vdefault_process_coding_system);
+      }
+    XPROCESS (proc)->decode_coding_system = val;
+
+    val = Vcoding_system_for_write;
+    if (NILP (val))
+      {
+	if (EQ (coding_systems, Qt))
+	  {
+	    args2 = (Lisp_Object *) alloca ((nargs + 1) * sizeof args2);
+	    args2[0] = Qstart_process;
+	    for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
+	    GCPRO1 (proc);
+	    coding_systems = Ffind_operation_coding_system (nargs + 1, args2);
+	    UNGCPRO;
+	  }
+	if (CONSP (coding_systems))
+	  val = XCDR (coding_systems);
+	else if (CONSP (Vdefault_process_coding_system))
+	  val = XCDR (Vdefault_process_coding_system);
+      }
+    XPROCESS (proc)->encode_coding_system = val;
+  }
+
+  XPROCESS (proc)->decoding_buf = make_uninit_string (0);
+  XPROCESS (proc)->decoding_carryover = make_number (0);
+  XPROCESS (proc)->encoding_buf = make_uninit_string (0);
+  XPROCESS (proc)->encoding_carryover = make_number (0);
+
+  XPROCESS (proc)->inherit_coding_system_flag
+    = (NILP (buffer) || !inherit_process_coding_system
+       ? Qnil : Qt);
+
+  create_process (proc, (char **) new_argv, current_dir);
+
+  return unbind_to (count, proc);
+}
+
+/* This function is the unwind_protect form for Fstart_process.  If
+   PROC doesn't have its pid set, then we know someone has signaled
+   an error and the process wasn't started successfully, so we should
+   remove it from the process list.  */
+static Lisp_Object
+start_process_unwind (proc)
+     Lisp_Object proc;
+{
+  if (!PROCESSP (proc))
+    abort ();
+
+  /* Was PROC started successfully?  */
+  if (XINT (XPROCESS (proc)->pid) <= 0)
+    remove_process (proc);
+
+  return Qnil;
+}
+
+void
+create_process_1 (timer)
+     struct atimer *timer;
+{
+  /* Nothing to do.  */
+}
+
+
+#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
+
+#ifndef VMS /* VMS version of this function is in vmsproc.c.  */
+void
+create_process (process, new_argv, current_dir)
+     Lisp_Object process;
+     char **new_argv;
+     Lisp_Object current_dir;
+{
+  int pid, inchannel, outchannel;
+  int sv[2];
+#ifdef POSIX_SIGNALS
+  sigset_t procmask;
+  sigset_t blocked;
+  struct sigaction sigint_action;
+  struct sigaction sigquit_action;
+#ifdef AIX
+  struct sigaction sighup_action;
+#endif
+#else /* !POSIX_SIGNALS */
+#if 0
+#ifdef SIGCHLD
+  SIGTYPE (*sigchld)();
+#endif
+#endif /* 0 */
+#endif /* !POSIX_SIGNALS */
+  /* Use volatile to protect variables from being clobbered by longjmp.  */
+  volatile int forkin, forkout;
+  volatile int pty_flag = 0;
+  extern char **environ;
+  Lisp_Object buffer = XPROCESS (process)->buffer;
+
+  inchannel = outchannel = -1;
+
+#ifdef HAVE_PTYS
+  if (!NILP (Vprocess_connection_type))
+    outchannel = inchannel = allocate_pty ();
+
+  if (inchannel >= 0)
+    {
+#ifndef USG 
+      /* On USG systems it does not work to open the pty's tty here
+	       and then close and reopen it in the child.  */
+#ifdef O_NOCTTY
+      /* Don't let this terminal become our controlling terminal
+	 (in case we don't have one).  */
+      forkout = forkin = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0);
+#else
+      forkout = forkin = emacs_open (pty_name, O_RDWR, 0);
+#endif
+      if (forkin < 0)
+	report_file_error ("Opening pty", Qnil);
+#else
+      forkin = forkout = -1;
+#endif /* not USG */
+      pty_flag = 1;
+    }
+  else
+#endif /* HAVE_PTYS */
+#ifdef SKTPAIR
+    {
+      if (socketpair (AF_UNIX, SOCK_STREAM, 0, sv) < 0)
+	report_file_error ("Opening socketpair", Qnil);
+      outchannel = inchannel = sv[0];
+      forkout = forkin = sv[1];
+    }
+#else /* not SKTPAIR */
+    {
+      int tem;
+      tem = pipe (sv);
+      if (tem < 0)
+	report_file_error ("Creating pipe", Qnil);
+      inchannel = sv[0];
+      forkout = sv[1];
+      tem = pipe (sv);
+      if (tem < 0)
+	{
+	  emacs_close (inchannel);
+	  emacs_close (forkout);
+	  report_file_error ("Creating pipe", Qnil);
+	}
+      outchannel = sv[1];
+      forkin = sv[0];
+    }
+#endif /* not SKTPAIR */
+
+#if 0
+  /* Replaced by close_process_descs */
+  set_exclusive_use (inchannel);
+  set_exclusive_use (outchannel);
+#endif
+
+/* Stride people say it's a mystery why this is needed
+   as well as the O_NDELAY, but that it fails without this.  */
+#if defined (STRIDE) || (defined (pfa) && defined (HAVE_PTYS))
+  {
+    int one = 1;
+    ioctl (inchannel, FIONBIO, &one);
+  }
+#endif
+
+#ifdef O_NONBLOCK
+  fcntl (inchannel, F_SETFL, O_NONBLOCK);
+  fcntl (outchannel, F_SETFL, O_NONBLOCK);
+#else
+#ifdef O_NDELAY
+  fcntl (inchannel, F_SETFL, O_NDELAY);
+  fcntl (outchannel, F_SETFL, O_NDELAY);
+#endif
+#endif
+
+  /* Record this as an active process, with its channels.
+     As a result, child_setup will close Emacs's side of the pipes.  */
+  chan_process[inchannel] = process;
+  XSETINT (XPROCESS (process)->infd, inchannel);
+  XSETINT (XPROCESS (process)->outfd, outchannel);
+  /* Record the tty descriptor used in the subprocess.  */
+  if (forkin < 0)
+    XPROCESS (process)->subtty = Qnil;
+  else
+    XSETFASTINT (XPROCESS (process)->subtty, forkin);
+  XPROCESS (process)->pty_flag = (pty_flag ? Qt : Qnil);
+  XPROCESS (process)->status = Qrun;
+  if (!proc_decode_coding_system[inchannel])
+    proc_decode_coding_system[inchannel]
+      = (struct coding_system *) xmalloc (sizeof (struct coding_system));
+  setup_coding_system (XPROCESS (process)->decode_coding_system,
+		       proc_decode_coding_system[inchannel]);
+  if (!proc_encode_coding_system[outchannel])
+    proc_encode_coding_system[outchannel]
+      = (struct coding_system *) xmalloc (sizeof (struct coding_system));
+  setup_coding_system (XPROCESS (process)->encode_coding_system,
+		       proc_encode_coding_system[outchannel]);
+
+  if ((!NILP (buffer) && NILP (XBUFFER (buffer)->enable_multibyte_characters))
+      || (NILP (buffer) && NILP (buffer_defaults.enable_multibyte_characters)))
+    {
+      /* In unibyte mode, character code conversion should not take
+	 place but EOL conversion should.  So, setup raw-text or one
+	 of the subsidiary according to the information just setup.  */
+      if (!NILP (XPROCESS (process)->decode_coding_system))
+	setup_raw_text_coding_system (proc_decode_coding_system[inchannel]);
+      if (!NILP (XPROCESS (process)->encode_coding_system))
+	setup_raw_text_coding_system (proc_encode_coding_system[outchannel]);
+    }
+
+  if (CODING_REQUIRE_ENCODING (proc_encode_coding_system[outchannel]))
+    {
+      /* Here we encode arguments by the coding system used for
+	 sending data to the process.  We don't support using
+	 different coding systems for encoding arguments and for
+	 encoding data sent to the process.  */
+      struct gcpro gcpro1;
+      int i = 1;
+      struct coding_system *coding = proc_encode_coding_system[outchannel];
+
+      coding->mode |= CODING_MODE_LAST_BLOCK;
+      GCPRO1 (process);
+      while (new_argv[i] != 0)
+	{
+	  int len = strlen (new_argv[i]);
+	  int size = encoding_buffer_size (coding, len);
+	  unsigned char *buf = (unsigned char *) alloca (size);
+
+	  encode_coding (coding, (unsigned char *)new_argv[i], buf, len, size);
+	  buf[coding->produced] = 0;
+	  /* We don't have to free new_argv[i] because it points to a
+             Lisp string given as an argument to `start-process'.  */
+	  new_argv[i++] = (char *) buf;
+	}
+      UNGCPRO;
+      coding->mode &= ~CODING_MODE_LAST_BLOCK;
+    }
+
+  /* Delay interrupts until we have a chance to store
+     the new fork's pid in its process structure */
+#ifdef POSIX_SIGNALS
+  sigemptyset (&blocked);
+#ifdef SIGCHLD
+  sigaddset (&blocked, SIGCHLD);
+#endif
+#ifdef HAVE_VFORK
+  /* On many hosts (e.g. Solaris 2.4), if a vforked child calls `signal',
+     this sets the parent's signal handlers as well as the child's.
+     So delay all interrupts whose handlers the child might munge,
+     and record the current handlers so they can be restored later.  */
+  sigaddset (&blocked, SIGINT );  sigaction (SIGINT , 0, &sigint_action );
+  sigaddset (&blocked, SIGQUIT);  sigaction (SIGQUIT, 0, &sigquit_action);
+#ifdef AIX
+  sigaddset (&blocked, SIGHUP );  sigaction (SIGHUP , 0, &sighup_action );
+#endif
+#endif /* HAVE_VFORK */
+  sigprocmask (SIG_BLOCK, &blocked, &procmask);
+#else /* !POSIX_SIGNALS */
+#ifdef SIGCHLD
+#ifdef BSD4_1
+  sighold (SIGCHLD);
+#else /* not BSD4_1 */
+#if defined (BSD_SYSTEM) || defined (UNIPLUS) || defined (HPUX)
+  sigsetmask (sigmask (SIGCHLD));
+#else /* ordinary USG */
+#if 0
+  sigchld_deferred = 0;
+  sigchld = signal (SIGCHLD, create_process_sigchld);
+#endif
+#endif /* ordinary USG */
+#endif /* not BSD4_1 */
+#endif /* SIGCHLD */
+#endif /* !POSIX_SIGNALS */
+
+  FD_SET (inchannel, &input_wait_mask);
+  FD_SET (inchannel, &non_keyboard_wait_mask);
+  if (inchannel > max_process_desc)
+    max_process_desc = inchannel;
+
+  /* Until we store the proper pid, enable sigchld_handler
+     to recognize an unknown pid as standing for this process.
+     It is very important not to let this `marker' value stay
+     in the table after this function has returned; if it does
+     it might cause call-process to hang and subsequent asynchronous
+     processes to get their return values scrambled.  */
+  XSETINT (XPROCESS (process)->pid, -1);
+
+  BLOCK_INPUT;
+  
+  {
+    /* child_setup must clobber environ on systems with true vfork.
+       Protect it from permanent change.  */
+    char **save_environ = environ;
+
+    current_dir = ENCODE_FILE (current_dir);
+
+#ifndef WINDOWSNT
+    pid = vfork ();
+    if (pid == 0)
+#endif /* not WINDOWSNT */
+      {
+	int xforkin = forkin;
+	int xforkout = forkout;
+
+#if 0 /* This was probably a mistake--it duplicates code later on,
+	 but fails to handle all the cases.  */
+	/* Make sure SIGCHLD is not blocked in the child.  */
+	sigsetmask (SIGEMPTYMASK);
+#endif
+
+	/* Make the pty be the controlling terminal of the process.  */
+#ifdef HAVE_PTYS
+	/* First, disconnect its current controlling terminal.  */
+#ifdef HAVE_SETSID
+	/* We tried doing setsid only if pty_flag, but it caused
+	   process_set_signal to fail on SGI when using a pipe.  */
+	setsid ();
+	/* Make the pty's terminal the controlling terminal.  */
+	if (pty_flag)
+	  {
+#ifdef TIOCSCTTY
+	    /* We ignore the return value
+	       because faith@cs.unc.edu says that is necessary on Linux.  */
+	    ioctl (xforkin, TIOCSCTTY, 0);
+#endif
+	  }
+#else /* not HAVE_SETSID */
+#ifdef USG
+	/* It's very important to call setpgrp here and no time
+	   afterwards.  Otherwise, we lose our controlling tty which
+	   is set when we open the pty. */
+	setpgrp ();
+#endif /* USG */
+#endif /* not HAVE_SETSID */
+#if defined (HAVE_TERMIOS) && defined (LDISC1)
+	if (pty_flag && xforkin >= 0)
+	  {
+	    struct termios t;
+	    tcgetattr (xforkin, &t);
+	    t.c_lflag = LDISC1;
+	    if (tcsetattr (xforkin, TCSANOW, &t) < 0)
+	      emacs_write (1, "create_process/tcsetattr LDISC1 failed\n", 39);
+	  }
+#else
+#if defined (NTTYDISC) && defined (TIOCSETD)
+	if (pty_flag && xforkin >= 0)
+	  {
+	    /* Use new line discipline.  */
+	    int ldisc = NTTYDISC;
+	    ioctl (xforkin, TIOCSETD, &ldisc);
+	  }
+#endif
+#endif
+#ifdef TIOCNOTTY 
+	/* In 4.3BSD, the TIOCSPGRP bug has been fixed, and now you
+	   can do TIOCSPGRP only to the process's controlling tty.  */
+	if (pty_flag)
+	  {
+	    /* I wonder: would just ioctl (0, TIOCNOTTY, 0) work here? 
+	       I can't test it since I don't have 4.3.  */
+	    int j = emacs_open ("/dev/tty", O_RDWR, 0);
+	    ioctl (j, TIOCNOTTY, 0);
+	    emacs_close (j);
+#ifndef USG
+	    /* In order to get a controlling terminal on some versions
+	       of BSD, it is necessary to put the process in pgrp 0
+	       before it opens the terminal.  */
+#ifdef HAVE_SETPGID
+	    setpgid (0, 0);
+#else
+	    setpgrp (0, 0);
+#endif
+#endif
+	  }
+#endif /* TIOCNOTTY */
+
+#if !defined (RTU) && !defined (UNIPLUS) && !defined (DONT_REOPEN_PTY)
+/*** There is a suggestion that this ought to be a
+     conditional on TIOCSPGRP,
+     or !(defined (HAVE_SETSID) && defined (TIOCSCTTY)).
+     Trying the latter gave the wrong results on Debian GNU/Linux 1.1;
+     that system does seem to need this code, even though
+     both HAVE_SETSID and TIOCSCTTY are defined.  */
+	/* Now close the pty (if we had it open) and reopen it.
+	   This makes the pty the controlling terminal of the subprocess.  */
+	if (pty_flag)
+	  {
+#ifdef SET_CHILD_PTY_PGRP
+	    int pgrp = getpid ();
+#endif
+
+	    /* I wonder if emacs_close (emacs_open (pty_name, ...))
+	       would work?  */
+	    if (xforkin >= 0)
+	      emacs_close (xforkin);
+	    xforkout = xforkin = emacs_open (pty_name, O_RDWR, 0);
+
+	    if (xforkin < 0)
+	      {
+		emacs_write (1, "Couldn't open the pty terminal ", 31);
+		emacs_write (1, pty_name, strlen (pty_name));
+		emacs_write (1, "\n", 1);
+		_exit (1);
+	      }
+
+#ifdef SET_CHILD_PTY_PGRP
+	    ioctl (xforkin, TIOCSPGRP, &pgrp);
+	    ioctl (xforkout, TIOCSPGRP, &pgrp);
+#endif
+	  }
+#endif /* not UNIPLUS and not RTU and not DONT_REOPEN_PTY */
+
+#ifdef SETUP_SLAVE_PTY
+	if (pty_flag)
+	  {
+	    SETUP_SLAVE_PTY;
+	  }
+#endif /* SETUP_SLAVE_PTY */
+#ifdef AIX
+	/* On AIX, we've disabled SIGHUP above once we start a child on a pty.
+	   Now reenable it in the child, so it will die when we want it to.  */
+	if (pty_flag)
+	  signal (SIGHUP, SIG_DFL);
+#endif
+#endif /* HAVE_PTYS */
+
+	signal (SIGINT, SIG_DFL);
+	signal (SIGQUIT, SIG_DFL);
+
+	/* Stop blocking signals in the child.  */
+#ifdef POSIX_SIGNALS
+	sigprocmask (SIG_SETMASK, &procmask, 0);
+#else /* !POSIX_SIGNALS */
+#ifdef SIGCHLD
+#ifdef BSD4_1
+	sigrelse (SIGCHLD);
+#else /* not BSD4_1 */
+#if defined (BSD_SYSTEM) || defined (UNIPLUS) || defined (HPUX)
+	sigsetmask (SIGEMPTYMASK);
+#else /* ordinary USG */
+#if 0
+	signal (SIGCHLD, sigchld);
+#endif
+#endif /* ordinary USG */
+#endif /* not BSD4_1 */
+#endif /* SIGCHLD */
+#endif /* !POSIX_SIGNALS */
+
+	if (pty_flag)
+	  child_setup_tty (xforkout);
+#ifdef WINDOWSNT
+	pid = child_setup (xforkin, xforkout, xforkout,
+			   new_argv, 1, current_dir);
+#else  /* not WINDOWSNT */	
+	child_setup (xforkin, xforkout, xforkout,
+		     new_argv, 1, current_dir);
+#endif /* not WINDOWSNT */
+      }
+    environ = save_environ;
+  }
+
+  UNBLOCK_INPUT;
+
+  /* This runs in the Emacs process.  */
+  if (pid < 0)
+    {
+      if (forkin >= 0)
+	emacs_close (forkin);
+      if (forkin != forkout && forkout >= 0)
+	emacs_close (forkout);
+    }
+  else
+    {
+      /* vfork succeeded.  */
+      XSETFASTINT (XPROCESS (process)->pid, pid);
+
+#ifdef WINDOWSNT
+      register_child (pid, inchannel);
+#endif /* WINDOWSNT */
+
+      /* If the subfork execv fails, and it exits,
+	 this close hangs.  I don't know why.
+	 So have an interrupt jar it loose.  */
+      {
+	struct atimer *timer;
+	EMACS_TIME offset;
+	
+	stop_polling ();
+	EMACS_SET_SECS_USECS (offset, 1, 0);
+	timer = start_atimer (ATIMER_RELATIVE, offset, create_process_1, 0);
+	
+	XPROCESS (process)->subtty = Qnil;
+	if (forkin >= 0)
+	  emacs_close (forkin);
+
+	cancel_atimer (timer);
+	start_polling ();
+      }
+      
+      if (forkin != forkout && forkout >= 0)
+	emacs_close (forkout);
+
+#ifdef HAVE_PTYS
+      if (pty_flag)
+	XPROCESS (process)->tty_name = build_string (pty_name);
+      else
+#endif
+	XPROCESS (process)->tty_name = Qnil;
+    }
+
+  /* Restore the signal state whether vfork succeeded or not.
+     (We will signal an error, below, if it failed.)  */
+#ifdef POSIX_SIGNALS
+#ifdef HAVE_VFORK
+  /* Restore the parent's signal handlers.  */
+  sigaction (SIGINT, &sigint_action, 0);
+  sigaction (SIGQUIT, &sigquit_action, 0);
+#ifdef AIX
+  sigaction (SIGHUP, &sighup_action, 0);
+#endif
+#endif /* HAVE_VFORK */
+  /* Stop blocking signals in the parent.  */
+  sigprocmask (SIG_SETMASK, &procmask, 0);
+#else /* !POSIX_SIGNALS */
+#ifdef SIGCHLD
+#ifdef BSD4_1
+  sigrelse (SIGCHLD);
+#else /* not BSD4_1 */
+#if defined (BSD_SYSTEM) || defined (UNIPLUS) || defined (HPUX)
+  sigsetmask (SIGEMPTYMASK);
+#else /* ordinary USG */
+#if 0
+  signal (SIGCHLD, sigchld);
+  /* Now really handle any of these signals
+     that came in during this function.  */
+  if (sigchld_deferred)
+    kill (getpid (), SIGCHLD);
+#endif
+#endif /* ordinary USG */
+#endif /* not BSD4_1 */
+#endif /* SIGCHLD */
+#endif /* !POSIX_SIGNALS */
+
+  /* Now generate the error if vfork failed.  */
+  if (pid < 0)
+    report_file_error ("Doing vfork", Qnil);
+}
+#endif /* not VMS */
+
+#ifdef HAVE_SOCKETS
+
+/* open a TCP network connection to a given HOST/SERVICE.  Treated
+   exactly like a normal process when reading and writing.  Only
+   differences are in status display and process deletion.  A network
+   connection has no PID; you cannot signal it.  All you can do is
+   deactivate and close it via delete-process */
+
+DEFUN ("open-network-stream", Fopen_network_stream, Sopen_network_stream, 
+       4, 4, 0, 
+  "Open a TCP connection for a service to a host.\n\
+Returns a subprocess-object to represent the connection.\n\
+Input and output work as for subprocesses; `delete-process' closes it.\n\
+Args are NAME BUFFER HOST SERVICE.\n\
+NAME is name for process.  It is modified if necessary to make it unique.\n\
+BUFFER is the buffer (or buffer-name) to associate with the process.\n\
+ Process output goes at end of that buffer, unless you specify\n\
+ an output stream or filter function to handle the output.\n\
+ BUFFER may be also nil, meaning that this process is not associated\n\
+ with any buffer\n\
+Third arg is name of the host to connect to, or its IP address.\n\
+Fourth arg SERVICE is name of the service desired, or an integer\n\
+ specifying a port number to connect to.")
+   (name, buffer, host, service)
+      Lisp_Object name, buffer, host, service;
+{
+  Lisp_Object proc;
+#ifndef HAVE_GETADDRINFO
+  struct sockaddr_in address;
+  struct servent *svc_info;
+  struct hostent *host_info_ptr, host_info;
+  char *(addr_list[2]);
+  IN_ADDR numeric_addr;
+  int port;
+#else /* HAVE_GETADDRINFO */
+  struct addrinfo hints, *res, *lres;
+  int ret = 0;
+  int xerrno = 0;
+  char *portstring, portbuf[128];
+#endif /* HAVE_GETADDRINFO */
+  int s = -1, outch, inch;
+  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+  int retry = 0;
+  int count = specpdl_ptr - specpdl;
+  int count1;
+
+#ifdef WINDOWSNT
+  /* Ensure socket support is loaded if available. */
+  init_winsock (TRUE);
+#endif
+
+  GCPRO4 (name, buffer, host, service);
+  CHECK_STRING (name, 0);
+  CHECK_STRING (host, 0);
+
+#ifdef HAVE_GETADDRINFO
+  /*
+   * SERVICE can either be a string or int.
+   * Convert to a C string for later use by getaddrinfo.
+   */
+  if (INTEGERP (service))
+    {
+      sprintf (portbuf, "%d", XINT (service));
+      portstring = portbuf;
+    }
+  else
+    {
+      CHECK_STRING (service, 0);
+      portstring = XSTRING (service)->data;
+    }
+#else /* ! HAVE_GETADDRINFO */
+  if (INTEGERP (service))
+    port = htons ((unsigned short) XINT (service));
+  else
+    {
+      CHECK_STRING (service, 0);
+      svc_info = getservbyname (XSTRING (service)->data, "tcp");
+      if (svc_info == 0)
+	error ("Unknown service \"%s\"", XSTRING (service)->data);
+      port = svc_info->s_port;
+    }
+#endif /* ! HAVE_GETADDRINFO */
+
+
+  /* Slow down polling to every ten seconds.
+     Some kernels have a bug which causes retrying connect to fail
+     after a connect.  Polling can interfere with gethostbyname too.  */
+#ifdef POLL_FOR_INPUT
+  bind_polling_period (10);
+#endif
+
+#ifndef TERM
+#ifdef HAVE_GETADDRINFO
+  {
+    immediate_quit = 1;
+    QUIT;
+    memset (&hints, 0, sizeof (hints));
+    hints.ai_flags = 0;
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_protocol = 0;
+    ret = getaddrinfo (XSTRING (host)->data, portstring, &hints, &res);
+    if (ret)
+      {
+	error ("%s/%s %s", XSTRING (host)->data, portstring,
+	       strerror (ret));
+      }
+    immediate_quit = 0;
+  }
+
+  s = -1;
+  count1 = specpdl_ptr - specpdl;
+  record_unwind_protect (close_file_unwind, make_number (s));
+
+  for (lres = res; lres; lres = lres->ai_next)
+    {
+      s = socket (lres->ai_family, lres->ai_socktype, lres->ai_protocol);
+      if (s < 0) 
+	continue;
+
+      /* Kernel bugs (on Ultrix at least) cause lossage (not just EINTR)
+	 when connect is interrupted.  So let's not let it get interrupted.
+	 Note we do not turn off polling, because polling is only used
+	 when not interrupt_input, and thus not normally used on the systems
+	 which have this bug.  On systems which use polling, there's no way
+	 to quit if polling is turned off.  */
+      if (interrupt_input)
+	unrequest_sigio ();
+
+      immediate_quit = 1;
+      QUIT;
+
+      ret = connect (s, lres->ai_addr, lres->ai_addrlen);
+      if (ret == 0)
+	break;
+      emacs_close (s);
+      s = -1;
+    }
+
+  freeaddrinfo (res);
+  if (s < 0)
+    {
+      if (interrupt_input)
+	request_sigio ();
+
+      errno = xerrno;
+      report_file_error ("connection failed",
+			 Fcons (host, Fcons (name, Qnil)));
+    }
+#else /* ! HAVE_GETADDRINFO */
+
+  while (1)
+    {
+#if 0
+#ifdef TRY_AGAIN
+      h_errno = 0;
+#endif
+#endif
+      immediate_quit = 1;
+      QUIT;
+      host_info_ptr = gethostbyname (XSTRING (host)->data);
+      immediate_quit = 0;
+#if 0
+#ifdef TRY_AGAIN
+      if (! (host_info_ptr == 0 && h_errno == TRY_AGAIN))
+#endif
+#endif
+	break;
+      Fsleep_for (make_number (1), Qnil);
+    }
+  if (host_info_ptr == 0)
+    /* Attempt to interpret host as numeric inet address */
+    {
+      numeric_addr = inet_addr ((char *) XSTRING (host)->data);
+      if (NUMERIC_ADDR_ERROR)
+	error ("Unknown host \"%s\"", XSTRING (host)->data);
+
+      host_info_ptr = &host_info;
+      host_info.h_name = 0;
+      host_info.h_aliases = 0;
+      host_info.h_addrtype = AF_INET;
+#ifdef h_addr
+      /* Older machines have only one address slot called h_addr.
+	 Newer machines have h_addr_list, but #define h_addr to
+	 be its first element.  */
+      host_info.h_addr_list = &(addr_list[0]);
+#endif
+      host_info.h_addr = (char*)(&numeric_addr);
+      addr_list[1] = 0;
+      /* numeric_addr isn't null-terminated; it has fixed length.  */
+      host_info.h_length = sizeof (numeric_addr);
+    }
+
+  bzero (&address, sizeof address);
+  bcopy (host_info_ptr->h_addr, (char *) &address.sin_addr,
+	 host_info_ptr->h_length);
+  address.sin_family = host_info_ptr->h_addrtype;
+  address.sin_port = port;
+
+  s = socket (host_info_ptr->h_addrtype, SOCK_STREAM, 0);
+  if (s < 0) 
+    report_file_error ("error creating socket", Fcons (name, Qnil));
+
+  count1 = specpdl_ptr - specpdl;
+  record_unwind_protect (close_file_unwind, make_number (s));
+
+  /* Kernel bugs (on Ultrix at least) cause lossage (not just EINTR)
+     when connect is interrupted.  So let's not let it get interrupted.
+     Note we do not turn off polling, because polling is only used
+     when not interrupt_input, and thus not normally used on the systems
+     which have this bug.  On systems which use polling, there's no way
+     to quit if polling is turned off.  */
+  if (interrupt_input)
+    unrequest_sigio ();
+
+ loop:
+
+  immediate_quit = 1;
+  QUIT;
+
+  if (connect (s, (struct sockaddr *) &address, sizeof address) == -1
+      && errno != EISCONN)
+    {
+      int xerrno = errno;
+
+      immediate_quit = 0;
+
+      if (errno == EINTR)
+	goto loop;
+      if (errno == EADDRINUSE && retry < 20)
+	{
+	  /* A delay here is needed on some FreeBSD systems,
+	     and it is harmless, since this retrying takes time anyway
+	     and should be infrequent.  */
+	  Fsleep_for (make_number (1), Qnil);
+	  retry++;
+	  goto loop;
+	}
+
+      /* Discard the unwind protect.  */
+      specpdl_ptr = specpdl + count1;
+
+      emacs_close (s);
+
+      if (interrupt_input)
+	request_sigio ();
+
+      errno = xerrno;
+      report_file_error ("connection failed",
+			 Fcons (host, Fcons (name, Qnil)));
+    }
+#endif /* ! HAVE_GETADDRINFO */
+
+  immediate_quit = 0;
+
+  /* Discard the unwind protect.  */
+  specpdl_ptr = specpdl + count1;
+
+#ifdef POLL_FOR_INPUT
+  unbind_to (count, Qnil);
+#endif
+
+  if (interrupt_input)
+    request_sigio ();
+
+#else /* TERM */
+  s = connect_server (0);
+  if (s < 0)
+    report_file_error ("error creating socket", Fcons (name, Qnil));
+  send_command (s, C_PORT, 0, "%s:%d", XSTRING (host)->data, ntohs (port));
+  send_command (s, C_DUMB, 1, 0);
+#endif /* TERM */
+
+  inch = s;
+  outch = s;
+
+  if (!NILP (buffer))
+    buffer = Fget_buffer_create (buffer);
+  proc = make_process (name);
+
+  chan_process[inch] = proc;
+
+#ifdef O_NONBLOCK
+  fcntl (inch, F_SETFL, O_NONBLOCK);
+#else
+#ifdef O_NDELAY
+  fcntl (inch, F_SETFL, O_NDELAY);
+#endif
+#endif
+
+  XPROCESS (proc)->childp = Fcons (host, Fcons (service, Qnil));
+  XPROCESS (proc)->command_channel_p = Qnil;
+  XPROCESS (proc)->buffer = buffer;
+  XPROCESS (proc)->sentinel = Qnil;
+  XPROCESS (proc)->filter = Qnil;
+  XPROCESS (proc)->command = Qnil;
+  XPROCESS (proc)->pid = Qnil;
+  XSETINT (XPROCESS (proc)->infd, inch);
+  XSETINT (XPROCESS (proc)->outfd, outch);
+  XPROCESS (proc)->status = Qrun;
+  FD_SET (inch, &input_wait_mask);
+  FD_SET (inch, &non_keyboard_wait_mask);
+  if (inch > max_process_desc)
+    max_process_desc = inch;
+
+  {
+    /* Setup coding systems for communicating with the network stream.  */
+    struct gcpro gcpro1;
+    /* Qt denotes we have not yet called Ffind_operation_coding_system.  */
+    Lisp_Object coding_systems = Qt;
+    Lisp_Object args[5], val;
+
+    if (!NILP (Vcoding_system_for_read))
+      val = Vcoding_system_for_read;
+    else if ((!NILP (buffer) && NILP (XBUFFER (buffer)->enable_multibyte_characters))
+	     || (NILP (buffer) && NILP (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
+	 CR LF.  */
+      val = Qnil;
+    else
+      {
+	args[0] = Qopen_network_stream, args[1] = name,
+	  args[2] = buffer, args[3] = host, args[4] = service;
+	GCPRO1 (proc);
+	coding_systems = Ffind_operation_coding_system (5, args);
+	UNGCPRO;
+	if (CONSP (coding_systems))
+	  val = XCAR (coding_systems);
+	else if (CONSP (Vdefault_process_coding_system))
+	  val = XCAR (Vdefault_process_coding_system);
+	else
+	  val = Qnil;
+      }
+    XPROCESS (proc)->decode_coding_system = val;
+
+    if (!NILP (Vcoding_system_for_write))
+      val = Vcoding_system_for_write;
+    else if (NILP (current_buffer->enable_multibyte_characters))
+      val = Qnil;
+    else
+      {
+	if (EQ (coding_systems, Qt))
+	  {
+	    args[0] = Qopen_network_stream, args[1] = name,
+	      args[2] = buffer, args[3] = host, args[4] = service;
+	    GCPRO1 (proc);
+	    coding_systems = Ffind_operation_coding_system (5, args);
+	    UNGCPRO;
+	  }
+	if (CONSP (coding_systems))
+	  val = XCDR (coding_systems);
+	else if (CONSP (Vdefault_process_coding_system))
+	  val = XCDR (Vdefault_process_coding_system);
+	else
+	  val = Qnil;
+      }
+    XPROCESS (proc)->encode_coding_system = val;
+  }
+
+  if (!proc_decode_coding_system[inch])
+    proc_decode_coding_system[inch]
+      = (struct coding_system *) xmalloc (sizeof (struct coding_system));
+  setup_coding_system (XPROCESS (proc)->decode_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 (XPROCESS (proc)->encode_coding_system,
+		       proc_encode_coding_system[outch]);
+
+  XPROCESS (proc)->decoding_buf = make_uninit_string (0);
+  XPROCESS (proc)->decoding_carryover = make_number (0);
+  XPROCESS (proc)->encoding_buf = make_uninit_string (0);
+  XPROCESS (proc)->encoding_carryover = make_number (0);
+
+  XPROCESS (proc)->inherit_coding_system_flag
+    = (NILP (buffer) || !inherit_process_coding_system
+       ? Qnil : Qt);
+
+  UNGCPRO;
+  return proc;
+}
+#endif	/* HAVE_SOCKETS */
+
+void
+deactivate_process (proc)
+     Lisp_Object proc;
+{
+  register int inchannel, outchannel;
+  register struct Lisp_Process *p = XPROCESS (proc);
+
+  inchannel = XINT (p->infd);
+  outchannel = XINT (p->outfd);
+
+  if (inchannel >= 0)
+    {
+      /* Beware SIGCHLD hereabouts. */
+      flush_pending_output (inchannel);
+#ifdef VMS
+      {
+	VMS_PROC_STUFF *get_vms_process_pointer (), *vs;
+	sys$dassgn (outchannel);
+	vs = get_vms_process_pointer (p->pid);
+	if (vs)
+	  give_back_vms_process_stuff (vs);
+      }
+#else
+      emacs_close (inchannel);
+      if (outchannel >= 0 && outchannel != inchannel)
+ 	emacs_close (outchannel);
+#endif
+
+      XSETINT (p->infd, -1);
+      XSETINT (p->outfd, -1);
+      chan_process[inchannel] = Qnil;
+      FD_CLR (inchannel, &input_wait_mask);
+      FD_CLR (inchannel, &non_keyboard_wait_mask);
+      if (inchannel == max_process_desc)
+	{
+	  int i;
+	  /* We just closed the highest-numbered process input descriptor,
+	     so recompute the highest-numbered one now.  */
+	  max_process_desc = 0;
+	  for (i = 0; i < MAXDESC; i++)
+	    if (!NILP (chan_process[i]))
+	      max_process_desc = i;
+	}
+    }
+}
+
+/* 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 ()
+{
+#ifndef WINDOWSNT
+  int i;
+  for (i = 0; i < MAXDESC; i++)
+    {
+      Lisp_Object process;
+      process = chan_process[i];
+      if (!NILP (process))
+	{
+	  int in = XINT (XPROCESS (process)->infd);
+	  int out = XINT (XPROCESS (process)->outfd);
+	  if (in >= 0)
+	    emacs_close (in);
+	  if (out >= 0 && in != out)
+	    emacs_close (out);
+	}
+    }
+#endif
+}
+
+DEFUN ("accept-process-output", Faccept_process_output, Saccept_process_output,
+  0, 3, 0,
+  "Allow any pending output from subprocesses to be read by Emacs.\n\
+It is read into the process' buffers or given to their filter functions.\n\
+Non-nil arg PROCESS means do not return until some output has been received\n\
+from PROCESS.\n\
+Non-nil second arg TIMEOUT and third arg TIMEOUT-MSECS are number of\n\
+seconds and microseconds to wait; return after that much time whether\n\
+or not there is input.\n\
+Return non-nil iff we received any output before the timeout expired.")
+  (process, timeout, timeout_msecs)
+     register Lisp_Object process, timeout, timeout_msecs;
+{
+  int seconds;
+  int useconds;
+
+  if (! NILP (process))
+    CHECK_PROCESS (process, 0);
+
+  if (! NILP (timeout_msecs))
+    {
+      CHECK_NUMBER (timeout_msecs, 2);
+      useconds = XINT (timeout_msecs);
+      if (!INTEGERP (timeout))
+	XSETINT (timeout, 0);
+
+      {
+	int carry = useconds / 1000000;
+
+	XSETINT (timeout, XINT (timeout) + carry);
+	useconds -= carry * 1000000;
+
+	/* I think this clause is necessary because C doesn't
+	   guarantee a particular rounding direction for negative
+	   integers.  */
+	if (useconds < 0)
+	  {
+	    XSETINT (timeout, XINT (timeout) - 1);
+	    useconds += 1000000;
+	  }
+      }
+    }
+  else
+    useconds = 0;
+
+  if (! NILP (timeout))
+    {
+      CHECK_NUMBER (timeout, 1);
+      seconds = XINT (timeout);
+      if (seconds < 0 || (seconds == 0 && useconds == 0))
+	seconds = -1;
+    }
+  else
+    {
+      if (NILP (process))
+	seconds = -1;
+      else
+	seconds = 0;
+    }
+
+  if (NILP (process))
+    XSETFASTINT (process, 0);
+
+  return
+    (wait_reading_process_input (seconds, useconds, process, 0)
+     ? Qt : Qnil);
+}
+
+/* This variable is different from waiting_for_input in keyboard.c.
+   It is used to communicate to a lisp process-filter/sentinel (via the
+   function Fwaiting_for_user_input_p below) whether emacs was waiting
+   for user-input when that process-filter was called.
+   waiting_for_input cannot be used as that is by definition 0 when
+   lisp code is being evalled.
+   This is also used in record_asynch_buffer_change.
+   For that purpose, this must be 0
+   when not inside wait_reading_process_input.  */
+static int waiting_for_user_input_p;
+
+/* This is here so breakpoints can be put on it.  */
+static void
+wait_reading_process_input_1 ()
+{
+}
+
+/* Read and dispose of subprocess output while waiting for timeout to
+   elapse and/or keyboard input to be available.
+
+   TIME_LIMIT is:
+     timeout in seconds, or
+     zero for no limit, or
+     -1 means gobble data immediately available but don't wait for any.
+
+   MICROSECS is:
+     an additional duration to wait, measured in microseconds.
+     If this is nonzero and time_limit is 0, then the timeout
+     consists of MICROSECS only.
+
+   READ_KBD is a lisp value:
+     0 to ignore keyboard input, or
+     1 to return when input is available, or
+     -1 meaning caller will actually read the input, so don't throw to
+       the quit handler, or
+     a cons cell, meaning wait until its car is non-nil
+       (and gobble terminal input into the buffer if any arrives), or
+     a process object, meaning wait until something arrives from that
+       process.  The return value is true iff we read some input from
+       that process.
+
+   DO_DISPLAY != 0 means redisplay should be done to show subprocess
+   output that arrives.
+
+   If READ_KBD is a pointer to a struct Lisp_Process, then the
+     function returns true iff we received input from that process
+     before the timeout elapsed.
+   Otherwise, return true iff we received input from any process.  */
+
+int
+wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
+     int time_limit, microsecs;
+     Lisp_Object read_kbd;
+     int do_display;
+{
+  register int channel, nfds;
+  static SELECT_TYPE Available;
+  int xerrno;
+  Lisp_Object proc;
+  EMACS_TIME timeout, end_time;
+  SELECT_TYPE Atemp;
+  int wait_channel = -1;
+  struct Lisp_Process *wait_proc = 0;
+  int got_some_input = 0;
+  Lisp_Object *wait_for_cell = 0;
+
+  FD_ZERO (&Available);
+
+  /* If read_kbd is a process to watch, set wait_proc and wait_channel
+     accordingly.  */
+  if (PROCESSP (read_kbd))
+    {
+      wait_proc = XPROCESS (read_kbd);
+      wait_channel = XINT (wait_proc->infd);
+      XSETFASTINT (read_kbd, 0);
+    }
+
+  /* If waiting for non-nil in a cell, record where.  */
+  if (CONSP (read_kbd))
+    {
+      wait_for_cell = &XCAR (read_kbd);
+      XSETFASTINT (read_kbd, 0);
+    }
+
+  waiting_for_user_input_p = XINT (read_kbd);
+
+  /* Since we may need to wait several times,
+     compute the absolute time to return at.  */
+  if (time_limit || microsecs)
+    {
+      EMACS_GET_TIME (end_time);
+      EMACS_SET_SECS_USECS (timeout, time_limit, microsecs);
+      EMACS_ADD_TIME (end_time, end_time, timeout);
+    }
+#ifdef hpux
+  /* AlainF 5-Jul-1996
+     HP-UX 10.10 seem to have problems with signals coming in
+     Causes "poll: interrupted system call" messages when Emacs is run
+     in an X window
+     Turn off periodic alarms (in case they are in use) */
+  turn_on_atimers (0);
+#endif
+
+  while (1)
+    {
+      int timeout_reduced_for_timers = 0;
+
+#ifdef HAVE_X_WINDOWS
+      if (display_busy_cursor_p)
+	Fx_hide_busy_cursor (Qnil);
+#endif
+
+      /* If calling from keyboard input, do not quit
+	 since we want to return C-g as an input character.
+	 Otherwise, do pending quit if requested.  */
+      if (XINT (read_kbd) >= 0)
+	QUIT;
+
+      /* Exit now if the cell we're waiting for became non-nil.  */
+      if (wait_for_cell && ! NILP (*wait_for_cell))
+	break;
+
+      /* Compute time from now till when time limit is up */
+      /* Exit if already run out */
+      if (time_limit == -1)
+	{
+	  /* -1 specified for timeout means
+	     gobble output available now
+	     but don't wait at all. */
+
+	  EMACS_SET_SECS_USECS (timeout, 0, 0);
+	}
+      else if (time_limit || microsecs)
+	{
+	  EMACS_GET_TIME (timeout);
+	  EMACS_SUB_TIME (timeout, end_time, timeout);
+	  if (EMACS_TIME_NEG_P (timeout))
+	    break;
+	}
+      else
+	{
+	  EMACS_SET_SECS_USECS (timeout, 100000, 0);
+	}
+
+      /* Normally we run timers here.
+	 But not if wait_for_cell; in those cases,
+	 the wait is supposed to be short,
+	 and those callers cannot handle running arbitrary Lisp code here.  */
+      if (! wait_for_cell)
+	{
+	  EMACS_TIME timer_delay;
+	  int old_timers_run;
+
+	retry:
+	  old_timers_run = timers_run;
+	  timer_delay = timer_check (1);
+	  if (timers_run != old_timers_run && do_display)
+	    {
+	      redisplay_preserve_echo_area ();
+	      /* We must retry, since a timer may have requeued itself
+		 and that could alter the time_delay.  */
+	      goto retry;
+	    }
+
+	  /* If there is unread keyboard input, also return.  */
+	  if (XINT (read_kbd) != 0
+	      && requeued_events_pending_p ())
+	    break;
+
+	  if (! EMACS_TIME_NEG_P (timer_delay) && time_limit != -1)
+	    {
+	      EMACS_TIME difference;
+	      EMACS_SUB_TIME (difference, timer_delay, timeout);
+	      if (EMACS_TIME_NEG_P (difference))
+		{
+		  timeout = timer_delay;
+		  timeout_reduced_for_timers = 1;
+		}
+	    }
+	  /* If time_limit is -1, we are not going to wait at all.  */
+	  else if (time_limit != -1)
+	    {
+	      /* This is so a breakpoint can be put here.  */
+	      wait_reading_process_input_1 ();
+	    }
+	}
+
+      /* Cause C-g and alarm signals to take immediate action,
+	 and cause input available signals to zero out timeout.
+
+	 It is important that we do this before checking for process
+	 activity.  If we get a SIGCHLD after the explicit checks for
+	 process activity, timeout is the only way we will know.  */
+      if (XINT (read_kbd) < 0)
+	set_waiting_for_input (&timeout);
+
+      /* If status of something has changed, and no input is
+	 available, notify the user of the change right away.  After
+	 this explicit check, we'll let the SIGCHLD handler zap
+	 timeout to get our attention.  */
+      if (update_tick != process_tick && do_display)
+	{
+	  Atemp = input_wait_mask;
+	  EMACS_SET_SECS_USECS (timeout, 0, 0);
+	  if ((select (max (max_process_desc, max_keyboard_desc) + 1,
+		       &Atemp, (SELECT_TYPE *)0, (SELECT_TYPE *)0,
+		       &timeout)
+	       <= 0))
+	    {
+	      /* It's okay for us to do this and then continue with
+		 the loop, since timeout has already been zeroed out.  */
+	      clear_waiting_for_input ();
+	      status_notify ();
+	    }
+	}
+
+      /* Don't wait for output from a non-running process.  */
+      if (wait_proc != 0 && !NILP (wait_proc->raw_status_low))
+	update_status (wait_proc);
+      if (wait_proc != 0
+	  && ! EQ (wait_proc->status, Qrun))
+	{
+	  int nread, total_nread = 0;
+
+	  clear_waiting_for_input ();
+	  XSETPROCESS (proc, wait_proc);
+
+	  /* Read data from the process, until we exhaust it.  */
+	  while (XINT (wait_proc->infd) >= 0)
+	    {
+	      nread = read_process_output (proc, XINT (wait_proc->infd));
+
+	      if (nread == 0)
+		break;
+
+              if (0 < nread) 
+                total_nread += nread;
+#ifdef EIO
+	      else if (nread == -1 && EIO == errno)
+                break;
+#endif
+#ifdef EAGAIN
+	      else if (nread == -1 && EAGAIN == errno)
+                break;
+#endif
+#ifdef EWOULDBLOCK
+	      else if (nread == -1 && EWOULDBLOCK == errno)
+                break;
+#endif
+	    }
+	  if (total_nread > 0 && do_display)
+	    redisplay_preserve_echo_area ();
+
+	  break;
+	}
+
+      /* Wait till there is something to do */
+
+      if (wait_for_cell)
+	Available = non_process_wait_mask;
+      else if (! XINT (read_kbd))
+	Available = non_keyboard_wait_mask;
+      else
+	Available = input_wait_mask;
+
+      /* If frame size has changed or the window is newly mapped,
+	 redisplay now, before we start to wait.  There is a race
+	 condition here; if a SIGIO arrives between now and the select
+	 and indicates that a frame is trashed, the select may block
+	 displaying a trashed screen.  */
+      if (frame_garbaged && do_display)
+	{
+	  clear_waiting_for_input ();
+	  redisplay_preserve_echo_area ();
+	  if (XINT (read_kbd) < 0)
+	    set_waiting_for_input (&timeout);
+	}
+
+      if (XINT (read_kbd) && detect_input_pending ())
+	{
+	  nfds = 0;
+	  FD_ZERO (&Available);
+	}
+      else
+	nfds = select (max (max_process_desc, max_keyboard_desc) + 1,
+		       &Available, (SELECT_TYPE *)0, (SELECT_TYPE *)0,
+		       &timeout);
+
+      xerrno = errno;
+
+      /* Make C-g and alarm signals set flags again */
+      clear_waiting_for_input ();
+
+      /*  If we woke up due to SIGWINCH, actually change size now.  */
+      do_pending_window_change (0);
+
+      if (time_limit && nfds == 0 && ! timeout_reduced_for_timers)
+	/* We wanted the full specified time, so return now.  */
+	break;
+      if (nfds < 0)
+	{
+	  if (xerrno == EINTR)
+	    FD_ZERO (&Available);
+#ifdef ultrix
+	  /* Ultrix select seems to return ENOMEM when it is
+	     interrupted.  Treat it just like EINTR.  Bleah.  Note
+	     that we want to test for the "ultrix" CPP symbol, not
+	     "__ultrix__"; the latter is only defined under GCC, but
+	     not by DEC's bundled CC.  -JimB  */
+	  else if (xerrno == ENOMEM)
+	    FD_ZERO (&Available);
+#endif
+#ifdef ALLIANT
+	  /* This happens for no known reason on ALLIANT.
+	     I am guessing that this is the right response. -- RMS.  */
+	  else if (xerrno == EFAULT)
+	    FD_ZERO (&Available);
+#endif
+	  else if (xerrno == EBADF)
+	    {
+#ifdef AIX
+	      /* AIX doesn't handle PTY closure the same way BSD does.  On AIX,
+		 the child's closure of the pts gives the parent a SIGHUP, and
+		 the ptc file descriptor is automatically closed,
+		 yielding EBADF here or at select() call above.
+		 So, SIGHUP is ignored (see def of PTY_TTY_NAME_SPRINTF
+		 in m/ibmrt-aix.h), and here we just ignore the select error.
+		 Cleanup occurs c/o status_notify after SIGCLD. */
+	      FD_ZERO (&Available); /* Cannot depend on values returned */
+#else
+	      abort ();
+#endif
+	    }
+	  else
+	    error ("select error: %s", emacs_strerror (xerrno));
+	}
+#if defined(sun) && !defined(USG5_4)
+      else if (nfds > 0 && keyboard_bit_set (&Available)
+	       && interrupt_input)
+	/* System sometimes fails to deliver SIGIO.
+
+	   David J. Mackenzie says that Emacs doesn't compile under
+	   Solaris if this code is enabled, thus the USG5_4 in the CPP
+	   conditional.  "I haven't noticed any ill effects so far.
+	   If you find a Solaris expert somewhere, they might know
+	   better." */
+	kill (getpid (), SIGIO);
+#endif
+
+#if 0 /* When polling is used, interrupt_input is 0,
+	 so get_input_pending should read the input.
+	 So this should not be needed.  */
+      /* If we are using polling for input,
+	 and we see input available, make it get read now.
+	 Otherwise it might not actually get read for a second.
+	 And on hpux, since we turn off polling in wait_reading_process_input,
+	 it might never get read at all if we don't spend much time
+	 outside of wait_reading_process_input.  */
+      if (XINT (read_kbd) && interrupt_input
+	  && keyboard_bit_set (&Available)
+	  && input_polling_used ())
+	kill (getpid (), SIGALRM);
+#endif
+
+      /* Check for keyboard input */
+      /* If there is any, return immediately
+	 to give it higher priority than subprocesses */
+
+      if (XINT (read_kbd) != 0
+	  && detect_input_pending_run_timers (do_display))
+	{
+	  swallow_events (do_display);
+	  if (detect_input_pending_run_timers (do_display))
+	    break;
+	}
+
+      /* If there is unread keyboard input, also return.  */
+      if (XINT (read_kbd) != 0
+	  && requeued_events_pending_p ())
+	break;
+
+      /* If we are not checking for keyboard input now,
+	 do process events (but don't run any timers).
+	 This is so that X events will be processed.
+	 Otherwise they may have to wait until polling takes place.
+	 That would causes delays in pasting selections, for example.
+
+	 (We used to do this only if wait_for_cell.)  */
+      if (XINT (read_kbd) == 0 && detect_input_pending ())
+	{
+	  swallow_events (do_display);
+#if 0  /* Exiting when read_kbd doesn't request that seems wrong, though.  */
+	  if (detect_input_pending ())
+	    break;
+#endif
+	}
+
+      /* Exit now if the cell we're waiting for became non-nil.  */
+      if (wait_for_cell && ! NILP (*wait_for_cell))
+	break;
+
+#ifdef SIGIO
+      /* If we think we have keyboard input waiting, but didn't get SIGIO,
+	 go read it.  This can happen with X on BSD after logging out.
+	 In that case, there really is no input and no SIGIO,
+	 but select says there is input.  */
+
+      if (XINT (read_kbd) && interrupt_input
+	  && keyboard_bit_set (&Available))
+	kill (getpid (), SIGIO);
+#endif
+
+      if (! wait_proc)
+	got_some_input |= nfds > 0;
+
+      /* If checking input just got us a size-change event from X,
+	 obey it now if we should.  */
+      if (XINT (read_kbd) || wait_for_cell)
+	do_pending_window_change (0);
+
+      /* Check for data from a process.  */
+      /* Really FIRST_PROC_DESC should be 0 on Unix,
+	 but this is safer in the short run.  */
+      for (channel = 0; channel <= max_process_desc; channel++)
+	{
+	  if (FD_ISSET (channel, &Available)
+	      && FD_ISSET (channel, &non_keyboard_wait_mask))
+	    {
+	      int nread;
+
+	      /* If waiting for this channel, arrange to return as
+		 soon as no more input to be processed.  No more
+		 waiting.  */
+	      if (wait_channel == channel)
+		{
+		  wait_channel = -1;
+		  time_limit = -1;
+		  got_some_input = 1;
+		}
+	      proc = chan_process[channel];
+	      if (NILP (proc))
+		continue;
+
+	      /* Read data from the process, starting with our
+		 buffered-ahead character if we have one.  */
+
+	      nread = read_process_output (proc, channel);
+	      if (nread > 0)
+		{
+		  /* Since read_process_output can run a filter,
+		     which can call accept-process-output,
+		     don't try to read from any other processes
+		     before doing the select again.  */
+		  FD_ZERO (&Available);
+
+		  if (do_display)
+		    redisplay_preserve_echo_area ();
+		}
+#ifdef EWOULDBLOCK
+	      else if (nread == -1 && errno == EWOULDBLOCK)
+		;
+#endif
+	      /* ISC 4.1 defines both EWOULDBLOCK and O_NONBLOCK,
+		 and Emacs uses O_NONBLOCK, so what we get is EAGAIN.  */
+#ifdef O_NONBLOCK
+	      else if (nread == -1 && errno == EAGAIN)
+		;
+#else
+#ifdef O_NDELAY
+	      else if (nread == -1 && errno == EAGAIN)
+		;
+	      /* Note that we cannot distinguish between no input
+		 available now and a closed pipe.
+		 With luck, a closed pipe will be accompanied by
+		 subprocess termination and SIGCHLD.  */
+	      else if (nread == 0 && !NETCONN_P (proc))
+		;
+#endif				/* O_NDELAY */
+#endif				/* O_NONBLOCK */
+#ifdef HAVE_PTYS
+	      /* On some OSs with ptys, when the process on one end of
+		 a pty exits, the other end gets an error reading with
+		 errno = EIO instead of getting an EOF (0 bytes read).
+		 Therefore, if we get an error reading and errno =
+		 EIO, just continue, because the child process has
+		 exited and should clean itself up soon (e.g. when we
+		 get a SIGCHLD).
+
+		 However, it has been known to happen that the SIGCHLD
+		 got lost.  So raise the signl again just in case.
+		 It can't hurt.  */
+	      else if (nread == -1 && errno == EIO)
+		kill (getpid (), SIGCHLD);
+#endif				/* HAVE_PTYS */
+	      /* If we can detect process termination, don't consider the process
+		 gone just because its pipe is closed.  */
+#ifdef SIGCHLD
+	      else if (nread == 0 && !NETCONN_P (proc))
+		;
+#endif
+	      else
+		{
+		  /* Preserve status of processes already terminated.  */
+		  XSETINT (XPROCESS (proc)->tick, ++process_tick);
+		  deactivate_process (proc);
+		  if (!NILP (XPROCESS (proc)->raw_status_low))
+		    update_status (XPROCESS (proc));
+		  if (EQ (XPROCESS (proc)->status, Qrun))
+		    XPROCESS (proc)->status
+		      = Fcons (Qexit, Fcons (make_number (256), Qnil));
+		}
+	    }
+	}			/* end for each file descriptor */
+    }				/* end while exit conditions not met */
+
+  waiting_for_user_input_p = 0;
+
+  /* If calling from keyboard input, do not quit
+     since we want to return C-g as an input character.
+     Otherwise, do pending quit if requested.  */
+  if (XINT (read_kbd) >= 0)
+    {
+      /* Prevent input_pending from remaining set if we quit.  */
+      clear_input_pending ();
+      QUIT;
+    }
+#ifdef hpux
+  /* AlainF 5-Jul-1996
+     HP-UX 10.10 seems to have problems with signals coming in
+     Causes "poll: interrupted system call" messages when Emacs is run
+     in an X window
+     Turn periodic alarms back on */
+  start_polling ();
+#endif
+
+#ifdef HAVE_X_WINDOWS
+  if (display_busy_cursor_p)
+    if (!inhibit_busy_cursor)
+      Fx_show_busy_cursor ();
+#endif
+   
+  return got_some_input;
+}
+
+/* Given a list (FUNCTION ARGS...), apply FUNCTION to the ARGS.  */
+
+static Lisp_Object
+read_process_output_call (fun_and_args)
+     Lisp_Object fun_and_args;
+{
+  return apply1 (XCAR (fun_and_args), XCDR (fun_and_args));
+}
+
+static Lisp_Object
+read_process_output_error_handler (error)
+     Lisp_Object error;
+{
+  cmd_error_internal (error, "error in process filter: ");
+  Vinhibit_quit = Qt;
+  update_echo_area ();
+  Fsleep_for (make_number (2), Qnil);
+}
+
+/* Read pending output from the process channel,
+   starting with our buffered-ahead character if we have one.
+   Yield number of decoded characters read.
+
+   This function reads at most 1024 characters.
+   If you want to read all available subprocess output,
+   you must call it repeatedly until it returns zero.
+
+   The characters read are decoded according to PROC's coding-system
+   for decoding.  */
+
+int
+read_process_output (proc, channel)
+     Lisp_Object proc;
+     register int channel;
+{
+  register int nchars, nbytes;
+  char *chars;
+#ifdef VMS
+  int chars_allocated = 0;	/* If 1, `chars' should be freed later.  */
+#else
+  char buf[1024];
+#endif
+  register Lisp_Object outstream;
+  register struct buffer *old = current_buffer;
+  register struct Lisp_Process *p = XPROCESS (proc);
+  register int opoint;
+  struct coding_system *coding = proc_decode_coding_system[channel];
+  int chars_in_decoding_buf = 0; /* If 1, `chars' points
+				    XSTRING (p->decoding_buf)->data.  */
+  int carryover = XINT (p->decoding_carryover);
+
+#ifdef VMS
+  VMS_PROC_STUFF *vs, *get_vms_process_pointer();
+
+  vs = get_vms_process_pointer (p->pid);
+  if (vs)
+    {
+      if (!vs->iosb[0])
+	return (0);		/* Really weird if it does this */
+      if (!(vs->iosb[0] & 1))
+	return -1;		/* I/O error */
+    }
+  else
+    error ("Could not get VMS process pointer");
+  chars = vs->inputBuffer;
+  nbytes = clean_vms_buffer (chars, vs->iosb[1]);
+  if (nbytes <= 0)
+    {
+      start_vms_process_read (vs); /* Crank up the next read on the process */
+      return 1;			/* Nothing worth printing, say we got 1 */
+    }
+  if (carryover > 0)
+    {
+      /* The data carried over in the previous decoding (which are at
+         the tail of decoding buffer) should be prepended to the new
+         data read to decode all together.  */
+      char *buf = (char *) xmalloc (nbytes + carryover);
+
+      bcopy (XSTRING (p->decoding_buf)->data
+	     + STRING_BYTES (XSTRING (p->decoding_buf)) - carryover,
+	     buf, carryover);
+      bcopy (chars, buf + carryover, nbytes);
+      chars = buf;
+      chars_allocated = 1;
+    }
+#else /* not VMS */
+
+  if (carryover)
+    /* See the comment above.  */
+    bcopy (XSTRING (p->decoding_buf)->data
+	   + STRING_BYTES (XSTRING (p->decoding_buf)) - carryover,
+	   buf, carryover);
+
+  if (proc_buffered_char[channel] < 0)
+    nbytes = emacs_read (channel, buf + carryover, (sizeof buf) - carryover);
+  else
+    {
+      buf[carryover] = proc_buffered_char[channel];
+      proc_buffered_char[channel] = -1;
+      nbytes = emacs_read (channel, buf + carryover + 1,
+			   (sizeof buf) - carryover - 1);
+      if (nbytes < 0)
+	nbytes = 1;
+      else
+	nbytes = nbytes + 1;
+    }
+  chars = buf;
+#endif /* not VMS */
+
+  XSETINT (p->decoding_carryover, 0);
+
+  /* At this point, NBYTES holds number of characters just received
+     (including the one in proc_buffered_char[channel]).  */
+  if (nbytes <= 0)
+    {
+      if (nbytes < 0 || coding->mode & CODING_MODE_LAST_BLOCK)
+	return nbytes;
+      coding->mode |= CODING_MODE_LAST_BLOCK;
+    }
+
+  /* Now set NBYTES how many bytes we must decode.  */
+  nbytes += carryover;
+  nchars = nbytes;
+
+  if (CODING_MAY_REQUIRE_DECODING (coding))
+    {
+      int require = decoding_buffer_size (coding, nbytes);
+      int result;
+      
+      if (STRING_BYTES (XSTRING (p->decoding_buf)) < require)
+	p->decoding_buf = make_uninit_string (require);
+      result = decode_coding (coding, chars, XSTRING (p->decoding_buf)->data,
+			      nbytes, STRING_BYTES (XSTRING (p->decoding_buf)));
+      carryover = nbytes - coding->consumed;
+      if (carryover > 0)
+	{
+	  /* Copy the carryover bytes to the end of p->decoding_buf, to
+	     be processed on the next read.  Since decoding_buffer_size
+	     asks for an extra amount of space beyond the maximum
+	     expected for the output, there should always be sufficient
+	     space for the carryover (which is by definition a sequence
+	     of bytes that was not long enough to be decoded, and thus
+	     has a bounded length).  */
+	  if (STRING_BYTES (XSTRING (p->decoding_buf))
+	      < coding->produced + carryover)
+	    abort ();
+	  bcopy (chars + coding->consumed,
+		 XSTRING (p->decoding_buf)->data
+		 + STRING_BYTES (XSTRING (p->decoding_buf)) - carryover,
+		 carryover);
+	  XSETINT (p->decoding_carryover, carryover);
+	}
+
+      /* A new coding system might be found by `decode_coding'.  */
+      if (!EQ (p->decode_coding_system, coding->symbol))
+	{
+	  p->decode_coding_system = coding->symbol;
+
+	  /* Don't call setup_coding_system for
+             proc_decode_coding_system[channel] here.  It is done in
+             detect_coding called via decode_coding above.  */
+
+	  /* If a coding system for encoding is not yet decided, we set
+	     it as the same as coding-system for decoding.
+
+	     But, before doing that we must check if
+	     proc_encode_coding_system[p->outfd] surely points to a
+	     valid memory because p->outfd will be changed once EOF is
+	     sent to the process.  */
+	  if (NILP (p->encode_coding_system)
+	      && proc_encode_coding_system[XINT (p->outfd)])
+	    {
+	      p->encode_coding_system = coding->symbol;
+	      setup_coding_system (coding->symbol,
+				   proc_encode_coding_system[XINT (p->outfd)]);
+	    }
+	}
+
+#ifdef VMS
+      /*  Now we don't need the contents of `chars'.  */
+      if (chars_allocated)
+	free (chars);
+#endif
+      if (coding->produced == 0)
+	return 0;
+      chars = (char *) XSTRING (p->decoding_buf)->data;
+      nbytes = coding->produced;
+      nchars = (coding->fake_multibyte
+		? multibyte_chars_in_text (chars, nbytes)
+		: coding->produced_char);
+      chars_in_decoding_buf = 1;
+    }
+  else
+    {
+#ifdef VMS
+      if (chars_allocated)
+	{
+	  /* Although we don't have to decode the received data, we
+	     must move it to an area which we don't have to free.  */
+	  if (! STRINGP (p->decoding_buf)
+	      || STRING_BYTES (XSTRING (p->decoding_buf)) < nbytes)
+	    p->decoding_buf = make_uninit_string (nbytes);
+	  bcopy (chars, XSTRING (p->decoding_buf)->data, nbytes);
+	  free (chars);
+	  chars = XSTRING (p->decoding_buf)->data;
+	  chars_in_decoding_buf = 1;
+	}
+#endif
+      nchars = multibyte_chars_in_text (chars, nbytes);
+    }
+
+  Vlast_coding_system_used = coding->symbol;
+
+  /* If the caller required, let the process associated buffer
+     inherit the coding-system used to decode the process output.  */
+  if (! NILP (p->inherit_coding_system_flag)
+      && !NILP (p->buffer) && !NILP (XBUFFER (p->buffer)->name))
+    {
+      struct buffer *prev_buf = current_buffer;
+
+      Fset_buffer (p->buffer);
+      call1 (intern ("after-insert-file-set-buffer-file-coding-system"),
+	     make_number (nbytes));
+      set_buffer_internal (prev_buf);
+    }
+
+  /* Read and dispose of the process output.  */
+  outstream = p->filter;
+  if (!NILP (outstream))
+    {
+      /* We inhibit quit here instead of just catching it so that 
+	 hitting ^G when a filter happens to be running won't screw
+	 it up.  */
+      int count = specpdl_ptr - specpdl;
+      Lisp_Object odeactivate;
+      Lisp_Object obuffer, okeymap;
+      Lisp_Object text;
+      int outer_running_asynch_code = running_asynch_code;
+      int waiting = waiting_for_user_input_p;
+
+      /* No need to gcpro these, because all we do with them later
+	 is test them for EQness, and none of them should be a string.  */
+      odeactivate = Vdeactivate_mark;
+      XSETBUFFER (obuffer, current_buffer);
+      okeymap = current_buffer->keymap;
+
+      specbind (Qinhibit_quit, Qt);
+      specbind (Qlast_nonmenu_event, Qt);
+
+      /* In case we get recursively called,
+	 and we already saved the match data nonrecursively,
+	 save the same match data in safely recursive fashion.  */
+      if (outer_running_asynch_code)
+	{
+	  Lisp_Object tem;
+	  /* Don't clobber the CURRENT match data, either!  */
+	  tem = Fmatch_data (Qnil, Qnil);
+	  restore_match_data ();
+	  record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
+	  Fset_match_data (tem);
+	}
+
+      /* For speed, if a search happens within this code,
+	 save the match data in a special nonrecursive fashion.  */
+      running_asynch_code = 1;
+
+      /* The multibyteness of a string given to the filter is decided
+         by which coding system we used for decoding.  */
+      if (coding->type == coding_type_no_conversion
+	  || coding->type == coding_type_raw_text)
+	text = make_unibyte_string (chars, nbytes);
+      else
+	text = make_multibyte_string (chars, nchars, nbytes);
+
+      internal_condition_case_1 (read_process_output_call,
+				 Fcons (outstream,
+					Fcons (proc, Fcons (text, Qnil))),
+				 !NILP (Vdebug_on_error) ? Qnil : Qerror,
+				 read_process_output_error_handler);
+
+      /* If we saved the match data nonrecursively, restore it now.  */
+      restore_match_data ();
+      running_asynch_code = outer_running_asynch_code;
+
+      /* Handling the process output should not deactivate the mark.  */
+      Vdeactivate_mark = odeactivate;
+
+      /* Restore waiting_for_user_input_p as it was
+	 when we were called, in case the filter clobbered it.  */
+      waiting_for_user_input_p = waiting;
+
+#if 0 /* Call record_asynch_buffer_change unconditionally,
+	 because we might have changed minor modes or other things
+	 that affect key bindings.  */
+      if (! EQ (Fcurrent_buffer (), obuffer)
+	  || ! EQ (current_buffer->keymap, okeymap))
+#endif
+	/* But do it only if the caller is actually going to read events.
+	   Otherwise there's no need to make him wake up, and it could
+	   cause trouble (for example it would make Fsit_for return).  */
+	if (waiting_for_user_input_p == -1)
+	  record_asynch_buffer_change ();
+
+#ifdef VMS
+      start_vms_process_read (vs);
+#endif
+      unbind_to (count, Qnil);
+      return nchars;
+    }
+
+  /* If no filter, write into buffer if it isn't dead.  */
+  if (!NILP (p->buffer) && !NILP (XBUFFER (p->buffer)->name))
+    {
+      Lisp_Object old_read_only;
+      int old_begv, old_zv;
+      int old_begv_byte, old_zv_byte;
+      Lisp_Object odeactivate;
+      int before, before_byte;
+      int opoint_byte;
+
+      odeactivate = Vdeactivate_mark;
+
+      Fset_buffer (p->buffer);
+      opoint = PT;
+      opoint_byte = PT_BYTE;
+      old_read_only = current_buffer->read_only;
+      old_begv = BEGV;
+      old_zv = ZV;
+      old_begv_byte = BEGV_BYTE;
+      old_zv_byte = ZV_BYTE;
+
+      current_buffer->read_only = Qnil;
+
+      /* Insert new output into buffer
+	 at the current end-of-output marker,
+	 thus preserving logical ordering of input and output.  */
+      if (XMARKER (p->mark)->buffer)
+	SET_PT_BOTH (clip_to_bounds (BEGV, marker_position (p->mark), ZV),
+		     clip_to_bounds (BEGV_BYTE, marker_byte_position (p->mark),
+				     ZV_BYTE));
+      else
+	SET_PT_BOTH (ZV, ZV_BYTE);
+      before = PT;
+      before_byte = PT_BYTE;
+
+      /* If the output marker is outside of the visible region, save
+	 the restriction and widen.  */
+      if (! (BEGV <= PT && PT <= ZV))
+	Fwiden ();
+
+      if (NILP (current_buffer->enable_multibyte_characters))
+	nchars = nbytes;
+
+      /* Insert before markers in case we are inserting where
+	 the buffer's mark is, and the user's next command is Meta-y.  */
+      if (chars_in_decoding_buf)
+	{
+	  /* Since multibyteness of p->docoding_buf is corrupted, we
+             can't use insert_from_string_before_markers.  */
+	  char *temp_buf;
+
+	  temp_buf = (char *) alloca (nbytes);
+	  bcopy (XSTRING (p->decoding_buf)->data, temp_buf, nbytes);
+	  insert_before_markers (temp_buf, nbytes);
+	}
+      else
+	{
+	  insert_1_both (chars, nchars, nbytes, 0, 1, 1);
+	  signal_after_change (before, 0, PT - before);
+	  update_compositions (before, PT, CHECK_BORDER);
+	}
+      set_marker_both (p->mark, p->buffer, PT, PT_BYTE);
+
+      update_mode_lines++;
+
+      /* Make sure opoint and the old restrictions
+	 float ahead of any new text just as point would.  */
+      if (opoint >= before)
+	{
+	  opoint += PT - before;
+	  opoint_byte += PT_BYTE - before_byte;
+	}
+      if (old_begv > before)
+	{
+	  old_begv += PT - before;
+	  old_begv_byte += PT_BYTE - before_byte;
+	}
+      if (old_zv >= before)
+	{
+	  old_zv += PT - before;
+	  old_zv_byte += PT_BYTE - before_byte;
+	}
+
+      /* If the restriction isn't what it should be, set it.  */
+      if (old_begv != BEGV || old_zv != ZV)
+	Fnarrow_to_region (make_number (old_begv), make_number (old_zv));
+
+      /* Handling the process output should not deactivate the mark.  */
+      Vdeactivate_mark = odeactivate;
+
+      current_buffer->read_only = old_read_only;
+      SET_PT_BOTH (opoint, opoint_byte);
+      set_buffer_internal (old);
+    }
+#ifdef VMS
+  start_vms_process_read (vs);
+#endif
+  return nbytes;
+}
+
+DEFUN ("waiting-for-user-input-p", Fwaiting_for_user_input_p, Swaiting_for_user_input_p,
+       0, 0, 0,
+  "Returns non-nil if emacs is waiting for input from the user.\n\
+This is intended for use by asynchronous process output filters and sentinels.")
+       ()
+{
+  return (waiting_for_user_input_p ? Qt : Qnil);
+}
+
+/* Sending data to subprocess */
+
+jmp_buf send_process_frame;
+
+SIGTYPE
+send_process_trap ()
+{
+#ifdef BSD4_1
+  sigrelse (SIGPIPE);
+  sigrelse (SIGALRM);
+#endif /* BSD4_1 */
+  longjmp (send_process_frame, 1);
+}
+
+/* Send some data to process PROC.
+   BUF is the beginning of the data; LEN is the number of characters.
+   OBJECT is the Lisp object that the data comes from.
+
+   The data is encoded by PROC's coding-system for encoding before it
+   is sent.  But if the data ends at the middle of multi-byte
+   representation, that incomplete sequence of bytes are sent without
+   being encoded.  Should we store them in a buffer to prepend them to
+   the data send later?  */
+
+void
+send_process (proc, buf, len, object)
+     volatile Lisp_Object proc;
+     unsigned char *buf;
+     int len;
+     Lisp_Object object;
+{
+  /* Use volatile to protect variables from being clobbered by longjmp.  */
+  int rv;
+  volatile unsigned char *procname = XSTRING (XPROCESS (proc)->name)->data;
+  struct coding_system *coding;
+  struct gcpro gcpro1;
+  int carryover = XINT (XPROCESS (proc)->encoding_carryover);
+
+  GCPRO1 (object);
+
+#ifdef VMS
+  struct Lisp_Process *p = XPROCESS (proc);
+  VMS_PROC_STUFF *vs, *get_vms_process_pointer();
+#endif /* VMS */
+
+  if (! NILP (XPROCESS (proc)->raw_status_low))
+    update_status (XPROCESS (proc));
+  if (! EQ (XPROCESS (proc)->status, Qrun))
+    error ("Process %s not running", procname);
+  if (XINT (XPROCESS (proc)->outfd) < 0)
+    error ("Output file descriptor of %s is closed", procname);
+
+  coding = proc_encode_coding_system[XINT (XPROCESS (proc)->outfd)];
+  Vlast_coding_system_used = coding->symbol;
+
+  if (CODING_REQUIRE_ENCODING (coding))
+    {
+      int require = encoding_buffer_size (coding, len);
+      int offset;
+      unsigned char *temp_buf = NULL;
+
+      /* Remember the offset of data because a string or a buffer may
+         be relocated.  Setting OFFSET to -1 means we don't have to
+         care about relocation.  */
+      offset = (BUFFERP (object)
+		? BUF_PTR_BYTE_POS (XBUFFER (object), buf)
+		: (STRINGP (object)
+		   ? buf - XSTRING (object)->data
+		   : -1));
+
+      if (carryover > 0)
+	{
+	  temp_buf = (unsigned char *) xmalloc (len + carryover);
+
+	  if (offset >= 0)
+	    {
+	      if (BUFFERP (object))
+		buf = BUF_BYTE_ADDRESS (XBUFFER (object), offset);
+	      else if (STRINGP (object))
+		buf = offset + XSTRING (object)->data;
+	      /* Now we don't have to care about relocation.  */
+	      offset = -1;
+	    }
+	  bcopy ((XSTRING (XPROCESS (proc)->encoding_buf)->data
+		  + STRING_BYTES (XSTRING (XPROCESS (proc)->encoding_buf))
+		  - carryover),
+		 temp_buf,
+		 carryover);
+	  bcopy (buf, temp_buf + carryover, len);
+	  buf = temp_buf;
+	}
+
+      if (STRING_BYTES (XSTRING (XPROCESS (proc)->encoding_buf)) < require)
+	{
+	  XPROCESS (proc)->encoding_buf = make_uninit_string (require);
+
+	  if (offset >= 0)
+	    {
+	      if (BUFFERP (object))
+		buf = BUF_BYTE_ADDRESS (XBUFFER (object), offset);
+	      else if (STRINGP (object))
+		buf = offset + XSTRING (object)->data;
+	    }
+	}
+      object = XPROCESS (proc)->encoding_buf;
+      encode_coding (coding, buf, XSTRING (object)->data,
+		     len, STRING_BYTES (XSTRING (object)));
+      len = coding->produced;
+      buf = XSTRING (object)->data;
+      if (temp_buf)
+	xfree (temp_buf);
+    }
+
+#ifdef VMS
+  vs = get_vms_process_pointer (p->pid);
+  if (vs == 0)
+    error ("Could not find this process: %x", p->pid);
+  else if (write_to_vms_process (vs, buf, len))
+    ;
+#else
+
+  if (pty_max_bytes == 0)
+    {
+#if defined (HAVE_FPATHCONF) && defined (_PC_MAX_CANON)
+      pty_max_bytes = fpathconf (XFASTINT (XPROCESS (proc)->outfd),
+				 _PC_MAX_CANON);
+      if (pty_max_bytes < 0)
+	pty_max_bytes = 250;
+#else
+      pty_max_bytes = 250;
+#endif
+      /* Deduct one, to leave space for the eof.  */
+      pty_max_bytes--;
+    }
+
+  if (!setjmp (send_process_frame))
+    while (len > 0)
+      {
+	int this = len;
+	SIGTYPE (*old_sigpipe)();
+
+	/* Decide how much data we can send in one batch.
+	   Long lines need to be split into multiple batches.  */
+	if (!NILP (XPROCESS (proc)->pty_flag))
+	  {
+	    /* Starting this at zero is always correct when not the first iteration
+	       because the previous iteration ended by sending C-d.
+	       It may not be correct for the first iteration
+	       if a partial line was sent in a separate send_process call.
+	       If that proves worth handling, we need to save linepos
+	       in the process object.  */
+	    int linepos = 0;
+	    unsigned char *ptr = buf;
+	    unsigned char *end = buf + len;
+
+	    /* Scan through this text for a line that is too long.  */
+	    while (ptr != end && linepos < pty_max_bytes)
+	      {
+		if (*ptr == '\n')
+		  linepos = 0;
+		else
+		  linepos++;
+		ptr++;
+	      }
+	    /* If we found one, break the line there
+	       and put in a C-d to force the buffer through.  */
+	    this = ptr - buf;
+	  }
+
+	/* Send this batch, using one or more write calls.  */
+	while (this > 0)
+	  {
+	    old_sigpipe = (SIGTYPE (*) ()) signal (SIGPIPE, send_process_trap);
+	    rv = emacs_write (XINT (XPROCESS (proc)->outfd), buf, this);
+	    signal (SIGPIPE, old_sigpipe);
+
+	    if (rv < 0)
+	      {
+		if (0
+#ifdef EWOULDBLOCK
+		    || errno == EWOULDBLOCK
+#endif
+#ifdef EAGAIN
+		    || errno == EAGAIN
+#endif
+		    )
+		  /* Buffer is full.  Wait, accepting input; 
+		     that may allow the program
+		     to finish doing output and read more.  */
+		  {
+		    Lisp_Object zero;
+		    int offset;
+
+		    /* Running filters might relocate buffers or strings.
+		       Arrange to relocate BUF.  */
+		    if (BUFFERP (object))
+		      offset = BUF_PTR_BYTE_POS (XBUFFER (object), buf);
+		    else if (STRINGP (object))
+		      offset = buf - XSTRING (object)->data;
+
+		    XSETFASTINT (zero, 0);
+#ifdef EMACS_HAS_USECS
+		    wait_reading_process_input (0, 20000, zero, 0);
+#else
+		    wait_reading_process_input (1, 0, zero, 0);
+#endif
+
+		    if (BUFFERP (object))
+		      buf = BUF_BYTE_ADDRESS (XBUFFER (object), offset);
+		    else if (STRINGP (object))
+		      buf = offset + XSTRING (object)->data;
+
+		    rv = 0;
+		  }
+		else
+		  /* This is a real error.  */
+		  report_file_error ("writing to process", Fcons (proc, Qnil));
+	      }
+	    buf += rv;
+	    len -= rv;
+	    this -= rv;
+	  }
+
+	/* If we sent just part of the string, put in an EOF
+	   to force it through, before we send the rest.  */
+	if (len > 0)
+	  Fprocess_send_eof (proc);
+      }
+#endif
+  else
+    {
+      XPROCESS (proc)->raw_status_low = Qnil;
+      XPROCESS (proc)->raw_status_high = Qnil;
+      XPROCESS (proc)->status = Fcons (Qexit, Fcons (make_number (256), Qnil));
+      XSETINT (XPROCESS (proc)->tick, ++process_tick);
+      deactivate_process (proc);
+#ifdef VMS
+      error ("Error writing to process %s; closed it", procname);
+#else
+      error ("SIGPIPE raised on process %s; closed it", procname);
+#endif
+    }
+
+  UNGCPRO;
+}
+
+DEFUN ("process-send-region", Fprocess_send_region, Sprocess_send_region,
+  3, 3, 0,
+  "Send current contents of region as input to PROCESS.\n\
+PROCESS may be a process, a buffer, the name of a process or buffer, or\n\
+nil, indicating the current buffer's process.\n\
+Called from program, takes three arguments, PROCESS, START and END.\n\
+If the region is more than 500 characters long,\n\
+it is sent in several bunches.  This may happen even for shorter regions.\n\
+Output from processes can arrive in between bunches.")
+  (process, start, end)
+     Lisp_Object process, start, end;
+{
+  Lisp_Object proc;
+  int start1, end1;
+
+  proc = get_process (process);
+  validate_region (&start, &end);
+
+  if (XINT (start) < GPT && XINT (end) > GPT)
+    move_gap (XINT (start));
+
+  start1 = CHAR_TO_BYTE (XINT (start));
+  end1 = CHAR_TO_BYTE (XINT (end));
+  send_process (proc, BYTE_POS_ADDR (start1), end1 - start1,
+		Fcurrent_buffer ());
+
+  return Qnil;
+}
+
+DEFUN ("process-send-string", Fprocess_send_string, Sprocess_send_string,
+  2, 2, 0,
+  "Send PROCESS the contents of STRING as input.\n\
+PROCESS may be a process, a buffer, the name of a process or buffer, or\n\
+nil, indicating the current buffer's process.\n\
+If STRING is more than 500 characters long,\n\
+it is sent in several bunches.  This may happen even for shorter strings.\n\
+Output from processes can arrive in between bunches.")
+  (process, string)
+     Lisp_Object process, string;
+{
+  Lisp_Object proc;
+  CHECK_STRING (string, 1);
+  proc = get_process (process);
+  send_process (proc, XSTRING (string)->data,
+		STRING_BYTES (XSTRING (string)), string);
+  return Qnil;
+}
+
+DEFUN ("process-running-child-p", Fprocess_running_child_p,
+       Sprocess_running_child_p, 0, 1, 0,
+  "Return t if PROCESS has given the terminal to a child.\n\
+If the operating system does not make it possible to find out,\n\
+return t unconditionally.")
+  (process)
+     Lisp_Object process;
+{
+  /* Initialize in case ioctl doesn't exist or gives an error,
+     in a way that will cause returning t.  */
+  int gid = 0;
+  Lisp_Object proc;
+  struct Lisp_Process *p;
+
+  proc = get_process (process);
+  p = XPROCESS (proc);
+
+  if (!EQ (p->childp, Qt))
+    error ("Process %s is not a subprocess",
+	   XSTRING (p->name)->data);
+  if (XINT (p->infd) < 0)
+    error ("Process %s is not active",
+	   XSTRING (p->name)->data);
+
+#ifdef TIOCGPGRP 
+  if (!NILP (p->subtty))
+    ioctl (XFASTINT (p->subtty), TIOCGPGRP, &gid);
+  else
+    ioctl (XINT (p->infd), TIOCGPGRP, &gid);
+#endif /* defined (TIOCGPGRP ) */
+
+  if (gid == XFASTINT (p->pid))
+    return Qnil;
+  return Qt;
+}
+
+/* send a signal number SIGNO to PROCESS.
+   If CURRENT_GROUP is t, that means send to the process group
+   that currently owns the terminal being used to communicate with PROCESS.
+   This is used for various commands in shell mode.
+   If CURRENT_GROUP is lambda, that means send to the process group
+   that currently owns the terminal, but only if it is NOT the shell itself.
+
+   If NOMSG is zero, insert signal-announcements into process's buffers
+   right away.
+
+   If we can, we try to signal PROCESS by sending control characters
+   down the pty.  This allows us to signal inferiors who have changed
+   their uid, for which killpg would return an EPERM error.  */
+
+static void
+process_send_signal (process, signo, current_group, nomsg)
+     Lisp_Object process;
+     int signo;
+     Lisp_Object current_group;
+     int nomsg;
+{
+  Lisp_Object proc;
+  register struct Lisp_Process *p;
+  int gid;
+  int no_pgrp = 0;
+
+  proc = get_process (process);
+  p = XPROCESS (proc);
+
+  if (!EQ (p->childp, Qt))
+    error ("Process %s is not a subprocess",
+	   XSTRING (p->name)->data);
+  if (XINT (p->infd) < 0)
+    error ("Process %s is not active",
+	   XSTRING (p->name)->data);
+
+  if (NILP (p->pty_flag))
+    current_group = Qnil;
+
+  /* If we are using pgrps, get a pgrp number and make it negative.  */
+  if (!NILP (current_group))
+    {
+#ifdef SIGNALS_VIA_CHARACTERS
+      /* If possible, send signals to the entire pgrp
+	 by sending an input character to it.  */
+
+      /* TERMIOS is the latest and bestest, and seems most likely to
+         work.  If the system has it, use it.  */
+#ifdef HAVE_TERMIOS
+      struct termios t;
+
+      switch (signo)
+	{
+	case SIGINT:
+	  tcgetattr (XINT (p->infd), &t);
+	  send_process (proc, &t.c_cc[VINTR], 1, Qnil);
+	  return;
+
+	case SIGQUIT:
+	  tcgetattr (XINT (p->infd), &t);
+  	  send_process (proc, &t.c_cc[VQUIT], 1, Qnil);
+  	  return;
+
+  	case SIGTSTP:
+	  tcgetattr (XINT (p->infd), &t);
+#if defined (VSWTCH) && !defined (PREFER_VSUSP)
+  	  send_process (proc, &t.c_cc[VSWTCH], 1, Qnil);
+#else
+	  send_process (proc, &t.c_cc[VSUSP], 1, Qnil);
+#endif
+  	  return;
+	}
+
+#else /* ! HAVE_TERMIOS */
+
+      /* On Berkeley descendants, the following IOCTL's retrieve the
+	 current control characters.  */
+#if defined (TIOCGLTC) && defined (TIOCGETC)
+
+      struct tchars c;
+      struct ltchars lc;
+
+      switch (signo)
+	{
+	case SIGINT:
+	  ioctl (XINT (p->infd), TIOCGETC, &c);
+	  send_process (proc, &c.t_intrc, 1, Qnil);
+	  return;
+	case SIGQUIT:
+	  ioctl (XINT (p->infd), TIOCGETC, &c);
+	  send_process (proc, &c.t_quitc, 1, Qnil);
+	  return;
+#ifdef SIGTSTP
+	case SIGTSTP:
+	  ioctl (XINT (p->infd), TIOCGLTC, &lc);
+	  send_process (proc, &lc.t_suspc, 1, Qnil);
+	  return;
+#endif /* ! defined (SIGTSTP) */
+	}
+
+#else /* ! defined (TIOCGLTC) && defined (TIOCGETC) */
+
+      /* On SYSV descendants, the TCGETA ioctl retrieves the current control
+	 characters.  */
+#ifdef TCGETA
+      struct termio t;
+      switch (signo)
+	{
+	case SIGINT:
+	  ioctl (XINT (p->infd), TCGETA, &t);
+	  send_process (proc, &t.c_cc[VINTR], 1, Qnil);
+	  return;
+	case SIGQUIT:
+	  ioctl (XINT (p->infd), TCGETA, &t);
+	  send_process (proc, &t.c_cc[VQUIT], 1, Qnil);
+	  return;
+#ifdef SIGTSTP
+	case SIGTSTP:
+	  ioctl (XINT (p->infd), TCGETA, &t);
+	  send_process (proc, &t.c_cc[VSWTCH], 1, Qnil);
+	  return;
+#endif /* ! defined (SIGTSTP) */
+	}
+#else /* ! defined (TCGETA) */
+      Your configuration files are messed up.
+      /* If your system configuration files define SIGNALS_VIA_CHARACTERS,
+	 you'd better be using one of the alternatives above!  */
+#endif /* ! defined (TCGETA) */
+#endif /* ! defined (TIOCGLTC) && defined (TIOCGETC) */
+#endif /* ! defined HAVE_TERMIOS */
+#endif /* ! defined (SIGNALS_VIA_CHARACTERS) */
+
+#ifdef TIOCGPGRP 
+      /* Get the pgrp using the tty itself, if we have that.
+	 Otherwise, use the pty to get the pgrp.
+	 On pfa systems, saka@pfu.fujitsu.co.JP writes:
+	 "TIOCGPGRP symbol defined in sys/ioctl.h at E50.
+	 But, TIOCGPGRP does not work on E50 ;-P works fine on E60"
+	 His patch indicates that if TIOCGPGRP returns an error, then
+	 we should just assume that p->pid is also the process group id.  */
+      {
+	int err;
+
+	if (!NILP (p->subtty))
+	  err = ioctl (XFASTINT (p->subtty), TIOCGPGRP, &gid);
+	else
+	  err = ioctl (XINT (p->infd), TIOCGPGRP, &gid);
+
+#ifdef pfa
+	if (err == -1)
+	  gid = - XFASTINT (p->pid);
+#endif /* ! defined (pfa) */
+      }
+      if (gid == -1)
+	no_pgrp = 1;
+      else
+	gid = - gid;
+#else  /* ! defined (TIOCGPGRP ) */
+      /* Can't select pgrps on this system, so we know that
+	 the child itself heads the pgrp.  */
+      gid = - XFASTINT (p->pid);
+#endif /* ! defined (TIOCGPGRP ) */
+
+      /* If current_group is lambda, and the shell owns the terminal,
+	 don't send any signal.  */
+      if (EQ (current_group, Qlambda) && gid == - XFASTINT (p->pid))
+	return;
+    }
+  else
+    gid = - XFASTINT (p->pid);
+
+  switch (signo)
+    {
+#ifdef SIGCONT
+    case SIGCONT:
+      p->raw_status_low = Qnil;
+      p->raw_status_high = Qnil;
+      p->status = Qrun;
+      XSETINT (p->tick, ++process_tick);
+      if (!nomsg)
+	status_notify ();
+      break;
+#endif /* ! defined (SIGCONT) */
+    case SIGINT:
+#ifdef VMS
+      send_process (proc, "\003", 1, Qnil);	/* ^C */
+      goto whoosh;
+#endif
+    case SIGQUIT:
+#ifdef VMS
+      send_process (proc, "\031", 1, Qnil);	/* ^Y */
+      goto whoosh;
+#endif
+    case SIGKILL:
+#ifdef VMS
+      sys$forcex (&(XFASTINT (p->pid)), 0, 1);
+      whoosh:
+#endif
+      flush_pending_output (XINT (p->infd));
+      break;
+    }
+
+  /* If we don't have process groups, send the signal to the immediate
+     subprocess.  That isn't really right, but it's better than any
+     obvious alternative.  */
+  if (no_pgrp)
+    {
+      kill (XFASTINT (p->pid), signo);
+      return;
+    }
+
+  /* gid may be a pid, or minus a pgrp's number */
+#ifdef TIOCSIGSEND
+  if (!NILP (current_group))
+    ioctl (XINT (p->infd), TIOCSIGSEND, signo);
+  else
+    {
+      gid = - XFASTINT (p->pid);
+      kill (gid, signo);
+    }
+#else /* ! defined (TIOCSIGSEND) */
+  EMACS_KILLPG (-gid, signo);
+#endif /* ! defined (TIOCSIGSEND) */
+}
+
+DEFUN ("interrupt-process", Finterrupt_process, Sinterrupt_process, 0, 2, 0,
+  "Interrupt process PROCESS.\n\
+PROCESS may be a process, a buffer, or the name of a process or buffer.\n\
+nil or no arg means current buffer's process.\n\
+Second arg CURRENT-GROUP non-nil means send signal to\n\
+the current process-group of the process's controlling terminal\n\
+rather than to the process's own process group.\n\
+If the process is a shell, this means interrupt current subjob\n\
+rather than the shell.\n\
+\n\
+If CURRENT-GROUP is `lambda', and if the shell owns the terminal,\n\
+don't send the signal.")
+  (process, current_group)
+     Lisp_Object process, current_group;
+{
+  process_send_signal (process, SIGINT, current_group, 0);
+  return process;
+}
+
+DEFUN ("kill-process", Fkill_process, Skill_process, 0, 2, 0,
+  "Kill process PROCESS.  May be process or name of one.\n\
+See function `interrupt-process' for more details on usage.")
+  (process, current_group)
+     Lisp_Object process, current_group;
+{
+  process_send_signal (process, SIGKILL, current_group, 0);
+  return process;
+}
+
+DEFUN ("quit-process", Fquit_process, Squit_process, 0, 2, 0,
+  "Send QUIT signal to process PROCESS.  May be process or name of one.\n\
+See function `interrupt-process' for more details on usage.")
+  (process, current_group)
+     Lisp_Object process, current_group;
+{
+  process_send_signal (process, SIGQUIT, current_group, 0);
+  return process;
+}
+
+DEFUN ("stop-process", Fstop_process, Sstop_process, 0, 2, 0,
+  "Stop process PROCESS.  May be process or name of one.\n\
+See function `interrupt-process' for more details on usage.")
+  (process, current_group)
+     Lisp_Object process, current_group;
+{
+#ifndef SIGTSTP
+  error ("no SIGTSTP support");
+#else
+  process_send_signal (process, SIGTSTP, current_group, 0);
+#endif
+  return process;
+}
+
+DEFUN ("continue-process", Fcontinue_process, Scontinue_process, 0, 2, 0,
+  "Continue process PROCESS.  May be process or name of one.\n\
+See function `interrupt-process' for more details on usage.")
+  (process, current_group)
+     Lisp_Object process, current_group;
+{
+#ifdef SIGCONT
+    process_send_signal (process, SIGCONT, current_group, 0);
+#else
+    error ("no SIGCONT support");
+#endif
+  return process;
+}
+
+DEFUN ("signal-process", Fsignal_process, Ssignal_process,
+  2, 2, "nProcess number: \nnSignal code: ",
+  "Send the process with process id PID the signal with code SIGCODE.\n\
+PID must be an integer.  The process need not be a child of this Emacs.\n\
+SIGCODE may be an integer, or a symbol whose name is a signal name.")
+  (pid, sigcode)
+     Lisp_Object pid, sigcode;
+{
+  CHECK_NUMBER (pid, 0);
+
+#define handle_signal(NAME, VALUE)		\
+  else if (!strcmp (name, NAME))		\
+    XSETINT (sigcode, VALUE)
+
+  if (INTEGERP (sigcode))
+    ;
+  else
+    {
+      unsigned char *name;
+
+      CHECK_SYMBOL (sigcode, 1);
+      name = XSYMBOL (sigcode)->name->data;
+
+      if (0)
+	;
+#ifdef SIGHUP
+      handle_signal ("SIGHUP", SIGHUP);
+#endif
+#ifdef SIGINT
+      handle_signal ("SIGINT", SIGINT);
+#endif
+#ifdef SIGQUIT
+      handle_signal ("SIGQUIT", SIGQUIT);
+#endif
+#ifdef SIGILL
+      handle_signal ("SIGILL", SIGILL);
+#endif
+#ifdef SIGABRT
+      handle_signal ("SIGABRT", SIGABRT);
+#endif
+#ifdef SIGEMT
+      handle_signal ("SIGEMT", SIGEMT);
+#endif
+#ifdef SIGKILL
+      handle_signal ("SIGKILL", SIGKILL);
+#endif
+#ifdef SIGFPE
+      handle_signal ("SIGFPE", SIGFPE);
+#endif
+#ifdef SIGBUS
+      handle_signal ("SIGBUS", SIGBUS);
+#endif
+#ifdef SIGSEGV
+      handle_signal ("SIGSEGV", SIGSEGV);
+#endif
+#ifdef SIGSYS
+      handle_signal ("SIGSYS", SIGSYS);
+#endif
+#ifdef SIGPIPE
+      handle_signal ("SIGPIPE", SIGPIPE);
+#endif
+#ifdef SIGALRM
+      handle_signal ("SIGALRM", SIGALRM);
+#endif
+#ifdef SIGTERM
+      handle_signal ("SIGTERM", SIGTERM);
+#endif
+#ifdef SIGURG
+      handle_signal ("SIGURG", SIGURG);
+#endif
+#ifdef SIGSTOP
+      handle_signal ("SIGSTOP", SIGSTOP);
+#endif
+#ifdef SIGTSTP
+      handle_signal ("SIGTSTP", SIGTSTP);
+#endif
+#ifdef SIGCONT
+      handle_signal ("SIGCONT", SIGCONT);
+#endif
+#ifdef SIGCHLD
+      handle_signal ("SIGCHLD", SIGCHLD);
+#endif
+#ifdef SIGTTIN
+      handle_signal ("SIGTTIN", SIGTTIN);
+#endif
+#ifdef SIGTTOU
+      handle_signal ("SIGTTOU", SIGTTOU);
+#endif
+#ifdef SIGIO
+      handle_signal ("SIGIO", SIGIO);
+#endif
+#ifdef SIGXCPU
+      handle_signal ("SIGXCPU", SIGXCPU);
+#endif
+#ifdef SIGXFSZ
+      handle_signal ("SIGXFSZ", SIGXFSZ);
+#endif
+#ifdef SIGVTALRM
+      handle_signal ("SIGVTALRM", SIGVTALRM);
+#endif
+#ifdef SIGPROF
+      handle_signal ("SIGPROF", SIGPROF);
+#endif
+#ifdef SIGWINCH
+      handle_signal ("SIGWINCH", SIGWINCH);
+#endif
+#ifdef SIGINFO
+      handle_signal ("SIGINFO", SIGINFO);
+#endif
+#ifdef SIGUSR1
+      handle_signal ("SIGUSR1", SIGUSR1);
+#endif
+#ifdef SIGUSR2
+      handle_signal ("SIGUSR2", SIGUSR2);
+#endif
+      else
+	error ("Undefined signal name %s", name);
+    }
+
+#undef handle_signal
+
+  return make_number (kill (XINT (pid), XINT (sigcode)));
+}
+
+DEFUN ("process-send-eof", Fprocess_send_eof, Sprocess_send_eof, 0, 1, 0,
+  "Make PROCESS see end-of-file in its input.\n\
+EOF comes after any text already sent to it.\n\
+PROCESS may be a process, a buffer, the name of a process or buffer, or\n\
+nil, indicating the current buffer's process.\n\
+If PROCESS is a network connection, or is a process communicating\n\
+through a pipe (as opposed to a pty), then you cannot send any more\n\
+text to PROCESS after you call this function.")
+  (process)
+     Lisp_Object process;
+{
+  Lisp_Object proc;
+  struct coding_system *coding;
+
+  proc = get_process (process);
+  coding = proc_encode_coding_system[XINT (XPROCESS (proc)->outfd)];
+
+  /* Make sure the process is really alive.  */
+  if (! NILP (XPROCESS (proc)->raw_status_low))
+    update_status (XPROCESS (proc));
+  if (! EQ (XPROCESS (proc)->status, Qrun))
+    error ("Process %s not running", XSTRING (XPROCESS (proc)->name)->data);
+
+  if (CODING_REQUIRE_FLUSHING (coding))
+    {
+      coding->mode |= CODING_MODE_LAST_BLOCK;
+      send_process (proc, "", 0, Qnil);
+    }
+
+#ifdef VMS
+  send_process (proc, "\032", 1, Qnil); 	/* ^z */
+#else
+  if (!NILP (XPROCESS (proc)->pty_flag))
+    send_process (proc, "\004", 1, Qnil);
+  else
+    {
+      int old_outfd, new_outfd;
+
+#ifdef HAVE_SHUTDOWN
+      /* If this is a network connection, or socketpair is used
+	 for communication with the subprocess, call shutdown to cause EOF.
+	 (In some old system, shutdown to socketpair doesn't work.
+	 Then we just can't win.)  */
+      if (NILP (XPROCESS (proc)->pid)
+	  || XINT (XPROCESS (proc)->outfd) == XINT (XPROCESS (proc)->infd))
+	shutdown (XINT (XPROCESS (proc)->outfd), 1);
+      /* In case of socketpair, outfd == infd, so don't close it.  */
+      if (XINT (XPROCESS (proc)->outfd) != XINT (XPROCESS (proc)->infd))
+	emacs_close (XINT (XPROCESS (proc)->outfd));
+#else /* not HAVE_SHUTDOWN */
+      emacs_close (XINT (XPROCESS (proc)->outfd));
+#endif /* not HAVE_SHUTDOWN */
+      new_outfd = emacs_open (NULL_DEVICE, O_WRONLY, 0);
+      old_outfd = XINT (XPROCESS (proc)->outfd);
+
+      if (!proc_encode_coding_system[new_outfd])
+	proc_encode_coding_system[new_outfd]
+	  = (struct coding_system *) xmalloc (sizeof (struct coding_system));
+      bcopy (proc_encode_coding_system[old_outfd],
+	     proc_encode_coding_system[new_outfd],
+	     sizeof (struct coding_system));
+      bzero (proc_encode_coding_system[old_outfd],
+	     sizeof (struct coding_system));
+
+      XSETINT (XPROCESS (proc)->outfd, new_outfd);
+    }
+#endif /* VMS */
+  return process;
+}
+
+/* Kill all processes associated with `buffer'.
+ If `buffer' is nil, kill all processes  */
+
+void
+kill_buffer_processes (buffer)
+     Lisp_Object buffer;
+{
+  Lisp_Object tail, proc;
+
+  for (tail = Vprocess_alist; GC_CONSP (tail); tail = XCDR (tail))
+    {
+      proc = XCDR (XCAR (tail));
+      if (GC_PROCESSP (proc)
+	  && (NILP (buffer) || EQ (XPROCESS (proc)->buffer, buffer)))
+	{
+	  if (NETCONN_P (proc))
+	    Fdelete_process (proc);
+	  else if (XINT (XPROCESS (proc)->infd) >= 0)
+	    process_send_signal (proc, SIGHUP, Qnil, 1);
+	}
+    }
+}
+
+/* On receipt of a signal that a child status has changed,
+ loop asking about children with changed statuses until
+ the system says there are no more.
+   All we do is change the status;
+ we do not run sentinels or print notifications.
+ That is saved for the next time keyboard input is done,
+ in order to avoid timing errors.  */
+
+/** WARNING: this can be called during garbage collection.
+ Therefore, it must not be fooled by the presence of mark bits in
+ Lisp objects.  */
+
+/** USG WARNING:  Although it is not obvious from the documentation
+ in signal(2), on a USG system the SIGCLD handler MUST NOT call
+ signal() before executing at least one wait(), otherwise the handler
+ will be called again, resulting in an infinite loop.  The relevant
+ portion of the documentation reads "SIGCLD signals will be queued
+ and the signal-catching function will be continually reentered until
+ the queue is empty".  Invoking signal() causes the kernel to reexamine
+ the SIGCLD queue.   Fred Fish, UniSoft Systems Inc. */
+
+SIGTYPE
+sigchld_handler (signo)
+     int signo;
+{
+  int old_errno = errno;
+  Lisp_Object proc;
+  register struct Lisp_Process *p;
+  extern EMACS_TIME *input_available_clear_time;
+
+#ifdef BSD4_1
+  extern int sigheld;
+  sigheld |= sigbit (SIGCHLD);
+#endif
+
+  while (1)
+    {
+      register int pid;
+      WAITTYPE w;
+      Lisp_Object tail;
+
+#ifdef WNOHANG
+#ifndef WUNTRACED
+#define WUNTRACED 0
+#endif /* no WUNTRACED */
+      /* Keep trying to get a status until we get a definitive result.  */
+      do 
+	{
+	  errno = 0;
+	  pid = wait3 (&w, WNOHANG | WUNTRACED, 0);
+	}
+      while (pid <= 0 && errno == EINTR);
+
+      if (pid <= 0)
+	{
+	  /* A real failure.  We have done all our job, so return.  */
+
+	  /* USG systems forget handlers when they are used;
+	     must reestablish each time */
+#if defined (USG) && !defined (POSIX_SIGNALS)
+	  signal (signo, sigchld_handler);   /* WARNING - must come after wait3() */
+#endif
+#ifdef  BSD4_1
+	  sigheld &= ~sigbit (SIGCHLD);
+	  sigrelse (SIGCHLD);
+#endif
+	  errno = old_errno;
+	  return;
+	}
+#else
+      pid = wait (&w);
+#endif /* no WNOHANG */
+
+      /* Find the process that signaled us, and record its status.  */
+
+      p = 0;
+      for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
+	{
+	  proc = XCDR (XCAR (tail));
+	  p = XPROCESS (proc);
+	  if (EQ (p->childp, Qt) && XFASTINT (p->pid) == pid)
+	    break;
+	  p = 0;
+	}
+
+      /* Look for an asynchronous process whose pid hasn't been filled
+	 in yet.  */
+      if (p == 0)
+	for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
+	  {
+	    proc = XCDR (XCAR (tail));
+	    p = XPROCESS (proc);
+	    if (INTEGERP (p->pid) && XINT (p->pid) == -1)
+	      break;
+	    p = 0;
+	  }
+      
+      /* Change the status of the process that was found.  */
+      if (p != 0)
+	{
+	  union { int i; WAITTYPE wt; } u;
+	  int clear_desc_flag = 0;
+	  
+	  XSETINT (p->tick, ++process_tick);
+	  u.wt = w;
+	  XSETINT (p->raw_status_low, u.i & 0xffff);
+	  XSETINT (p->raw_status_high, u.i >> 16);
+	  
+	  /* If process has terminated, stop waiting for its output.  */
+	  if ((WIFSIGNALED (w) || WIFEXITED (w))
+	      && XINT (p->infd) >= 0)
+	    clear_desc_flag = 1;
+
+	  /* We use clear_desc_flag to avoid a compiler bug in Microsoft C.  */
+	  if (clear_desc_flag)
+	    {
+	      FD_CLR (XINT (p->infd), &input_wait_mask);
+	      FD_CLR (XINT (p->infd), &non_keyboard_wait_mask);
+	    }
+
+	  /* Tell wait_reading_process_input that it needs to wake up and
+	     look around.  */
+	  if (input_available_clear_time)
+	    EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
+	}
+
+	/* There was no asynchronous process found for that id.  Check
+	   if we have a synchronous process.  */
+      else
+	{
+	  synch_process_alive = 0;
+
+	  /* Report the status of the synchronous process.  */
+	  if (WIFEXITED (w))
+	    synch_process_retcode = WRETCODE (w);
+	  else if (WIFSIGNALED (w))
+	    {
+	      int code = WTERMSIG (w);
+	      char *signame;
+
+	      synchronize_system_messages_locale ();
+	      signame = strsignal (code);
+
+	      if (signame == 0)
+		signame = "unknown";
+
+	      synch_process_death = signame;
+	    }
+
+	  /* Tell wait_reading_process_input that it needs to wake up and
+	     look around.  */
+	  if (input_available_clear_time)
+	    EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
+	}
+
+      /* On some systems, we must return right away.
+	 If any more processes want to signal us, we will
+	 get another signal.
+	 Otherwise (on systems that have WNOHANG), loop around
+	 to use up all the processes that have something to tell us.  */
+#if defined (USG) && ! (defined (HPUX) && defined (WNOHANG)) || defined (WINDOWSNT)
+#if defined (USG) && ! defined (POSIX_SIGNALS)
+      signal (signo, sigchld_handler);
+#endif
+      errno = old_errno;
+      return;
+#endif /* USG, but not HPUX with WNOHANG */
+    }
+}
+
+
+static Lisp_Object
+exec_sentinel_unwind (data)
+     Lisp_Object data;
+{
+  XPROCESS (XCAR (data))->sentinel = XCDR (data);
+  return Qnil;
+}
+
+static Lisp_Object
+exec_sentinel_error_handler (error)
+     Lisp_Object error;
+{
+  cmd_error_internal (error, "error in process sentinel: ");
+  Vinhibit_quit = Qt;
+  update_echo_area ();
+  Fsleep_for (make_number (2), Qnil);
+}
+
+static void
+exec_sentinel (proc, reason)
+     Lisp_Object proc, reason;
+{
+  Lisp_Object sentinel, obuffer, odeactivate, okeymap;
+  register struct Lisp_Process *p = XPROCESS (proc);
+  int count = specpdl_ptr - specpdl;
+  int outer_running_asynch_code = running_asynch_code;
+  int waiting = waiting_for_user_input_p;
+
+  /* No need to gcpro these, because all we do with them later
+     is test them for EQness, and none of them should be a string.  */
+  odeactivate = Vdeactivate_mark;
+  XSETBUFFER (obuffer, current_buffer);
+  okeymap = current_buffer->keymap;
+
+  sentinel = p->sentinel;
+  if (NILP (sentinel))
+    return;
+
+  /* Zilch the sentinel while it's running, to avoid recursive invocations;
+     assure that it gets restored no matter how the sentinel exits.  */
+  p->sentinel = Qnil;
+  record_unwind_protect (exec_sentinel_unwind, Fcons (proc, sentinel));
+  /* Inhibit quit so that random quits don't screw up a running filter.  */
+  specbind (Qinhibit_quit, Qt);
+  specbind (Qlast_nonmenu_event, Qt);
+
+  /* In case we get recursively called,
+     and we already saved the match data nonrecursively,
+     save the same match data in safely recursive fashion.  */
+  if (outer_running_asynch_code)
+    {
+      Lisp_Object tem;
+      tem = Fmatch_data (Qnil, Qnil);
+      restore_match_data ();
+      record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
+      Fset_match_data (tem);
+    }
+
+  /* For speed, if a search happens within this code,
+     save the match data in a special nonrecursive fashion.  */
+  running_asynch_code = 1;
+
+  internal_condition_case_1 (read_process_output_call,
+			     Fcons (sentinel,
+				    Fcons (proc, Fcons (reason, Qnil))),
+			     !NILP (Vdebug_on_error) ? Qnil : Qerror,
+			     exec_sentinel_error_handler);
+
+  /* If we saved the match data nonrecursively, restore it now.  */
+  restore_match_data ();
+  running_asynch_code = outer_running_asynch_code;
+
+  Vdeactivate_mark = odeactivate;
+
+  /* Restore waiting_for_user_input_p as it was
+     when we were called, in case the filter clobbered it.  */
+  waiting_for_user_input_p = waiting;
+
+#if 0
+  if (! EQ (Fcurrent_buffer (), obuffer)
+      || ! EQ (current_buffer->keymap, okeymap))
+#endif
+    /* But do it only if the caller is actually going to read events.
+       Otherwise there's no need to make him wake up, and it could
+       cause trouble (for example it would make Fsit_for return).  */
+    if (waiting_for_user_input_p == -1)
+      record_asynch_buffer_change ();
+
+  unbind_to (count, Qnil);
+}
+
+/* Report all recent events of a change in process status
+   (either run the sentinel or output a message).
+   This is done while Emacs is waiting for keyboard input.  */
+
+void
+status_notify ()
+{
+  register Lisp_Object proc, buffer;
+  Lisp_Object tail, msg;
+  struct gcpro gcpro1, gcpro2;
+
+  tail = Qnil;
+  msg = Qnil;
+  /* We need to gcpro tail; if read_process_output calls a filter
+     which deletes a process and removes the cons to which tail points
+     from Vprocess_alist, and then causes a GC, tail is an unprotected
+     reference.  */
+  GCPRO2 (tail, msg);
+
+  /* Set this now, so that if new processes are created by sentinels
+     that we run, we get called again to handle their status changes.  */
+  update_tick = process_tick;
+
+  for (tail = Vprocess_alist; !NILP (tail); tail = Fcdr (tail))
+    {
+      Lisp_Object symbol;
+      register struct Lisp_Process *p;
+
+      proc = Fcdr (Fcar (tail));
+      p = XPROCESS (proc);
+
+      if (XINT (p->tick) != XINT (p->update_tick))
+	{
+	  XSETINT (p->update_tick, XINT (p->tick));
+
+	  /* If process is still active, read any output that remains.  */
+	  while (! EQ (p->filter, Qt)
+		 && XINT (p->infd) >= 0
+		 && read_process_output (proc, XINT (p->infd)) > 0);
+
+	  buffer = p->buffer;
+
+	  /* Get the text to use for the message.  */
+	  if (!NILP (p->raw_status_low))
+	    update_status (p);
+	  msg = status_message (p->status);
+
+	  /* If process is terminated, deactivate it or delete it.  */
+	  symbol = p->status;
+	  if (CONSP (p->status))
+	    symbol = XCAR (p->status);
+
+	  if (EQ (symbol, Qsignal) || EQ (symbol, Qexit)
+	      || EQ (symbol, Qclosed))
+	    {
+	      if (delete_exited_processes)
+		remove_process (proc);
+	      else
+		deactivate_process (proc);
+	    }
+
+	  /* The actions above may have further incremented p->tick.
+	     So set p->update_tick again
+	     so that an error in the sentinel will not cause
+	     this code to be run again.  */
+	  XSETINT (p->update_tick, XINT (p->tick));
+	  /* Now output the message suitably.  */
+	  if (!NILP (p->sentinel))
+	    exec_sentinel (proc, msg);
+	  /* Don't bother with a message in the buffer
+	     when a process becomes runnable.  */
+	  else if (!EQ (symbol, Qrun) && !NILP (buffer))
+	    {
+	      Lisp_Object ro, tem;
+	      struct buffer *old = current_buffer;
+	      int opoint, opoint_byte;
+	      int before, before_byte;
+
+	      ro = XBUFFER (buffer)->read_only;
+
+	      /* Avoid error if buffer is deleted
+		 (probably that's why the process is dead, too) */
+	      if (NILP (XBUFFER (buffer)->name))
+		continue;
+	      Fset_buffer (buffer);
+
+	      opoint = PT;
+	      opoint_byte = PT_BYTE;
+	      /* Insert new output into buffer
+		 at the current end-of-output marker,
+		 thus preserving logical ordering of input and output.  */
+	      if (XMARKER (p->mark)->buffer)
+		Fgoto_char (p->mark);
+	      else
+		SET_PT_BOTH (ZV, ZV_BYTE);
+
+	      before = PT;
+	      before_byte = PT_BYTE;
+
+	      tem = current_buffer->read_only;
+	      current_buffer->read_only = Qnil;
+	      insert_string ("\nProcess ");
+	      Finsert (1, &p->name);
+	      insert_string (" ");
+	      Finsert (1, &msg);
+	      current_buffer->read_only = tem;
+	      set_marker_both (p->mark, p->buffer, PT, PT_BYTE);
+
+	      if (opoint >= before)
+		SET_PT_BOTH (opoint + (PT - before),
+			     opoint_byte + (PT_BYTE - before_byte));
+	      else
+		SET_PT_BOTH (opoint, opoint_byte);
+
+	      set_buffer_internal (old);
+	    }
+	}
+    } /* end for */
+
+  update_mode_lines++;  /* in case buffers use %s in mode-line-format */
+  redisplay_preserve_echo_area ();
+
+  UNGCPRO;
+}
+
+
+DEFUN ("set-process-coding-system", Fset_process_coding_system,
+       Sset_process_coding_system, 1, 3, 0,
+  "Set coding systems of PROCESS to DECODING and ENCODING.\n\
+DECODING will be used to decode subprocess output and ENCODING to\n\
+encode subprocess input.")
+  (proc, decoding, encoding)
+     register Lisp_Object proc, decoding, encoding;
+{
+  register struct Lisp_Process *p;
+
+  CHECK_PROCESS (proc, 0);
+  p = XPROCESS (proc);
+  if (XINT (p->infd) < 0)
+    error ("Input file descriptor of %s closed", XSTRING (p->name)->data);
+  if (XINT (p->outfd) < 0)
+    error ("Output file descriptor of %s closed", XSTRING (p->name)->data);
+
+  p->decode_coding_system = Fcheck_coding_system (decoding);
+  p->encode_coding_system = Fcheck_coding_system (encoding);
+  setup_coding_system (decoding,
+		       proc_decode_coding_system[XINT (p->infd)]);
+  setup_coding_system (encoding,
+		       proc_encode_coding_system[XINT (p->outfd)]);
+
+  return Qnil;
+}
+
+DEFUN ("process-coding-system",
+       Fprocess_coding_system, Sprocess_coding_system, 1, 1, 0,
+  "Return a cons of coding systems for decoding and encoding of PROCESS.")
+  (proc)
+     register Lisp_Object proc;
+{
+  CHECK_PROCESS (proc, 0);
+  return Fcons (XPROCESS (proc)->decode_coding_system,
+		XPROCESS (proc)->encode_coding_system);
+}
+
+/* The first time this is called, assume keyboard input comes from DESC
+   instead of from where we used to expect it.
+   Subsequent calls mean assume input keyboard can come from DESC
+   in addition to other places.  */
+
+static int add_keyboard_wait_descriptor_called_flag;
+
+void
+add_keyboard_wait_descriptor (desc)
+     int desc;
+{
+  if (! add_keyboard_wait_descriptor_called_flag)
+    FD_CLR (0, &input_wait_mask);
+  add_keyboard_wait_descriptor_called_flag = 1;
+  FD_SET (desc, &input_wait_mask);
+  FD_SET (desc, &non_process_wait_mask);
+  if (desc > max_keyboard_desc)
+    max_keyboard_desc = desc;
+}
+
+/* From now on, do not expect DESC to give keyboard input.  */
+
+void
+delete_keyboard_wait_descriptor (desc)
+     int desc;
+{
+  int fd;
+  int lim = max_keyboard_desc;
+
+  FD_CLR (desc, &input_wait_mask);
+  FD_CLR (desc, &non_process_wait_mask);
+
+  if (desc == max_keyboard_desc)
+    for (fd = 0; fd < lim; fd++)
+      if (FD_ISSET (fd, &input_wait_mask)
+	  && !FD_ISSET (fd, &non_keyboard_wait_mask))
+	max_keyboard_desc = fd;
+}
+
+/* Return nonzero if *MASK has a bit set
+   that corresponds to one of the keyboard input descriptors.  */
+
+int
+keyboard_bit_set (mask)
+     SELECT_TYPE *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;
+}
+
+void
+init_process ()
+{
+  register int i;
+
+#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;
+
+  FD_SET (0, &input_wait_mask);
+
+  Vprocess_alist = Qnil;
+  for (i = 0; i < MAXDESC; i++)
+    {
+      chan_process[i] = Qnil;
+      proc_buffered_char[i] = -1;
+    }
+  bzero (proc_decode_coding_system, sizeof proc_decode_coding_system);
+  bzero (proc_encode_coding_system, sizeof proc_encode_coding_system);
+
+  Vdefault_process_coding_system
+    = (NILP (buffer_defaults.enable_multibyte_characters)
+       ? Fcons (Qraw_text, Qnil)
+       : Fcons (Qemacs_mule, Qnil));
+}
+
+void
+syms_of_process ()
+{
+  Qprocessp = intern ("processp");
+  staticpro (&Qprocessp);
+  Qrun = intern ("run");
+  staticpro (&Qrun);
+  Qstop = intern ("stop");
+  staticpro (&Qstop);
+  Qsignal = intern ("signal");
+  staticpro (&Qsignal);
+
+  /* Qexit is already staticpro'd by syms_of_eval; don't staticpro it
+     here again.
+
+     Qexit = intern ("exit");
+     staticpro (&Qexit); */
+
+  Qopen = intern ("open");
+  staticpro (&Qopen);
+  Qclosed = intern ("closed");
+  staticpro (&Qclosed);
+
+  Qlast_nonmenu_event = intern ("last-nonmenu-event");
+  staticpro (&Qlast_nonmenu_event);
+
+  staticpro (&Vprocess_alist);
+
+  DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes,
+    "*Non-nil means delete processes immediately when they exit.\n\
+nil means don't delete them until `list-processes' is run.");
+
+  delete_exited_processes = 1;
+
+  DEFVAR_LISP ("process-connection-type", &Vprocess_connection_type,
+    "Control type of device used to communicate with subprocesses.\n\
+Values are nil to use a pipe, or t or `pty' to use a pty.\n\
+The value has no effect if the system has no ptys or if all ptys are busy:\n\
+then a pipe is used in any case.\n\
+The value takes effect when `start-process' is called.");
+  Vprocess_connection_type = Qt;
+
+  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 (&Sprocess_kill_without_query);
+  defsubr (&Sprocess_contact);
+  defsubr (&Slist_processes);
+  defsubr (&Sprocess_list);
+  defsubr (&Sstart_process);
+#ifdef HAVE_SOCKETS
+  defsubr (&Sopen_network_stream);
+#endif /* HAVE_SOCKETS */
+  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_connection); */
+  defsubr (&Sset_process_coding_system);
+  defsubr (&Sprocess_coding_system);
+}
+
+
+#else /* not subprocesses */
+
+#include <sys/types.h>
+#include <errno.h>
+
+#include "lisp.h"
+#include "systime.h"
+#include "charset.h"
+#include "coding.h"
+#include "termopts.h"
+#include "sysselect.h"
+
+extern int frame_garbaged;
+
+extern EMACS_TIME timer_check ();
+extern int timers_run;
+
+/* As described above, except assuming that there are no subprocesses:
+
+   Wait for timeout to elapse and/or keyboard input to be available.
+
+   time_limit is:
+     timeout in seconds, or
+     zero for no limit, or
+     -1 means gobble data immediately available but don't wait for any.
+
+   read_kbd is a Lisp_Object:
+     0 to ignore keyboard input, or
+     1 to return when input is available, or
+     -1 means caller will actually read the input, so don't throw to
+       the quit handler.
+     a cons cell, meaning wait until its car is non-nil
+       (and gobble terminal input into the buffer if any arrives), or
+     We know that read_kbd will never be a Lisp_Process, since
+     `subprocesses' isn't defined.
+
+   do_display != 0 means redisplay should be done to show subprocess
+   output that arrives.
+
+   Return true iff we received input from any process.  */
+
+int
+wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
+     int time_limit, microsecs;
+     Lisp_Object read_kbd;
+     int do_display;
+{
+  register int nfds;
+  EMACS_TIME end_time, timeout;
+  SELECT_TYPE waitchannels;
+  int xerrno;
+  Lisp_Object *wait_for_cell = 0;
+
+  /* If waiting for non-nil in a cell, record where.  */
+  if (CONSP (read_kbd))
+    {
+      wait_for_cell = &XCAR (read_kbd);
+      XSETFASTINT (read_kbd, 0);
+    }
+
+  /* What does time_limit really mean?  */
+  if (time_limit || microsecs)
+    {
+      EMACS_GET_TIME (end_time);
+      EMACS_SET_SECS_USECS (timeout, time_limit, microsecs);
+      EMACS_ADD_TIME (end_time, end_time, timeout);
+    }
+
+  /* Turn off periodic alarms (in case they are in use)
+     because the select emulator uses alarms.  */
+  turn_on_atimers (0);
+
+  while (1)
+    {
+      int timeout_reduced_for_timers = 0;
+
+      /* If calling from keyboard input, do not quit
+	 since we want to return C-g as an input character.
+	 Otherwise, do pending quit if requested.  */
+      if (XINT (read_kbd) >= 0)
+	QUIT;
+
+      /* Exit now if the cell we're waiting for became non-nil.  */
+      if (wait_for_cell && ! NILP (*wait_for_cell))
+	break;
+
+      /* Compute time from now till when time limit is up */
+      /* Exit if already run out */
+      if (time_limit == -1)
+	{
+	  /* -1 specified for timeout means
+	     gobble output available now
+	     but don't wait at all. */
+
+	  EMACS_SET_SECS_USECS (timeout, 0, 0);
+	}
+      else if (time_limit || microsecs)
+	{
+	  EMACS_GET_TIME (timeout);
+	  EMACS_SUB_TIME (timeout, end_time, timeout);
+	  if (EMACS_TIME_NEG_P (timeout))
+	    break;
+	}
+      else
+	{
+	  EMACS_SET_SECS_USECS (timeout, 100000, 0);
+	}
+
+      /* If our caller will not immediately handle keyboard events,
+	 run timer events directly.
+	 (Callers that will immediately read keyboard events
+	 call timer_delay on their own.)  */
+      if (! wait_for_cell)
+	{
+	  EMACS_TIME timer_delay;
+	  int old_timers_run;
+
+	retry:
+	  old_timers_run = timers_run;
+	  timer_delay = timer_check (1);
+	  if (timers_run != old_timers_run && do_display)
+	    {
+	      redisplay_preserve_echo_area ();
+	      /* We must retry, since a timer may have requeued itself
+		 and that could alter the time delay.  */
+	      goto retry;
+	    }
+
+	  /* If there is unread keyboard input, also return.  */
+	  if (XINT (read_kbd) != 0
+	      && requeued_events_pending_p ())
+	    break;
+
+	  if (! EMACS_TIME_NEG_P (timer_delay) && time_limit != -1)
+	    {
+	      EMACS_TIME difference;
+	      EMACS_SUB_TIME (difference, timer_delay, timeout);
+	      if (EMACS_TIME_NEG_P (difference))
+		{
+		  timeout = timer_delay;
+		  timeout_reduced_for_timers = 1;
+		}
+	    }
+	}
+
+      /* Cause C-g and alarm signals to take immediate action,
+	 and cause input available signals to zero out timeout.  */
+      if (XINT (read_kbd) < 0)
+	set_waiting_for_input (&timeout);
+
+      /* Wait till there is something to do.  */
+
+      if (! XINT (read_kbd) && wait_for_cell == 0)
+	FD_ZERO (&waitchannels);
+      else
+	FD_SET (0, &waitchannels);
+
+      /* If a frame has been newly mapped and needs updating,
+	 reprocess its display stuff.  */
+      if (frame_garbaged && do_display)
+	{
+	  clear_waiting_for_input ();
+	  redisplay_preserve_echo_area ();
+	  if (XINT (read_kbd) < 0)
+	    set_waiting_for_input (&timeout);
+	}
+
+      if (XINT (read_kbd) && detect_input_pending ())
+	{
+	  nfds = 0;
+	  FD_ZERO (&waitchannels);
+	}
+      else
+	nfds = select (1, &waitchannels, (SELECT_TYPE *)0, (SELECT_TYPE *)0,
+		       &timeout);
+
+      xerrno = errno;
+
+      /* Make C-g and alarm signals set flags again */
+      clear_waiting_for_input ();
+
+      /*  If we woke up due to SIGWINCH, actually change size now.  */
+      do_pending_window_change (0);
+
+      if (time_limit && nfds == 0 && ! timeout_reduced_for_timers)
+	/* We waited the full specified time, so return now.  */
+	break;
+
+      if (nfds == -1)
+	{
+	  /* If the system call was interrupted, then go around the
+	     loop again.  */
+	  if (xerrno == EINTR)
+	    FD_ZERO (&waitchannels);
+	  else
+	    error ("select error: %s", emacs_strerror (xerrno));
+	}
+#ifdef sun
+      else if (nfds > 0 && (waitchannels & 1)  && interrupt_input)
+	/* System sometimes fails to deliver SIGIO.  */
+	kill (getpid (), SIGIO);
+#endif
+#ifdef SIGIO
+      if (XINT (read_kbd) && interrupt_input && (waitchannels & 1))
+	kill (getpid (), SIGIO);
+#endif
+
+      /* Check for keyboard input */
+
+      if ((XINT (read_kbd) != 0)
+	  && detect_input_pending_run_timers (do_display))
+	{
+	  swallow_events (do_display);
+	  if (detect_input_pending_run_timers (do_display))
+	    break;
+	}
+
+      /* If there is unread keyboard input, also return.  */
+      if (XINT (read_kbd) != 0
+	  && requeued_events_pending_p ())
+	break;
+
+      /* If wait_for_cell. check for keyboard input
+	 but don't run any timers.
+	 ??? (It seems wrong to me to check for keyboard
+	 input at all when wait_for_cell, but the code
+	 has been this way since July 1994.
+	 Try changing this after version 19.31.)  */
+      if (wait_for_cell
+	  && detect_input_pending ())
+	{
+	  swallow_events (do_display);
+	  if (detect_input_pending ())
+	    break;
+	}
+
+      /* Exit now if the cell we're waiting for became non-nil.  */
+      if (wait_for_cell && ! NILP (*wait_for_cell))
+	break;
+    }
+
+  start_polling ();
+
+  return 0;
+}
+
+
+DEFUN ("get-buffer-process", Fget_buffer_process, Sget_buffer_process, 1, 1, 0,
+  /* Don't confuse make-docfile by having two doc strings for this function.
+     make-docfile does not pay attention to #if, for good reason!  */
+  0)
+  (name)
+     register Lisp_Object name;
+{
+  return Qnil;
+}
+
+DEFUN ("process-inherit-coding-system-flag",
+  Fprocess_inherit_coding_system_flag, Sprocess_inherit_coding_system_flag,
+  1, 1, 0,
+  /* Don't confuse make-docfile by having two doc strings for this function.
+     make-docfile does not pay attention to #if, for good reason!  */
+  0)
+  (process)
+     register Lisp_Object process;
+{
+  /* Ignore the argument and return the value of
+     inherit-process-coding-system.  */
+  return inherit_process_coding_system ? Qt : Qnil;
+}
+
+/* Kill all processes associated with `buffer'.
+   If `buffer' is nil, kill all processes.
+   Since we have no subprocesses, this does nothing.  */
+
+void
+kill_buffer_processes (buffer)
+     Lisp_Object buffer;
+{
+}
+
+void
+init_process ()
+{
+}
+
+void
+syms_of_process ()
+{
+  defsubr (&Sget_buffer_process);
+  defsubr (&Sprocess_inherit_coding_system_flag);
+}
+
+
+#endif /* not subprocesses */