(Faref): Use SPLIT_CHAR instead of SPLIT_NON_ASCII_CHAR.
[bpt/emacs.git] / src / process.c
index 4d2cc5e..8b23d2f 100644 (file)
@@ -1,5 +1,5 @@
 /* Asynchronous subprocess control for GNU Emacs.
-   Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 96, 1998
+   Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 96, 98, 1999
       Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -20,9 +20,9 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
 
-#include <signal.h>
-
+#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
@@ -59,7 +59,7 @@ Boston, MA 02111-1307, USA.  */
 #endif /* NEED_NET_ERRNO_H */
 #endif /* HAVE_SOCKETS */
 
-/* TERM is a poor-man's SLIP, used on Linux.  */
+/* TERM is a poor-man's SLIP, used on GNU/Linux.  */
 #ifdef TERM
 #include <client.h>
 #endif
@@ -108,6 +108,8 @@ Boston, MA 02111-1307, USA.  */
 #include "blockinput.h"
 #include "keyboard.h"
 #include "dispextern.h"
+#include "composite.h"
+#include "atimer.h"
 
 #define max(a, b) ((a) > (b) ? (a) : (b))
 
@@ -143,8 +145,9 @@ Lisp_Object Qlast_nonmenu_event;
 
 #include "syswait.h"
 
+extern void set_waiting_for_input P_ ((EMACS_TIME *));
+
 extern int errno;
-extern char *strerror ();
 #ifdef VMS
 extern char *sys_errlist[];
 #endif
@@ -153,48 +156,6 @@ extern char *sys_errlist[];
 extern int h_errno;
 #endif
 
-#ifndef SYS_SIGLIST_DECLARED
-#ifndef VMS
-#ifndef BSD4_1
-#ifndef WINDOWSNT
-#ifndef LINUX
-extern char *sys_siglist[];
-#endif /* not LINUX */
-#else /* BSD4_1 */
-char *sys_siglist[] =
-  {
-    "bum signal!!",
-    "hangup",
-    "interrupt",
-    "quit",
-    "illegal instruction",
-    "trace trap",
-    "iot instruction",
-    "emt instruction",
-    "floating point exception",
-    "kill",
-    "bus error",
-    "segmentation violation",
-    "bad argument to system call",
-    "write on a pipe with no one to read it",
-    "alarm clock",
-    "software termination signal from kill",
-    "status signal",
-    "sendable stop signal not from tty",
-    "stop signal from tty",
-    "continue a stopped process",
-    "child status has changed",
-    "background read attempted from control tty",
-    "background write attempted from control tty",
-    "input record available at control tty",
-    "exceeded CPU time limit",
-    "exceeded file size limit"
-    };
-#endif /* not WINDOWSNT */
-#endif
-#endif /* VMS */
-#endif /* ! SYS_SIGLIST_DECLARED */
-
 /* t means use pty, nil means use a pipe,
    maybe other values to come.  */
 static Lisp_Object Vprocess_connection_type;
@@ -214,6 +175,8 @@ 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
@@ -331,10 +294,10 @@ decode_status (l, symbol, code, coredump)
     }
   else
     {
-      *symbol = XCONS (l)->car;
-      tem = XCONS (l)->cdr;
-      *code = XFASTINT (XCONS (tem)->car);
-      tem = XCONS (tem)->cdr;
+      *symbol = XCAR (l);
+      tem = XCDR (l);
+      *code = XFASTINT (XCAR (tem));
+      tem = XCDR (tem);
       *coredump = !NILP (tem);
     }
 }
@@ -353,16 +316,9 @@ status_message (status)
 
   if (EQ (symbol, Qsignal) || EQ (symbol, Qstop))
     {
-      char *signame = 0;
-      if (code < NSIG)
-       {
-#ifndef VMS
-         /* Cast to suppress warning if the table has const char *.  */
-         signame = (char *) sys_siglist[code];
-#else
-         signame = sys_errlist[code];
-#endif
-       }
+      char *signame;
+      synchronize_system_messages_locale ();
+      signame = strsignal (code);
       if (signame == 0)
        signame = "unknown";
       string = build_string (signame);
@@ -422,7 +378,7 @@ allocate_pty ()
 #else /* no PTY_OPEN */
 #ifdef IRIS
        /* Unusual IRIS code */
-       *ptyv = open ("/dev/ptc", O_RDWR | O_NDELAY, 0);
+       *ptyv = emacs_open ("/dev/ptc", O_RDWR | O_NDELAY, 0);
        if (fd < 0)
          return -1;
        if (fstat (fd, &stb) < 0)
@@ -437,9 +393,9 @@ allocate_pty ()
        else
          failed_count = 0;
 #ifdef O_NONBLOCK
-       fd = open (pty_name, O_RDWR | O_NONBLOCK, 0);
+       fd = emacs_open (pty_name, O_RDWR | O_NONBLOCK, 0);
 #else
-       fd = open (pty_name, O_RDWR | O_NDELAY, 0);
+       fd = emacs_open (pty_name, O_RDWR | O_NDELAY, 0);
 #endif
 #endif /* not IRIS */
 #endif /* no PTY_OPEN */
@@ -456,7 +412,7 @@ allocate_pty ()
 #ifndef UNIPLUS
            if (access (pty_name, 6) != 0)
              {
-               close (fd);
+               emacs_close (fd);
 #if !defined(IRIS) && !defined(__sgi)
                continue;
 #else
@@ -665,7 +621,7 @@ nil, indicating the current buffer's process.")
     update_status (p);
   status = p->status;
   if (CONSP (status))
-    status = XCONS (status)->car;
+    status = XCAR (status);
   if (NETCONN_P (process))
     {
       if (EQ (status, Qrun))
@@ -687,7 +643,7 @@ If PROCESS has not yet exited or died, return 0.")
   if (!NILP (XPROCESS (process)->raw_status_low))
     update_status (XPROCESS (process));
   if (CONSP (XPROCESS (process)->status))
-    return XCONS (XCONS (XPROCESS (process)->status)->cdr)->car;
+    return XCAR (XCDR (XPROCESS (process)->status));
   return make_number (0);
 }
 
@@ -932,9 +888,7 @@ list_processes_1 ()
 {
   register Lisp_Object tail, tem;
   Lisp_Object proc, minspace, tem1;
-  register struct buffer *old = current_buffer;
   register struct Lisp_Process *p;
-  register int state;
   char tembuf[80];
 
   XSETFASTINT (minspace, 1);
@@ -964,7 +918,7 @@ Proc         Status   Buffer         Tty         Command\n\
        update_status (p);
       symbol = p->status;
       if (CONSP (p->status))
-       symbol = XCONS (p->status)->car;
+       symbol = XCAR (p->status);
 
       
       if (EQ (symbol, Qsignal))
@@ -1024,7 +978,7 @@ Proc         Status   Buffer         Tty         Command\n\
       if (NETCONN_P (proc))
         {
          sprintf (tembuf, "(network stream connection to %s)\n",
-                  XSTRING (XCONS (p->childp)->car)->data);
+                  XSTRING (XCAR (p->childp))->data);
          insert_string (tembuf);
         }
       else 
@@ -1069,7 +1023,6 @@ 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\
-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\
@@ -1226,9 +1179,9 @@ Remaining arguments are strings to give program as arguments.")
        coding_systems = Ffind_operation_coding_system (nargs + 1, args2);
        UNGCPRO;
        if (CONSP (coding_systems))
-         val = XCONS (coding_systems)->car;
+         val = XCAR (coding_systems);
        else if (CONSP (Vdefault_process_coding_system))
-         val = XCONS (Vdefault_process_coding_system)->car;
+         val = XCAR (Vdefault_process_coding_system);
       }
     XPROCESS (proc)->decode_coding_system = val;
 
@@ -1245,9 +1198,9 @@ Remaining arguments are strings to give program as arguments.")
            UNGCPRO;
          }
        if (CONSP (coding_systems))
-         val = XCONS (coding_systems)->cdr;
+         val = XCDR (coding_systems);
        else if (CONSP (Vdefault_process_coding_system))
-         val = XCONS (Vdefault_process_coding_system)->cdr;
+         val = XCDR (Vdefault_process_coding_system);
       }
     XPROCESS (proc)->encode_coding_system = val;
   }
@@ -1284,18 +1237,14 @@ start_process_unwind (proc)
   return Qnil;
 }
 
-
-SIGTYPE
-create_process_1 (signo)
-     int signo;
+void
+create_process_1 (timer)
+     struct atimer *timer;
 {
-#if defined (USG) && !defined (POSIX_SIGNALS)
-  /* USG systems forget handlers when they are used;
-     must reestablish each time */
-  signal (signo, create_process_1);
-#endif /* USG */
+  /* Nothing to do.  */
 }
 
+
 #if 0  /* This doesn't work; see the note before sigchld_handler.  */
 #ifdef USG
 #ifdef SIGCHLD
@@ -1333,9 +1282,11 @@ create_process (process, new_argv, current_dir)
   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;
@@ -1357,9 +1308,9 @@ create_process (process, new_argv, current_dir)
 #ifdef O_NOCTTY
       /* Don't let this terminal become our controlling terminal
         (in case we don't have one).  */
-      forkout = forkin = open (pty_name, O_RDWR | O_NOCTTY, 0);
+      forkout = forkin = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0);
 #else
-      forkout = forkin = open (pty_name, O_RDWR, 0);
+      forkout = forkin = emacs_open (pty_name, O_RDWR, 0);
 #endif
       if (forkin < 0)
        report_file_error ("Opening pty", Qnil);
@@ -1388,8 +1339,8 @@ create_process (process, new_argv, current_dir)
       tem = pipe (sv);
       if (tem < 0)
        {
-         close (inchannel);
-         close (forkout);
+         emacs_close (inchannel);
+         emacs_close (forkout);
          report_file_error ("Creating pipe", Qnil);
        }
       outchannel = sv[1];
@@ -1445,7 +1396,7 @@ create_process (process, new_argv, current_dir)
   setup_coding_system (XPROCESS (process)->encode_coding_system,
                       proc_encode_coding_system[outchannel]);
 
-  if (!NILP (buffer) && NILP (XBUFFER (buffer)->enable_multibyte_characters)
+  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
@@ -1588,7 +1539,7 @@ create_process (process, new_argv, current_dir)
            tcgetattr (xforkin, &t);
            t.c_lflag = LDISC1;
            if (tcsetattr (xforkin, TCSANOW, &t) < 0)
-             write (1, "create_process/tcsetattr LDISC1 failed\n", 39);
+             emacs_write (1, "create_process/tcsetattr LDISC1 failed\n", 39);
          }
 #else
 #if defined (NTTYDISC) && defined (TIOCSETD)
@@ -1607,9 +1558,9 @@ create_process (process, new_argv, current_dir)
          {
            /* I wonder: would just ioctl (0, TIOCNOTTY, 0) work here? 
               I can't test it since I don't have 4.3.  */
-           int j = open ("/dev/tty", O_RDWR, 0);
+           int j = emacs_open ("/dev/tty", O_RDWR, 0);
            ioctl (j, TIOCNOTTY, 0);
-           close (j);
+           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
@@ -1638,16 +1589,17 @@ create_process (process, new_argv, current_dir)
            int pgrp = getpid ();
 #endif
 
-           /* I wonder if close (open (pty_name, ...)) would work?  */
+           /* I wonder if emacs_close (emacs_open (pty_name, ...))
+              would work?  */
            if (xforkin >= 0)
-             close (xforkin);
-           xforkout = xforkin = open (pty_name, O_RDWR, 0);
+             emacs_close (xforkin);
+           xforkout = xforkin = emacs_open (pty_name, O_RDWR, 0);
 
            if (xforkin < 0)
              {
-               write (1, "Couldn't open the pty terminal ", 31);
-               write (1, pty_name, strlen (pty_name));
-               write (1, "\n", 1);
+               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);
              }
 
@@ -1713,9 +1665,9 @@ create_process (process, new_argv, current_dir)
   if (pid < 0)
     {
       if (forkin >= 0)
-       close (forkin);
+       emacs_close (forkin);
       if (forkin != forkout && forkout >= 0)
-       close (forkout);
+       emacs_close (forkout);
     }
   else
     {
@@ -1729,16 +1681,24 @@ create_process (process, new_argv, current_dir)
       /* If the subfork execv fails, and it exits,
         this close hangs.  I don't know why.
         So have an interrupt jar it loose.  */
-      stop_polling ();
-      signal (SIGALRM, create_process_1);
-      alarm (1);
-      XPROCESS (process)->subtty = Qnil;
-      if (forkin >= 0)
-       close (forkin);
-      alarm (0);
-      start_polling ();
+      {
+       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)
-       close (forkout);
+       emacs_close (forkout);
 
 #ifdef HAVE_PTYS
       if (pty_flag)
@@ -1814,26 +1774,24 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\
       Lisp_Object name, buffer, host, service;
 {
   Lisp_Object proc;
-  register int i;
-
 #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;
-  struct hostent host_info_fixed;
   int port;
-#else /* HAVE_GETADDRINFO */
+#else /* HAVE_GETADDRINFO */
   struct addrinfo hints, *res, *lres;
   int ret = 0;
   int xerrno = 0;
-  char *portstring, portbuf [128];
-#endif /* HAVE_GETADDRINFO */
-  int s, outch, inch;
+  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. */
@@ -1877,6 +1835,7 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\
      Some kernels have a bug which causes retrying connect to fail
      after a connect.  Polling can interfere with gethostbyname too.  */
 #ifdef POLL_FOR_INPUT
+  record_unwind_protect (unwind_stop_other_atimers, Qnil);
   bind_polling_period (10);
 #endif
 
@@ -1886,34 +1845,28 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\
     immediate_quit = 1;
     QUIT;
     memset (&hints, 0, sizeof (hints));
-    hints.ai_flags = AI_NUMERICHOST;
+    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)    /* numeric */
-      {
-       freeaddrinfo (res);
-       hints.ai_flags = AI_CANONNAME;
-      }
-    else         /* non-numeric */
-      {
-       hints.ai_flags = 0;
-      }
-    ret = getaddrinfo (XSTRING (host)->data, portstring, &hints, &res);
     if (ret)
       {
        error ("%s/%s %s", XSTRING (host)->data, portstring,
-             gai_strerror (ret));
+              strerror (ret));
       }
     immediate_quit = 0;
   }
 
-  for (lres = res; lres ; lres = lres->ai_next)
+  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) 
-       report_file_error ("error creating socket", Fcons (name, Qnil));
+       continue;
 
       /* Kernel bugs (on Ultrix at least) cause lossage (not just EINTR)
         when connect is interrupted.  So let's not let it get interrupted.
@@ -1924,38 +1877,18 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\
       if (interrupt_input)
        unrequest_sigio ();
 
-  loop:
-
       immediate_quit = 1;
       QUIT;
 
       ret = connect (s, lres->ai_addr, lres->ai_addrlen);
-
-      if (ret == -1 && errno != EISCONN)
-       {
-         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;
-           }
-
-         close (s);
-       }
-      if (ret == 0)            /* We got a valid connect */
+      if (ret == 0)
        break;
-  } /* address loop */
+      emacs_close (s);
+      s = -1;
+    }
+
   freeaddrinfo (res);
-  if (ret != 0)
+  if (s < 0)
     {
       if (interrupt_input)
        request_sigio ();
@@ -1968,15 +1901,19 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\
 
   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);
@@ -2014,6 +1951,9 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\
   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
@@ -2047,7 +1987,10 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\
          goto loop;
        }
 
-      close (s);
+      /* Discard the unwind protect.  */
+      specpdl_ptr = specpdl + count1;
+
+      emacs_close (s);
 
       if (interrupt_input)
        request_sigio ();
@@ -2060,6 +2003,9 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\
 
   immediate_quit = 0;
 
+  /* Discard the unwind protect.  */
+  specpdl_ptr = specpdl + count1;
+
 #ifdef POLL_FOR_INPUT
   unbind_to (count, Qnil);
 #endif
@@ -2116,8 +2062,8 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\
 
     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))
+    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
@@ -2131,9 +2077,9 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\
        coding_systems = Ffind_operation_coding_system (5, args);
        UNGCPRO;
        if (CONSP (coding_systems))
-         val = XCONS (coding_systems)->car;
+         val = XCAR (coding_systems);
        else if (CONSP (Vdefault_process_coding_system))
-         val = XCONS (Vdefault_process_coding_system)->car;
+         val = XCAR (Vdefault_process_coding_system);
        else
          val = Qnil;
       }
@@ -2154,9 +2100,9 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\
            UNGCPRO;
          }
        if (CONSP (coding_systems))
-         val = XCONS (coding_systems)->cdr;
+         val = XCDR (coding_systems);
        else if (CONSP (Vdefault_process_coding_system))
-         val = XCONS (Vdefault_process_coding_system)->cdr;
+         val = XCDR (Vdefault_process_coding_system);
        else
          val = Qnil;
       }
@@ -2211,9 +2157,9 @@ deactivate_process (proc)
          give_back_vms_process_stuff (vs);
       }
 #else
-      close (inchannel);
+      emacs_close (inchannel);
       if (outchannel >= 0 && outchannel != inchannel)
-       close (outchannel);
+       emacs_close (outchannel);
 #endif
 
       XSETINT (p->infd, -1);
@@ -2252,9 +2198,9 @@ close_process_descs ()
          int in = XINT (XPROCESS (process)->infd);
          int out = XINT (XPROCESS (process)->outfd);
          if (in >= 0)
-           close (in);
+           emacs_close (in);
          if (out >= 0 && in != out)
-           close (out);
+           emacs_close (out);
        }
     }
 #endif
@@ -2383,11 +2329,11 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
      Lisp_Object read_kbd;
      int do_display;
 {
-  register int channel, nfds, m;
+  register int channel, nfds;
   static SELECT_TYPE Available;
   int xerrno;
   Lisp_Object proc;
-  EMACS_TIME timeout, end_time, garbage;
+  EMACS_TIME timeout, end_time;
   SELECT_TYPE Atemp;
   int wait_channel = -1;
   struct Lisp_Process *wait_proc = 0;
@@ -2408,7 +2354,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
   /* If waiting for non-nil in a cell, record where.  */
   if (CONSP (read_kbd))
     {
-      wait_for_cell = &XCONS (read_kbd)->car;
+      wait_for_cell = &XCAR (read_kbd);
       XSETFASTINT (read_kbd, 0);
     }
 
@@ -2428,18 +2374,13 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
      Causes "poll: interrupted system call" messages when Emacs is run
      in an X window
      Turn off periodic alarms (in case they are in use) */
-  stop_polling ();
+  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.  */
@@ -2556,15 +2497,26 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
          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))))
+         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)
@@ -2611,7 +2563,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
       clear_waiting_for_input ();
 
       /*  If we woke up due to SIGWINCH, actually change size now.  */
-      do_pending_window_change ();
+      do_pending_window_change (0);
 
       if (time_limit && nfds == 0 && ! timeout_reduced_for_timers)
        /* We wanted the full specified time, so return now.  */
@@ -2651,7 +2603,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
 #endif
            }
          else
-           error ("select error: %s", strerror (xerrno));
+           error ("select error: %s", emacs_strerror (xerrno));
        }
 #if defined(sun) && !defined(USG5_4)
       else if (nfds > 0 && keyboard_bit_set (&Available)
@@ -2735,7 +2687,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
       /* 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 ();
+       do_pending_window_change (0);
 
       /* Check for data from a process.  */
       /* Really FIRST_PROC_DESC should be 0 on Unix,
@@ -2852,12 +2804,6 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
   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;
 }
 \f
@@ -2867,7 +2813,7 @@ static Lisp_Object
 read_process_output_call (fun_and_args)
      Lisp_Object fun_and_args;
 {
-  return apply1 (XCONS (fun_and_args)->car, XCONS (fun_and_args)->cdr);
+  return apply1 (XCAR (fun_and_args), XCDR (fun_and_args));
 }
 
 static Lisp_Object
@@ -2878,6 +2824,7 @@ read_process_output_error_handler (error)
   Vinhibit_quit = Qt;
   update_echo_area ();
   Fsleep_for (make_number (2), Qnil);
+  return Qt;
 }
 
 /* Read pending output from the process channel,
@@ -2955,13 +2902,13 @@ read_process_output (proc, channel)
           buf, carryover);
 
   if (proc_buffered_char[channel] < 0)
-    nbytes = read (channel, buf + carryover, (sizeof buf) - carryover);
+    nbytes = emacs_read (channel, buf + carryover, (sizeof buf) - carryover);
   else
     {
       buf[carryover] = proc_buffered_char[channel];
       proc_buffered_char[channel] = -1;
-      nbytes = read (channel, buf + carryover + 1,
-                    (sizeof buf) - carryover - 1);
+      nbytes = emacs_read (channel, buf + carryover + 1,
+                          (sizeof buf) - carryover - 1);
       if (nbytes < 0)
        nbytes = 1;
       else
@@ -3229,7 +3176,8 @@ read_process_output (proc, channel)
       else
        {
          insert_1_both (chars, nchars, nbytes, 0, 1, 1);
-         signal_after_change (opoint, 0, PT - opoint);
+         signal_after_change (before, 0, PT - before);
+         update_compositions (before, PT, CHECK_BORDER);
        }
       set_marker_both (p->mark, p->buffer, PT, PT_BYTE);
 
@@ -3301,7 +3249,9 @@ send_process_trap ()
    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?  */
+   the data send later? 
+
+   This function can evaluate Lisp code and can garbage collect.  */
 
 void
 send_process (proc, buf, len, object)
@@ -3312,7 +3262,6 @@ send_process (proc, buf, len, 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);
@@ -3327,9 +3276,11 @@ send_process (proc, buf, len, object)
   if (! NILP (XPROCESS (proc)->raw_status_low))
     update_status (XPROCESS (proc));
   if (! EQ (XPROCESS (proc)->status, Qrun))
-    error ("Process %s not running", procname);
+    error ("Process %s not running",
+          XSTRING (XPROCESS (proc)->name)->data);
   if (XINT (XPROCESS (proc)->outfd) < 0)
-    error ("Output file descriptor of %s is closed", procname);
+    error ("Output file descriptor of %s is closed",
+          XSTRING (XPROCESS (proc)->name)->data);
 
   coding = proc_encode_coding_system[XINT (XPROCESS (proc)->outfd)];
   Vlast_coding_system_used = coding->symbol;
@@ -3337,7 +3288,7 @@ send_process (proc, buf, len, object)
   if (CODING_REQUIRE_ENCODING (coding))
     {
       int require = encoding_buffer_size (coding, len);
-      int offset, dummy;
+      int offset;
       unsigned char *temp_buf = NULL;
 
       /* Remember the offset of data because a string or a buffer may
@@ -3419,7 +3370,6 @@ send_process (proc, buf, len, object)
       {
        int this = len;
        SIGTYPE (*old_sigpipe)();
-       int flush_pty = 0;
 
        /* Decide how much data we can send in one batch.
           Long lines need to be split into multiple batches.  */
@@ -3453,7 +3403,7 @@ send_process (proc, buf, len, object)
        while (this > 0)
          {
            old_sigpipe = (SIGTYPE (*) ()) signal (SIGPIPE, send_process_trap);
-           rv = write (XINT (XPROCESS (proc)->outfd), buf, this);
+           rv = emacs_write (XINT (XPROCESS (proc)->outfd), buf, this);
            signal (SIGPIPE, old_sigpipe);
 
            if (rv < 0)
@@ -3473,6 +3423,32 @@ send_process (proc, buf, len, object)
                    Lisp_Object zero;
                    int offset;
 
+#ifdef BROKEN_PTY_READ_AFTER_EAGAIN
+                   /* A gross hack to work around a bug in FreeBSD.
+                      In the following sequence, read(2) returns
+                      bogus data:
+
+                      write(2)  1022 bytes
+                      write(2)   954 bytes, get EAGAIN
+                      read(2)   1024 bytes in process_read_output
+                      read(2)     11 bytes in process_read_output
+
+                      That is, read(2) returns more bytes than have
+                      ever been written successfully.  The 1033 bytes
+                      read are the 1022 bytes written successfully
+                      after processing (for example with CRs added if
+                      the terminal is set up that way which it is
+                      here).  The same bytes will be seen again in a
+                      later read(2), without the CRs.  */
+                   
+                   if (errno == EAGAIN)
+                     {
+                       int flags = FWRITE;
+                       ioctl (XINT (XPROCESS (proc)->outfd), TIOCFLUSH,
+                              &flags);
+                     }
+#endif /* BROKEN_PTY_READ_AFTER_EAGAIN */
+                   
                    /* Running filters might relocate buffers or strings.
                       Arrange to relocate BUF.  */
                    if (BUFFERP (object))
@@ -3517,9 +3493,11 @@ send_process (proc, buf, len, object)
       XSETINT (XPROCESS (proc)->tick, ++process_tick);
       deactivate_process (proc);
 #ifdef VMS
-      error ("Error writing to process %s; closed it", procname);
+      error ("Error writing to process %s; closed it", 
+            XSTRING (XPROCESS (proc)->name)->data);
 #else
-      error ("SIGPIPE raised on process %s; closed it", procname);
+      error ("SIGPIPE raised on process %s; closed it",
+            XSTRING (XPROCESS (proc)->name)->data);
 #endif
     }
 
@@ -4074,11 +4052,11 @@ text to PROCESS after you call this function.")
        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))
-       close (XINT (XPROCESS (proc)->outfd));
+       emacs_close (XINT (XPROCESS (proc)->outfd));
 #else /* not HAVE_SHUTDOWN */
-      close (XINT (XPROCESS (proc)->outfd));
+      emacs_close (XINT (XPROCESS (proc)->outfd));
 #endif /* not HAVE_SHUTDOWN */
-      new_outfd = open (NULL_DEVICE, O_WRONLY);
+      new_outfd = emacs_open (NULL_DEVICE, O_WRONLY, 0);
       old_outfd = XINT (XPROCESS (proc)->outfd);
 
       if (!proc_encode_coding_system[new_outfd])
@@ -4105,9 +4083,9 @@ kill_buffer_processes (buffer)
 {
   Lisp_Object tail, proc;
 
-  for (tail = Vprocess_alist; GC_CONSP (tail); tail = XCONS (tail)->cdr)
+  for (tail = Vprocess_alist; GC_CONSP (tail); tail = XCDR (tail))
     {
-      proc = XCONS (XCONS (tail)->car)->cdr;
+      proc = XCDR (XCAR (tail));
       if (GC_PROCESSP (proc)
          && (NILP (buffer) || EQ (XPROCESS (proc)->buffer, buffer)))
        {
@@ -4195,9 +4173,9 @@ sigchld_handler (signo)
       /* Find the process that signaled us, and record its status.  */
 
       p = 0;
-      for (tail = Vprocess_alist; CONSP (tail); tail = XCONS (tail)->cdr)
+      for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
        {
-         proc = XCONS (XCONS (tail)->car)->cdr;
+         proc = XCDR (XCAR (tail));
          p = XPROCESS (proc);
          if (EQ (p->childp, Qt) && XFASTINT (p->pid) == pid)
            break;
@@ -4207,9 +4185,9 @@ sigchld_handler (signo)
       /* Look for an asynchronous process whose pid hasn't been filled
         in yet.  */
       if (p == 0)
-       for (tail = Vprocess_alist; CONSP (tail); tail = XCONS (tail)->cdr)
+       for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
          {
-           proc = XCONS (XCONS (tail)->car)->cdr;
+           proc = XCDR (XCAR (tail));
            p = XPROCESS (proc);
            if (INTEGERP (p->pid) && XINT (p->pid) == -1)
              break;
@@ -4257,17 +4235,11 @@ sigchld_handler (signo)
          else if (WIFSIGNALED (w))
            {
              int code = WTERMSIG (w);
-             char *signame = 0;
+             char *signame;
+
+             synchronize_system_messages_locale ();
+             signame = strsignal (code);
 
-             if (code < NSIG)
-               {
-#ifndef VMS
-                 /* Suppress warning if the table has const char *.  */
-                 signame = (char *) sys_siglist[code];
-#else
-                 signame = sys_errlist[code];
-#endif
-               }
              if (signame == 0)
                signame = "unknown";
 
@@ -4300,7 +4272,7 @@ static Lisp_Object
 exec_sentinel_unwind (data)
      Lisp_Object data;
 {
-  XPROCESS (XCONS (data)->car)->sentinel = XCONS (data)->cdr;
+  XPROCESS (XCAR (data))->sentinel = XCDR (data);
   return Qnil;
 }
 
@@ -4312,6 +4284,7 @@ exec_sentinel_error_handler (error)
   Vinhibit_quit = Qt;
   update_echo_area ();
   Fsleep_for (make_number (2), Qnil);
+  return Qt;
 }
 
 static void
@@ -4437,7 +4410,7 @@ status_notify ()
          /* If process is terminated, deactivate it or delete it.  */
          symbol = p->status;
          if (CONSP (p->status))
-           symbol = XCONS (p->status)->car;
+           symbol = XCAR (p->status);
 
          if (EQ (symbol, Qsignal) || EQ (symbol, Qexit)
              || EQ (symbol, Qclosed))
@@ -4785,7 +4758,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
   /* If waiting for non-nil in a cell, record where.  */
   if (CONSP (read_kbd))
     {
-      wait_for_cell = &XCONS (read_kbd)->car;
+      wait_for_cell = &XCAR (read_kbd);
       XSETFASTINT (read_kbd, 0);
     }
 
@@ -4799,7 +4772,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
 
   /* Turn off periodic alarms (in case they are in use)
      because the select emulator uses alarms.  */
-  stop_polling ();
+  turn_on_atimers (0);
 
   while (1)
     {
@@ -4911,7 +4884,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
       clear_waiting_for_input ();
 
       /*  If we woke up due to SIGWINCH, actually change size now.  */
-      do_pending_window_change ();
+      do_pending_window_change (0);
 
       if (time_limit && nfds == 0 && ! timeout_reduced_for_timers)
        /* We waited the full specified time, so return now.  */
@@ -4924,7 +4897,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
          if (xerrno == EINTR)
            FD_ZERO (&waitchannels);
          else
-           error ("select error: %s", strerror (xerrno));
+           error ("select error: %s", emacs_strerror (xerrno));
        }
 #ifdef sun
       else if (nfds > 0 && (waitchannels & 1)  && interrupt_input)