]> code.delx.au - gnu-emacs/blobdiff - src/process.c
* Makefile.in (doxemacs, dotemacs): Explicitly pass along the CC
[gnu-emacs] / src / process.c
index 8ddfe240eb69ddbf81f14f3e298c538d5eb23ded..35a30540c02f36dc2faddf8442b4c35c5968534a 100644 (file)
@@ -22,8 +22,15 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "config.h"
 
+/* This file is split into two parts by the following preprocessor
+   conditional.  The 'then' clause contains all of the support for
+   asynchronous subprocesses.  The 'else' clause contains stub
+   versions of some of the asynchronous subprocess routines that are
+   often called elsewhere in Emacs, so we don't have to #ifdef the
+   sections that call them.  */
+
+\f
 #ifdef subprocesses
-/* The entire file is within this conditional */
 
 #include <stdio.h>
 #include <errno.h>
@@ -41,58 +48,21 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #if defined(BSD) || defined(STRIDE)
 #include <sys/ioctl.h>
-#if !defined (O_NDELAY) && defined (HAVE_PTYS)
+#if !defined (O_NDELAY) && defined (HAVE_PTYS) && !defined(USG5)
 #include <fcntl.h>
 #endif /* HAVE_PTYS and no O_NDELAY */
 #endif /* BSD or STRIDE */
-#ifdef USG
-#ifdef HAVE_TERMIOS
-#include <termios.h>
-#else
-#include <termio.h>
-#endif
-#include <fcntl.h>
-#endif /* USG */
 
 #ifdef NEED_BSDTTY
 #include <bsdtty.h>
 #endif
 
-#ifdef HPUX
-#undef TIOCGPGRP
-#endif
-
 #ifdef IRIS
 #include <sys/sysmacros.h>     /* for "minor" */
 #endif /* not IRIS */
 
 #include "systime.h"
-
-#if defined (HPUX) && defined (HAVE_PTYS)
-#include <sys/ptyio.h>
-#endif
-
-#ifdef AIX
-#include <sys/pty.h>
-#include <unistd.h>
-#endif
-
-#ifdef SYSV_PTYS
-#include <sys/tty.h>
-#ifdef titan
-#include <sys/ttyhw.h>
-#include <sys/stream.h>
-#endif
-#include <sys/pty.h>
-#endif
-
-#ifdef XENIX
-#undef TIOCGETC  /* Avoid confusing some conditionals that test this.  */
-#endif
-
-#ifdef BROKEN_TIOCGETC
-#undef TIOCGETC
-#endif
+#include "systty.h"
 
 #include "lisp.h"
 #include "window.h"
@@ -101,8 +71,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "termhooks.h"
 #include "termopts.h"
 #include "commands.h"
-
-extern int screen_garbaged;
+#include "dispextern.h"
 
 Lisp_Object Qrun, Qstop, Qsignal, Qopen, Qclosed;
 /* Qexit is declared and initialized in eval.c.  */
@@ -142,15 +111,16 @@ static Lisp_Object stream_process;
 #ifndef VMS
 #ifndef WAITTYPE
 #if !defined (BSD) && !defined (UNIPLUS) && !defined (STRIDE) && !(defined (HPUX) && !defined (NOMULTIPLEJOBS)) && !defined (HAVE_WAIT_HEADER)
-mis;tak-+;;:
 #define WAITTYPE int
 #define WIFSTOPPED(w) ((w&0377) == 0177)
 #define WIFSIGNALED(w) ((w&0377) != 0177 && (w&~0377) == 0)
 #define WIFEXITED(w) ((w&0377) == 0)
 #define WRETCODE(w) (w >> 8)
 #define WSTOPSIG(w) (w >> 8)
-#define WCOREDUMP(w) ((w&0200) != 0)
 #define WTERMSIG(w) (w & 0377)
+#ifndef WCOREDUMP
+#define WCOREDUMP(w) ((w&0200) != 0)
+#endif
 #else 
 #ifdef BSD4_1
 #include <wait.h>
@@ -306,6 +276,8 @@ int proc_buffered_char[MAXDESC];
 /* Compute the Lisp form of the process status, p->status, from
    the numeric status that was returned by `wait'.  */
 
+Lisp_Object status_convert ();
+
 update_status (p)
      struct Lisp_Process *p;
 {
@@ -358,7 +330,7 @@ decode_status (l, symbol, code, coredump)
       *symbol = XCONS (l)->car;
       tem = XCONS (l)->cdr;
       *code = XFASTINT (XCONS (tem)->car);
-      tem = XFASTINT (XCONS (tem)->cdr);
+      tem = XCONS (tem)->cdr;
       *coredump = !NILP (tem);
     }
 }
@@ -396,7 +368,6 @@ status_message (status)
 }
 \f
 #ifdef HAVE_PTYS
-static pty_process;
 
 /* Open an available pty, returning a file descriptor.
    Return -1 on failure.
@@ -412,6 +383,13 @@ allocate_pty ()
   register 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
@@ -421,33 +399,36 @@ allocate_pty ()
       {
 #ifdef PTY_NAME_SPRINTF
        PTY_NAME_SPRINTF
-#else
-#ifdef HPUX
-       sprintf (pty_name, "/dev/ptym/pty%c%x", c, i);
-#else
-#ifdef RTU
-       sprintf (pty_name, "/dev/pty%x", i);
 #else
        sprintf (pty_name, "/dev/pty%c%x", c, i);
-#endif /* not RTU */
-#endif /* not HPUX */
 #endif /* no PTY_NAME_SPRINTF */
 
-#ifndef IRIS
-       if (stat (pty_name, &stb) < 0)
+#ifdef PTY_OPEN
+       PTY_OPEN;
+#else /* no PTY_OPEN */
+#ifdef IRIS
+       /* Unusual IRIS code */
+       *ptyv = 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 = open (pty_name, O_RDWR | O_NONBLOCK, 0);
 #else
        fd = open (pty_name, O_RDWR | O_NDELAY, 0);
 #endif
-#else /* Unusual IRIS code */
-       *ptyv = open ("/dev/ptc", O_RDWR | O_NDELAY, 0);
-       if (fd < 0)
-         return -1;
-       if (fstat (fd, &stb) < 0)
-         return -1;
-#endif /* IRIS */
+#endif /* not IRIS */
+#endif /* no PTY_OPEN */
 
        if (fd >= 0)
          {
@@ -455,21 +436,8 @@ allocate_pty ()
               this avoids a nasty yet stupid bug in rlogins */
 #ifdef PTY_TTY_NAME_SPRINTF
            PTY_TTY_NAME_SPRINTF
-#else
-           /* TODO: In version 19, make these special cases use the macro above.  */
-#ifdef HPUX
-            sprintf (pty_name, "/dev/pty/tty%c%x", c, i);
-#else
-#ifdef RTU
-            sprintf (pty_name, "/dev/ttyp%x", i);
-#else
-#ifdef IRIS
-           sprintf (pty_name, "/dev/ttyq%d", minor (stb.st_rdev));
 #else
             sprintf (pty_name, "/dev/tty%c%x", c, i);
-#endif /* not IRIS */
-#endif /* not RTU */
-#endif /* not HPUX */
 #endif /* no PTY_TTY_NAME_SPRINTF */
 #ifndef UNIPLUS
            if (access (pty_name, 6) != 0)
@@ -588,7 +556,10 @@ BUFFER may be a buffer or the name of one.")
   return Qnil;
 }
 
-/* This is how commands for the user decode process arguments */
+/* 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.  */
 
 Lisp_Object
 get_process (name)
@@ -616,7 +587,8 @@ get_process (name)
 
 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 or the name of one, or a buffer name.")
+PROCESS may be a process, a buffer, the name of a process or buffer, or\n\
+nil, indicating the current buffer's process.")
   (proc)
      register Lisp_Object proc;
 {
@@ -649,7 +621,9 @@ 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.")
+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 buffer, or\n\
+nil, indicating the current buffer's process.")
 /* command -- for a command channel opened to Emacs by another process.\n\
    external -- for an i/o channel opened to Emacs by another process.\n\  */
   (proc)
@@ -657,7 +631,7 @@ nil -- if arg is a process name and no such process exists.")
 {
   register struct Lisp_Process *p;
   register Lisp_Object status;
-  proc = Fget_process (proc);
+  proc = get_process (proc);
   if (NILP (proc))
     return proc;
   p = XPROCESS (proc);
@@ -1089,11 +1063,8 @@ create_process (process, new_argv)
 #endif
   int pty_flag = 0;
   Lisp_Object current_dir;
-  char **env;
   extern char **environ;
 
-  env = environ;
-
   inchannel = outchannel = -1;
 
 #ifdef HAVE_PTYS
@@ -1230,6 +1201,11 @@ create_process (process, new_argv)
        /* First, disconnect its current controlling terminal.  */
 #ifdef HAVE_SETSID
        setsid ();
+#ifdef TIOCSCTTY
+       /* Make the pty's terminal the controlling terminal.  */
+       if (pty_flag && (ioctl (xforkin, TIOCSCTTY, 0) < 0))
+         abort ();
+#endif
 #else /* not HAVE_SETSID */
 #ifdef USG
        /* It's very important to call setpgrp() here and no time
@@ -1291,14 +1267,16 @@ create_process (process, new_argv)
 #if defined (BSD) || defined (UNIPLUS) || defined (HPUX)
        sigsetmask (SIGEMPTYMASK);
 #else /* ordinary USG */
+#if 0
        signal (SIGCHLD, sigchld);
+#endif
 #endif /* ordinary USG */
 #endif /* not BSD4_1 */
 #endif /* SIGCHLD */
 
        child_setup_tty (xforkout);
        child_setup (xforkin, xforkout, xforkout,
-                    new_argv, env, 1, current_dir);
+                    new_argv, 1, current_dir);
       }
     environ = save_environ;
   }
@@ -1583,6 +1561,8 @@ Return non-nil iff we received any output before the timeout expired.")
          }
       }
     }
+  else
+    useconds = 0;
 
   if (! NILP (timeout))
     {
@@ -1599,10 +1579,11 @@ Return non-nil iff we received any output before the timeout expired.")
        seconds = 0;
     }
 
+  if (NILP (proc))
+    XFASTINT (proc) = 0;
+
   return
-    (wait_reading_process_input (seconds, useconds,
-                                (NILP (proc)
-                                 ? XPROCESS (get_process (proc)) : 0), 0)
+    (wait_reading_process_input (seconds, useconds, proc, 0)
      ? Qt : Qnil);
 }
 
@@ -1622,14 +1603,14 @@ static int waiting_for_user_input_p;
      zero for no limit, or
      -1 means gobble data immediately available but don't wait for any.
 
-   read_kbd is:
+   read_kbd is a lisp value:
      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, or
-     a pointer to a struct Lisp_Process, meaning wait until something
-       arrives from that process.  The return value is true iff we read
-       some input from that process.
+     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.
@@ -1640,7 +1621,9 @@ static int waiting_for_user_input_p;
    Otherwise, return true iff we recieved input from any process.  */
 
 wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
-     int time_limit, microsecs, read_kbd, do_display;
+     int time_limit, microsecs;
+     Lisp_Object read_kbd;
+     int do_display;
 {
   register int channel, nfds, m;
   static SELECT_TYPE Available;
@@ -1654,15 +1637,16 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
 
   FD_ZERO (&Available);
 
-  /* Detect when read_kbd is really the address of a Lisp_Process.  */
-  if (read_kbd > 10 || read_kbd < -1)
+  /* If read_kbd is a process to watch, set wait_proc and wait_channel
+     accordingly.  */
+  if (XTYPE (read_kbd) == Lisp_Process)
     {
-      wait_proc = (struct Lisp_Process *) read_kbd;
+      wait_proc = XPROCESS (read_kbd);
       wait_channel = XFASTINT (wait_proc->infd);
-      read_kbd = 0;
+      XFASTINT (read_kbd) = 0;
     }
 
-  waiting_for_user_input_p = read_kbd;
+  waiting_for_user_input_p = XINT (read_kbd);
 
   /* Since we may need to wait several times,
      compute the absolute time to return at.  */
@@ -1673,16 +1657,12 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
       EMACS_ADD_TIME (end_time, end_time, timeout);
     }
 
-  /* Turn off periodic alarms (in case they are in use)
-     because the select emulator uses alarms.  */
-  stop_polling ();
-
   while (1)
     {
       /* 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 (read_kbd >= 0)
+      if (XINT (read_kbd) >= 0)
        QUIT;
 
       /* If status of something has changed, and no input is available,
@@ -1726,32 +1706,27 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
 
       /* Cause C-g and alarm signals to take immediate action,
         and cause input available signals to zero out timeout */
-      if (read_kbd < 0)
+      if (XINT (read_kbd) < 0)
        set_waiting_for_input (&timeout);
 
       /* Wait till there is something to do */
 
       Available = input_wait_mask;
-      if (!read_kbd)
+      if (! XINT (read_kbd))
        FD_CLR (0, &Available);
 
-      /* If a screen has been newly mapped and needs updating,
-        reprocess its display stuff.  */
-      if (screen_garbaged)
+      /* 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, we lose.  */
+      if (frame_garbaged)
        redisplay_preserve_echo_area ();
 
-      if (read_kbd && detect_input_pending ())
+      if (XINT (read_kbd) && detect_input_pending ())
        nfds = 0;
       else
-#ifdef AIX
-       nfds = select (MAXDESC, &Available, 0, 0, &timeout);
-#else
-#ifdef HPUX
        nfds = select (MAXDESC, &Available, 0, 0, &timeout);
-#else
-       nfds = select (MAXDESC, &Available, 0, 0, &timeout);
-#endif
-#endif
+
       xerrno = errno;
 
       /* Make C-g and alarm signals set flags again */
@@ -1760,12 +1735,18 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
       /*  If we woke up due to SIGWINCH, actually change size now.  */
       do_pending_window_change ();
 
-      if (time_limit && nfds == 0)     /* timeout elapsed */
+      if (time_limit && nfds == 0) /* timeout elapsed */
        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.  -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.  */
@@ -1782,7 +1763,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
                 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 */
+             FD_ZERO (&Available); /* Cannot depend on values returned */
 #else
              abort ();
 #endif
@@ -1800,19 +1781,21 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
       /* If there is any, return immediately
         to give it higher priority than subprocesses */
 
-      if (read_kbd && detect_input_pending ())
+      if (XINT (read_kbd) && detect_input_pending ())
        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 (read_kbd && interrupt_input && (Available & fileno (stdin)))
-      */
-      if (read_kbd && interrupt_input && (FD_ISSET (fileno (stdin), &Available)))
+       if (XINT (read_kbd) && interrupt_input && (Available & fileno (stdin)))
+       */
+      if (XINT (read_kbd) && interrupt_input && (FD_ISSET (fileno (stdin), &Available)))
        kill (0, SIGIO);
+#endif
 
 #ifdef vipc
       /* Check for connection from other process */
@@ -1822,11 +1805,16 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
          Available &= ~(ChannelMask (comm_server));
          create_commchan ();
        }
-#endif vipc
+#endif /* vipc */
 
       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))
+       do_pending_window_change ();
+
       /* Check for data from a process or a command channel */
       for (channel = FIRST_PROC_DESC; channel < MAXDESC; channel++)
        {
@@ -1863,7 +1851,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
                    }
                  continue;
                }
-#endif /* vipc */
+#endif                         /* vipc */
 
              /* Read data from the process, starting with our
                 buffered-ahead character if we have one.  */
@@ -1897,9 +1885,9 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
                 subprocess termination and SIGCHLD.  */
              else if (nread == 0 && !NETCONN_P (proc))
                ;
-#endif /* O_NDELAY */
-#endif /* O_NONBLOCK */
-#endif /* EWOULDBLOCK */
+#endif                         /* O_NDELAY */
+#endif                         /* O_NONBLOCK */
+#endif                         /* EWOULDBLOCK */
 #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
@@ -1910,9 +1898,9 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
                 get a SIGCHLD). */
              else if (nread == -1 && errno == EIO)
                ;
-#endif /* HAVE_PTYS */
-/* If we can detect process termination, don't consider the process
-   gone just because its pipe is closed.  */
+#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))
                ;
@@ -1929,11 +1917,18 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
                      = Fcons (Qexit, Fcons (make_number (256), Qnil));
                }
            }
-       } /* end for each file descriptor */
-    } /* end while exit conditions not met */
+       }                       /* end for each file descriptor */
+    }                          /* end while exit conditions not met */
 
-  /* Resume periodic signals to poll for input, if necessary.  */
-  start_polling ();
+  /* 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;
+    }
 
   return got_some_input;
 }
@@ -2106,12 +2101,14 @@ send_process (proc, buf, len)
     while (len > 0)
       {
        int this = len;
+       SIGTYPE (*old_sigpipe)();
+
        /* Don't send more than 500 bytes at a time.  */
        if (this > 500)
          this = 500;
-       signal (SIGPIPE, send_process_trap);
+       old_sigpipe = (SIGTYPE (*) ()) signal (SIGPIPE, send_process_trap);
        rv = write (XFASTINT (XPROCESS (proc)->outfd), buf, this);
-       signal (SIGPIPE, SIG_DFL);
+       signal (SIGPIPE, old_sigpipe);
        if (rv < 0)
          {
            if (0
@@ -2139,7 +2136,12 @@ send_process (proc, buf, len)
        /* Allow input from processes between bursts of sending.
           Otherwise things may get stopped up.  */
        if (len > 0)
-         wait_reading_process_input (-1, 0, 0, 0);
+         {
+           Lisp_Object zero;
+
+           XFASTINT (zero) = 0;
+           wait_reading_process_input (-1, 0, zero, 0);
+         }
       }
 #endif
   else
@@ -2160,7 +2162,8 @@ send_process (proc, buf, len)
 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 name or an actual 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\
@@ -2186,7 +2189,8 @@ Output from processes can arrive in between bunches.")
 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 name or an actual 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\
 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.")
@@ -2207,6 +2211,7 @@ Output from processes can arrive in between bunches.")
    If NOMSG is zero, insert signal-announcements into process's buffers
    right away.  */
 
+static void
 process_send_signal (process, signo, current_group, nomsg)
      Lisp_Object process;
      int signo;
@@ -2231,7 +2236,6 @@ process_send_signal (process, signo, current_group, nomsg)
   if (NILP (p->pty_flag))
     current_group = Qnil;
 
-#ifdef TIOCGPGRP               /* Not sure about this! (fnf) */
   /* If we are using pgrps, get a pgrp number and make it negative.  */
   if (!NILP (current_group))
     {
@@ -2246,45 +2250,49 @@ process_send_signal (process, signo, current_group, nomsg)
        case SIGINT:
          ioctl (XFASTINT (p->infd), TIOCGETC, &c);
          send_process (proc, &c.t_intrc, 1);
-         return Qnil;
+         return;
        case SIGQUIT:
          ioctl (XFASTINT (p->infd), TIOCGETC, &c);
          send_process (proc, &c.t_quitc, 1);
-         return Qnil;
+         return;
+#ifdef SIGTSTP
        case SIGTSTP:
          ioctl (XFASTINT (p->infd), TIOCGLTC, &lc);
          send_process (proc, &lc.t_suspc, 1);
-         return Qnil;
+         return;
+#endif /* SIGTSTP */
        }
-#endif /* have TIOCGLTC and have TIOCGETC */
+#endif /* ! defined (TIOCGLTC) && defined (TIOCGETC) */
       /* It is possible that the following code would work
         on other kinds of USG systems, not just on the IRIS.
         This should be tried in Emacs 19.  */
-#if defined (IRIS) && defined (HAVE_SETSID) /* Check for Irix, not older
-                                              systems.  */
+#if defined (USG)
       struct termio t;
       switch (signo)
        {
        case SIGINT:
          ioctl (XFASTINT (p->infd), TCGETA, &t);
          send_process (proc, &t.c_cc[VINTR], 1);
-         return Qnil;
+         return;
        case SIGQUIT:
          ioctl (XFASTINT (p->infd), TCGETA, &t);
          send_process (proc, &t.c_cc[VQUIT], 1);
-         return Qnil;
+         return;
+#ifdef SIGTSTP
        case SIGTSTP:
          ioctl (XFASTINT (p->infd), TCGETA, &t);
          send_process (proc, &t.c_cc[VSWTCH], 1);
-         return Qnil;
+         return;
+#endif
        }
-#endif /* IRIS and HAVE_SETSID */
+#endif /* ! defined (USG) */
 
+#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:
         "TICGPGRP symbol defined in sys/ioctl.h at E50.
-         But, TIOCGPGRP donot work on E50 ;-P work fine on E60"
+         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.  */
       {
@@ -2298,20 +2306,20 @@ process_send_signal (process, signo, current_group, nomsg)
 #ifdef pfa
        if (err == -1)
          gid = - XFASTINT (p->pid);
-#endif
+#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 ) */
     }
   else
     gid = - XFASTINT (p->pid);
-#else /* not using pgrps */
-  /* Can't select pgrps on this system, so we know that
-     the child itself heads the pgrp.  */
-  gid = - XFASTINT (p->pid);
-#endif /* not using pgrps */
 
   switch (signo)
     {
@@ -2324,7 +2332,7 @@ process_send_signal (process, signo, current_group, nomsg)
       if (!nomsg)
        status_notify ();
       break;
-#endif
+#endif /* ! defined (SIGCONT) */
     case SIGINT:
 #ifdef VMS
       send_process (proc, "\003", 1);  /* ^C */
@@ -2362,13 +2370,14 @@ process_send_signal (process, signo, current_group, nomsg)
       gid = - XFASTINT (p->pid);
       kill (gid, signo);
     }
-#else /* no TIOCSIGSEND */
+#else /* ! defined (TIOCSIGSEND) */
   EMACS_KILLPG (-gid, signo);
-#endif
+#endif /* ! defined (TIOCSIGSEND) */
 }
 
 DEFUN ("interrupt-process", Finterrupt_process, Sinterrupt_process, 0, 2, 0,
   "Interrupt process PROCESS.  May be process or name of one.\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\
@@ -2445,7 +2454,8 @@ Both PID and CODE are integers.")
 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\
-nil or no arg means current buffer's process.")
+PROCESS may be a process, a buffer, the name of a process or buffer, or\n\
+nil, indicating the current buffer's process.")
   (process)
      Lisp_Object process;
 {
@@ -2606,8 +2616,8 @@ sigchld_handler (signo)
          
          /* If process has terminated, stop waiting for its output.  */
          if (WIFSIGNALED (w) || WIFEXITED (w))
-           if (p->infd)
-             FD_CLR (p->infd, &input_wait_mask);
+           if (XFASTINT (p->infd))
+             FD_CLR (XFASTINT (p->infd), &input_wait_mask);
        }
 
        /* There was no asynchronous process found for that id.  Check
@@ -2794,7 +2804,7 @@ init_process ()
       proc_buffered_char[i] = -1;
     }
 }
-#ifdef 0
+#if 0
 DEFUN ("process-connection", Fprocess_connection, Sprocess_connection, 0, 1, 0,
  "Return the connection type of `PROCESS'.  This can be nil (pipe),\n\
 t or pty (pty) or stream (socket connection).")
@@ -2806,9 +2816,6 @@ t or pty (pty) or stream (socket connection).")
 #endif
 syms_of_process ()
 {
-#ifdef HAVE_PTYS
-  pty_process = intern ("pty");
-#endif
 #ifdef HAVE_SOCKETS
   stream_process = intern ("stream");
 #endif
@@ -2884,4 +2891,167 @@ effect when `start-process' is called.");
 /*  defsubr (&Sprocess_connection); */
 }
 
-#endif /* subprocesses */
+\f
+#else /* not subprocesses */
+
+#include <sys/types.h>
+#include <errno.h>
+
+#include "lisp.h"
+#include "systime.h"
+#include "termopts.h"
+
+extern int frame_garbaged;
+
+
+/* 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.
+     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.  This version of the function ignores it.
+
+   Return true iff we recieved 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;
+{
+  EMACS_TIME end_time, timeout, *timeout_p;
+  int waitchannels;
+
+  /* What does time_limit really mean?  */
+  if (time_limit || microsecs)
+    {
+      /* It's not infinite.  */
+      timeout_p = &timeout;
+
+      if (time_limit == -1)
+       /* In fact, it's zero.  */
+       EMACS_SET_SECS_USECS (timeout, 0, 0);
+      else
+       EMACS_SET_SECS_USECS (timeout, time_limit, microsecs);
+
+      /* How far in the future is that?  */
+      EMACS_GET_TIME (end_time);
+      EMACS_ADD_TIME (end_time, end_time, timeout);
+    }
+  else
+    /* It's infinite.  */
+    timeout_p = 0;
+
+  /* Turn off periodic alarms (in case they are in use)
+     because the select emulator uses alarms.  */
+  stop_polling ();
+
+  for (;;)
+    {
+      int nfds;
+
+      waitchannels = XINT (read_kbd) ? 1 : 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;
+
+      if (timeout_p)
+       {
+         EMACS_GET_TIME (*timeout_p);
+         EMACS_SUB_TIME (*timeout_p, end_time, *timeout_p);
+         if (EMACS_TIME_NEG_P (*timeout_p))
+           break;
+       }
+
+      /* 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);
+
+      /* If a frame has been newly mapped and needs updating,
+        reprocess its display stuff.  */
+      if (frame_garbaged)
+       redisplay_preserve_echo_area ();
+
+      if (XINT (read_kbd) && detect_input_pending ())
+       nfds = 0;
+      else
+       nfds = select (1, &waitchannels, 0, 0, timeout_p);
+
+      /* 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 ();
+
+      if (nfds == -1)
+       {
+         /* If the system call was interrupted, then go around the
+            loop again.  */
+         if (errno == EINTR)
+           waitchannels = 0;
+       }
+#ifdef sun
+      else if (nfds > 0 && (waitchannels & 1)  && interrupt_input)
+       /* System sometimes fails to deliver SIGIO.  */
+       kill (getpid (), SIGIO);
+#endif
+      if (XINT (read_kbd) && interrupt_input && (waitchannels & 1))
+       kill (0, SIGIO);
+
+      /* If we have timed out (nfds == 0) or found some input (nfds > 0),
+        we should exit.  */
+      if (nfds >= 0)
+       break;
+    }
+
+  return 0;
+}
+
+
+DEFUN ("get-buffer-process", Fget_buffer_process, Sget_buffer_process, 1, 1, 0,
+  "Return the (or, a) process associated with BUFFER.\n\
+This copy of Emacs has not been built to support subprocesses, so this\n\
+function always returns nil.")
+  (name)
+     register Lisp_Object name;
+{
+  return Qnil;
+}
+
+/* Kill all processes associated with `buffer'.
+   If `buffer' is nil, kill all processes.
+   Since we have no subprocesses, this does nothing.  */
+
+kill_buffer_processes (buffer)
+     Lisp_Object buffer;
+{
+}
+
+init_process ()
+{
+}
+
+syms_of_process ()
+{
+  defsubr (&Sget_buffer_process);
+}
+
+\f
+#endif /* not subprocesses */