(mouse-autoselect-window-cancel): Don't cancel for
[bpt/emacs.git] / src / process.c
index 857d749..fd8e2c9 100644 (file)
@@ -1,13 +1,13 @@
 /* Asynchronous subprocess control for GNU Emacs.
    Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995,
                  1996, 1998, 1999, 2001, 2002, 2003, 2004,
 /* Asynchronous subprocess control for GNU Emacs.
    Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995,
                  1996, 1998, 1999, 2001, 2002, 2003, 2004,
-                 2005, 2006 Free Software Foundation, Inc.
+                 2005, 2006, 2007 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
 
 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)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -318,6 +318,12 @@ static int read_process_output P_ ((Lisp_Object, int));
 #define POLL_FOR_INPUT
 #endif
 
 #define POLL_FOR_INPUT
 #endif
 
+static Lisp_Object get_process ();
+static void exec_sentinel ();
+
+extern EMACS_TIME timer_check ();
+extern int timers_run;
+\f
 /* Mask of bits indicating the descriptors that we wait for input on.  */
 
 static SELECT_TYPE input_wait_mask;
 /* Mask of bits indicating the descriptors that we wait for input on.  */
 
 static SELECT_TYPE input_wait_mask;
@@ -386,15 +392,13 @@ struct sockaddr_and_len {
 #define DATAGRAM_CONN_P(proc)  (0)
 #endif
 
 #define DATAGRAM_CONN_P(proc)  (0)
 #endif
 
-static Lisp_Object get_process ();
-static void exec_sentinel ();
-
-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;
 
 /* Maximum number of bytes to send to a pty without an eof.  */
 static int pty_max_bytes;
 
+/* Nonzero means don't run process sentinels.  This is used
+   when exiting.  */
+int inhibit_sentinels;
+
 #ifdef HAVE_PTYS
 #ifdef HAVE_PTY_H
 #include <pty.h>
 #ifdef HAVE_PTYS
 #ifdef HAVE_PTY_H
 #include <pty.h>
@@ -811,9 +815,12 @@ nil, indicating the current buffer's process.  */)
     {
 #ifdef SIGCHLD
       Lisp_Object symbol;
     {
 #ifdef SIGCHLD
       Lisp_Object symbol;
+      /* Assignment to EMACS_INT stops GCC whining about limited range
+        of data type.  */
+      EMACS_INT pid = p->pid;
 
       /* No problem storing the pid here, as it is still in Vprocess_alist.  */
 
       /* No problem storing the pid here, as it is still in Vprocess_alist.  */
-      deleted_pid_list = Fcons (make_fixnum_or_float (p->pid),
+      deleted_pid_list = Fcons (make_fixnum_or_float (pid),
                                /* GC treated elements set to nil.  */
                                Fdelq (Qnil, deleted_pid_list));
       /* If the process has already signaled, remove it from the list.  */
                                /* GC treated elements set to nil.  */
                                Fdelq (Qnil, deleted_pid_list));
       /* If the process has already signaled, remove it from the list.  */
@@ -823,7 +830,8 @@ nil, indicating the current buffer's process.  */)
       if (CONSP (p->status))
        symbol = XCAR (p->status);
       if (EQ (symbol, Qsignal) || EQ (symbol, Qexit))
       if (CONSP (p->status))
        symbol = XCAR (p->status);
       if (EQ (symbol, Qsignal) || EQ (symbol, Qexit))
-       Fdelete (make_fixnum_or_float (p->pid), deleted_pid_list);
+       deleted_pid_list
+         = Fdelete (make_fixnum_or_float (pid), deleted_pid_list);
       else
 #endif
        {
       else
 #endif
        {
@@ -908,10 +916,13 @@ For a network connection, this value is nil.  */)
      (process)
      register Lisp_Object process;
 {
      (process)
      register Lisp_Object process;
 {
+  /* Assignment to EMACS_INT stops GCC whining about limited range of
+     data type.  */
+  EMACS_INT pid;
+
   CHECK_PROCESS (process);
   CHECK_PROCESS (process);
-  return (XPROCESS (process)->pid
-         ? make_fixnum_or_float (XPROCESS (process)->pid)
-         : Qnil);
+  pid = XPROCESS (process)->pid;
+  return (pid ? make_fixnum_or_float (pid) : Qnil);
 }
 
 DEFUN ("process-name", Fprocess_name, Sprocess_name, 1, 1, 0,
 }
 
 DEFUN ("process-name", Fprocess_name, Sprocess_name, 1, 1, 0,
@@ -1257,7 +1268,7 @@ Returns nil if format of ADDRESS is invalid.  */)
   if (VECTORP (address))  /* AF_INET or AF_INET6 */
     {
       register struct Lisp_Vector *p = XVECTOR (address);
   if (VECTORP (address))  /* AF_INET or AF_INET6 */
     {
       register struct Lisp_Vector *p = XVECTOR (address);
-      Lisp_Object args[6];
+      Lisp_Object args[10];
       int nargs, i;
 
       if (p->size == 4 || (p->size == 5 && !NILP (omit_port)))
       int nargs, i;
 
       if (p->size == 4 || (p->size == 5 && !NILP (omit_port)))
@@ -1284,7 +1295,20 @@ Returns nil if format of ADDRESS is invalid.  */)
        return Qnil;
 
       for (i = 0; i < nargs; i++)
        return Qnil;
 
       for (i = 0; i < nargs; i++)
-       args[i+1] = p->contents[i];
+       {
+         EMACS_INT element = XINT (p->contents[i]);
+
+         if (element < 0 || element > 65535)
+           return Qnil;
+
+         if (nargs <= 5         /* IPv4 */
+             && i < 4           /* host, not port */
+             && element > 255)
+           return Qnil;
+
+         args[i+1] = p->contents[i];
+       }
+
       return Fformat (nargs+1, args);
     }
 
       return Fformat (nargs+1, args);
     }
 
@@ -1294,7 +1318,6 @@ Returns nil if format of ADDRESS is invalid.  */)
       args[0] = build_string ("<Family %d>");
       args[1] = Fcar (address);
       return Fformat (2, args);
       args[0] = build_string ("<Family %d>");
       args[1] = Fcar (address);
       return Fformat (2, args);
-
     }
 
   return Qnil;
     }
 
   return Qnil;
@@ -1310,6 +1333,7 @@ list_processes_1 (query_only)
   register struct Lisp_Process *p;
   char tembuf[300];
   int w_proc, w_buffer, w_tty;
   register struct Lisp_Process *p;
   char tembuf[300];
   int w_proc, w_buffer, w_tty;
+  int exited = 0;
   Lisp_Object i_status, i_buffer, i_tty, i_command;
 
   w_proc = 4;    /* Proc   */
   Lisp_Object i_status, i_buffer, i_tty, i_command;
 
   w_proc = 4;    /* Proc   */
@@ -1399,7 +1423,6 @@ list_processes_1 (query_only)
       if (CONSP (p->status))
        symbol = XCAR (p->status);
 
       if (CONSP (p->status))
        symbol = XCAR (p->status);
 
-
       if (EQ (symbol, Qsignal))
        {
          Lisp_Object tem;
       if (EQ (symbol, Qsignal))
        {
          Lisp_Object tem;
@@ -1436,8 +1459,8 @@ list_processes_1 (query_only)
            }
        }
 
            }
        }
 
-      if (EQ (symbol, Qsignal) || EQ (symbol, Qexit))
-       remove_process (proc);
+      if (EQ (symbol, Qsignal) || EQ (symbol, Qexit) || EQ (symbol, Qclosed))
+       exited++;
 
       Findent_to (i_buffer, minspace);
       if (NILP (p->buffer))
 
       Findent_to (i_buffer, minspace);
       if (NILP (p->buffer))
@@ -1501,6 +1524,8 @@ list_processes_1 (query_only)
          insert_string ("\n");
        }
     }
          insert_string ("\n");
        }
     }
+  if (exited)
+    status_notify (NULL);
   return Qnil;
 }
 
   return Qnil;
 }
 
@@ -1533,13 +1558,19 @@ DEFUN ("start-process", Fstart_process, Sstart_process, 3, MANY, 0,
        doc: /* Start a program in a subprocess.  Return the process object for it.
 NAME is name for process.  It is modified if necessary to make it unique.
 BUFFER is the buffer (or buffer name) to associate with the process.
        doc: /* Start a program in a subprocess.  Return the process object for it.
 NAME is name for process.  It is modified if necessary to make it unique.
 BUFFER is the buffer (or buffer name) to associate with the process.
- Process output goes at end of that buffer, unless you specify
- an output stream or filter function to handle the output.
- BUFFER may be also nil, meaning that this process is not associated
- with any buffer.
+
+Process output (both standard output and standard error streams) goes
+at end of BUFFER, unless you specify an output stream or filter
+function to handle the output.  BUFFER may also be nil, meaning that
+this process is not associated with any buffer.
+
 PROGRAM is the program file name.  It is searched for in PATH.
 Remaining arguments are strings to give program as arguments.
 
 PROGRAM is the program file name.  It is searched for in PATH.
 Remaining arguments are strings to give program as arguments.
 
+If you want to separate standard output from standard error, invoke
+the command through a shell and redirect one of them using the shell
+syntax.
+
 usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
      (nargs, args)
      int nargs;
 usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
      (nargs, args)
      int nargs;
@@ -1805,7 +1836,8 @@ create_process (process, new_argv, current_dir)
      char **new_argv;
      Lisp_Object current_dir;
 {
      char **new_argv;
      Lisp_Object current_dir;
 {
-  int pid, inchannel, outchannel;
+  int inchannel, outchannel;
+  pid_t pid;
   int sv[2];
 #ifdef POSIX_SIGNALS
   sigset_t procmask;
   int sv[2];
 #ifdef POSIX_SIGNALS
   sigset_t procmask;
@@ -2690,7 +2722,9 @@ host, and only clients connecting to that address will be accepted.
 
 :service SERVICE -- SERVICE is name of the service desired, or an
 integer specifying a port number to connect to.  If SERVICE is t,
 
 :service SERVICE -- SERVICE is name of the service desired, or an
 integer specifying a port number to connect to.  If SERVICE is t,
-a random port number is selected for the server.
+a random port number is selected for the server.  (If Emacs was
+compiled with getaddrinfo, a port number can also be specified as a
+string, e.g. "80", as well as an integer.  This is not portable.)
 
 :type TYPE -- TYPE is the type of connection.  The default (nil) is a
 stream type connection, `datagram' creates a datagram type connection.
 
 :type TYPE -- TYPE is the type of connection.  The default (nil) is a
 stream type connection, `datagram' creates a datagram type connection.
@@ -2749,7 +2783,7 @@ The stopped state is cleared by `continue-process' and set by
 
 :filter-multibyte BOOL -- If BOOL is non-nil, strings given to the
 process filter are multibyte, otherwise they are unibyte.
 
 :filter-multibyte BOOL -- If BOOL is non-nil, strings given to the
 process filter are multibyte, otherwise they are unibyte.
-If this keyword is not specified, the strings are multibyte iff
+If this keyword is not specified, the strings are multibyte if
 `default-enable-multibyte-characters' is non-nil.
 
 :sentinel SENTINEL -- Install SENTINEL as the process sentinel.
 `default-enable-multibyte-characters' is non-nil.
 
 :sentinel SENTINEL -- Install SENTINEL as the process sentinel.
@@ -2893,7 +2927,7 @@ usage: (make-network-process &rest ARGS)  */)
   /* Make QCaddress an alias for :local (server) or :remote (client).  */
   QCaddress = is_server ? QClocal : QCremote;
 
   /* Make QCaddress an alias for :local (server) or :remote (client).  */
   QCaddress = is_server ? QClocal : QCremote;
 
-  /* :wait BOOL */
+  /* :nowait BOOL */
   if (!is_server && socktype == SOCK_STREAM
       && (tem = Fplist_get (contact, QCnowait), !NILP (tem)))
     {
   if (!is_server && socktype == SOCK_STREAM
       && (tem = Fplist_get (contact, QCnowait), !NILP (tem)))
     {
@@ -3321,13 +3355,17 @@ usage: (make-network-process &rest ARGS)  */)
 #endif
     }
 
 #endif
     }
 
+  immediate_quit = 0;
+
 #ifdef HAVE_GETADDRINFO
   if (res != &ai)
 #ifdef HAVE_GETADDRINFO
   if (res != &ai)
-    freeaddrinfo (res);
+    {
+      BLOCK_INPUT;
+      freeaddrinfo (res);
+      UNBLOCK_INPUT;
+    }
 #endif
 
 #endif
 
-  immediate_quit = 0;
-
   /* Discard the unwind protect for closing S, if any.  */
   specpdl_ptr = specpdl + count1;
 
   /* Discard the unwind protect for closing S, if any.  */
   specpdl_ptr = specpdl + count1;
 
@@ -3884,7 +3922,7 @@ it specifies a fractional number of seconds to wait.
 If optional fourth arg JUST-THIS-ONE is non-nil, only accept output
 from PROCESS, suspending reading output from other processes.
 If JUST-THIS-ONE is an integer, don't run any timers either.
 If optional fourth arg JUST-THIS-ONE is non-nil, only accept output
 from PROCESS, suspending reading output from other processes.
 If JUST-THIS-ONE is an integer, don't run any timers either.
-Return non-nil iff we received any output before the timeout expired.  */)
+Return non-nil if we received any output before the timeout expired.  */)
      (process, seconds, millisec, just_this_one)
      register Lisp_Object process, seconds, millisec, just_this_one;
 {
      (process, seconds, millisec, just_this_one)
      register Lisp_Object process, seconds, millisec, just_this_one;
 {
@@ -4158,6 +4196,14 @@ server_accept_connection (server, channel)
    when not inside wait_reading_process_output.  */
 static int waiting_for_user_input_p;
 
    when not inside wait_reading_process_output.  */
 static int waiting_for_user_input_p;
 
+static Lisp_Object
+wait_reading_process_output_unwind (data)
+     Lisp_Object data;
+{
+  waiting_for_user_input_p = XINT (data);
+  return Qnil;
+}
+
 /* This is here so breakpoints can be put on it.  */
 static void
 wait_reading_process_output_1 ()
 /* This is here so breakpoints can be put on it.  */
 static void
 wait_reading_process_output_1 ()
@@ -4209,16 +4255,16 @@ select_wrapper (n, rfd, wfd, xfd, tmo)
      (and gobble terminal input into the buffer if any arrives).
 
    If WAIT_PROC is specified, wait until something arrives from that
      (and gobble terminal input into the buffer if any arrives).
 
    If WAIT_PROC is specified, wait until something arrives from that
-     process.  The return value is true iff we read some input from
+     process.  The return value is true if we read some input from
      that process.
 
    If JUST_WAIT_PROC is non-nil, handle only output from WAIT_PROC
      (suspending output from other processes).  A negative value
      means don't run any timers either.
 
      that process.
 
    If JUST_WAIT_PROC is non-nil, handle only output from WAIT_PROC
      (suspending output from other processes).  A negative value
      means don't run any timers either.
 
-   If WAIT_PROC is specified, then the function returns true iff we
+   If WAIT_PROC is specified, then the function returns true if we
      received input from that process before the timeout elapsed.
      received input from that process before the timeout elapsed.
-   Otherwise, return true iff we received input from any process.  */
+   Otherwise, return true if we received input from any process.  */
 
 int
 wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
 
 int
 wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
@@ -4240,9 +4286,7 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
   EMACS_TIME timeout, end_time;
   int wait_channel = -1;
   int got_some_input = 0;
   EMACS_TIME timeout, end_time;
   int wait_channel = -1;
   int got_some_input = 0;
-  /* Either nil or a cons cell, the car of which is of interest and
-     may be changed outside of this routine.  */
-  int saved_waiting_for_user_input_p = waiting_for_user_input_p;
+  int count = SPECPDL_INDEX ();
 
   FD_ZERO (&Available);
 #ifdef NON_BLOCKING_CONNECT
 
   FD_ZERO (&Available);
 #ifdef NON_BLOCKING_CONNECT
@@ -4253,6 +4297,8 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
   if (wait_proc != NULL)
     wait_channel = XINT (wait_proc->infd);
 
   if (wait_proc != NULL)
     wait_channel = XINT (wait_proc->infd);
 
+  record_unwind_protect (wait_reading_process_output_unwind,
+                        make_number (waiting_for_user_input_p));
   waiting_for_user_input_p = read_kbd;
 
   /* Since we may need to wait several times,
   waiting_for_user_input_p = read_kbd;
 
   /* Since we may need to wait several times,
@@ -4779,8 +4825,8 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
                 subprocess termination and SIGCHLD.  */
              else if (nread == 0 && !NETCONN_P (proc))
                ;
                 subprocess termination and SIGCHLD.  */
              else if (nread == 0 && !NETCONN_P (proc))
                ;
-#endif                         /* O_NDELAY */
-#endif                         /* O_NONBLOCK */
+#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
 #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
@@ -4791,11 +4837,17 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
                 get a SIGCHLD).
 
                 However, it has been known to happen that the SIGCHLD
                 get a SIGCHLD).
 
                 However, it has been known to happen that the SIGCHLD
-                got lost.  So raise the signl again just in case.
+                got lost.  So raise the signal again just in case.
                 It can't hurt.  */
              else if (nread == -1 && errno == EIO)
                 It can't hurt.  */
              else if (nread == -1 && errno == EIO)
-               kill (getpid (), SIGCHLD);
-#endif                         /* HAVE_PTYS */
+               {
+                 /* Clear the descriptor now, so we only raise the signal once.  */
+                 FD_CLR (channel, &input_wait_mask);
+                 FD_CLR (channel, &non_keyboard_wait_mask);
+
+                 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
              /* If we can detect process termination, don't consider the process
                 gone just because its pipe is closed.  */
 #ifdef SIGCHLD
@@ -4879,7 +4931,7 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
        }                       /* end for each file descriptor */
     }                          /* end while exit conditions not met */
 
        }                       /* end for each file descriptor */
     }                          /* end while exit conditions not met */
 
-  waiting_for_user_input_p = saved_waiting_for_user_input_p;
+  unbind_to (count, Qnil);
 
   /* If calling from keyboard input, do not quit
      since we want to return C-g as an input character.
 
   /* If calling from keyboard input, do not quit
      since we want to return C-g as an input character.
@@ -5124,6 +5176,9 @@ read_process_output (proc, channel)
        }
 
       carryover = nbytes - coding->consumed;
        }
 
       carryover = nbytes - coding->consumed;
+      if (carryover < 0)
+       abort ();
+
       if (SCHARS (p->decoding_buf) < carryover)
        p->decoding_buf = make_uninit_string (carryover);
       bcopy (chars + coding->consumed, SDATA (p->decoding_buf),
       if (SCHARS (p->decoding_buf) < carryover)
        p->decoding_buf = make_uninit_string (carryover);
       bcopy (chars + coding->consumed, SDATA (p->decoding_buf),
@@ -5234,11 +5289,15 @@ read_process_output (proc, channel)
            }
        }
       carryover = nbytes - coding->consumed;
            }
        }
       carryover = nbytes - coding->consumed;
+      if (carryover < 0)
+       abort ();
+
       if (SCHARS (p->decoding_buf) < carryover)
        p->decoding_buf = make_uninit_string (carryover);
       bcopy (chars + coding->consumed, SDATA (p->decoding_buf),
             carryover);
       XSETINT (p->decoding_carryover, carryover);
       if (SCHARS (p->decoding_buf) < carryover)
        p->decoding_buf = make_uninit_string (carryover);
       bcopy (chars + coding->consumed, SDATA (p->decoding_buf),
             carryover);
       XSETINT (p->decoding_carryover, carryover);
+
       /* Adjust the multibyteness of TEXT to that of the buffer.  */
       if (NILP (current_buffer->enable_multibyte_characters)
          != ! STRING_MULTIBYTE (text))
       /* Adjust the multibyteness of TEXT to that of the buffer.  */
       if (NILP (current_buffer->enable_multibyte_characters)
          != ! STRING_MULTIBYTE (text))
@@ -5632,6 +5691,91 @@ send_process (proc, buf, len, object)
   UNGCPRO;
 }
 
   UNGCPRO;
 }
 
+static Lisp_Object
+send_process_object_unwind (buf)
+     Lisp_Object buf;
+{
+  Lisp_Object tembuf;
+
+  if (XBUFFER (buf) == current_buffer)
+    return Qnil;
+  tembuf = Fcurrent_buffer ();
+  Fset_buffer (buf);
+  Fkill_buffer (tembuf);
+  return Qnil;
+}
+
+/* Send current contents of region between START and END to PROC.
+   If START is a string, send it instead.
+   This function can evaluate Lisp code and can garbage collect.  */
+
+static void
+send_process_object (proc, start, end)
+     Lisp_Object proc, start, end;
+{
+  int count = SPECPDL_INDEX ();
+  Lisp_Object object = STRINGP (start) ? start : Fcurrent_buffer ();
+  struct buffer *given_buffer = current_buffer;
+  unsigned char *buf;
+  int len;
+
+  record_unwind_protect (send_process_object_unwind, Fcurrent_buffer ());
+
+  if (STRINGP (object) ? STRING_MULTIBYTE (object)
+      : ! NILP (XBUFFER (object)->enable_multibyte_characters))
+    {
+      struct Lisp_Process *p = XPROCESS (proc);
+      struct coding_system *coding;
+
+      if (p->raw_status_new)
+       update_status (p);
+      if (! EQ (p->status, Qrun))
+       error ("Process %s not running", SDATA (p->name));
+      if (XINT (p->outfd) < 0)
+       error ("Output file descriptor of %s is closed", SDATA (p->name));
+
+      coding = proc_encode_coding_system[XINT (p->outfd)];
+      if (! EQ (coding->symbol, p->encode_coding_system))
+       /* The coding system for encoding was changed to raw-text
+          because we sent a unibyte text previously.  Now we are
+          sending a multibyte text, thus we must encode it by the
+          original coding system specified for the current process.  */
+       setup_coding_system (p->encode_coding_system, coding);
+      if (! NILP (coding->pre_write_conversion))
+       {
+         struct gcpro gcpro1, gcpro2;
+
+         GCPRO2 (proc, object);
+         call2 (coding->pre_write_conversion, start, end);
+         UNGCPRO;
+         if (given_buffer != current_buffer)
+           {
+             start = make_number (BEGV), end = make_number (ZV);
+             object = Fcurrent_buffer ();
+           }
+       }
+    }
+
+  if (BUFFERP (object))
+    {
+      EMACS_INT start_byte;
+
+      if (XINT (start) < GPT && XINT (end) > GPT)
+       move_gap (XINT (end));
+      start_byte = CHAR_TO_BYTE (XINT (start));
+      buf = BYTE_POS_ADDR (start_byte);
+      len = CHAR_TO_BYTE (XINT (end)) - start_byte;
+    }
+  else
+    {
+      buf = SDATA (object);
+      len = SBYTES (object);
+    }
+  send_process (proc, buf, len, object);
+
+  unbind_to (count, Qnil);
+}
+
 DEFUN ("process-send-region", Fprocess_send_region, Sprocess_send_region,
        3, 3, 0,
        doc: /* Send current contents of region as input to PROCESS.
 DEFUN ("process-send-region", Fprocess_send_region, Sprocess_send_region,
        3, 3, 0,
        doc: /* Send current contents of region as input to PROCESS.
@@ -5645,19 +5789,10 @@ Output from processes can arrive in between bunches.  */)
      Lisp_Object process, start, end;
 {
   Lisp_Object proc;
      Lisp_Object process, start, end;
 {
   Lisp_Object proc;
-  int start1, end1;
 
   proc = get_process (process);
   validate_region (&start, &end);
 
   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 ());
-
+  send_process_object (proc, start, end);
   return Qnil;
 }
 
   return Qnil;
 }
 
@@ -5675,8 +5810,7 @@ Output from processes can arrive in between bunches.  */)
   Lisp_Object proc;
   CHECK_STRING (string);
   proc = get_process (process);
   Lisp_Object proc;
   CHECK_STRING (string);
   proc = get_process (process);
-  send_process (proc, SDATA (string),
-               SBYTES (string), string);
+  send_process_object (proc, string, Qnil);
   return Qnil;
 }
 \f
   return Qnil;
 }
 \f
@@ -6079,7 +6213,7 @@ If PROCESS is a network process, resume handling of incoming traffic.  */)
 DEFUN ("signal-process", Fsignal_process, Ssignal_process,
        2, 2, "sProcess (name or number): \nnSignal code: ",
        doc: /* Send PROCESS the signal with code SIGCODE.
 DEFUN ("signal-process", Fsignal_process, Ssignal_process,
        2, 2, "sProcess (name or number): \nnSignal code: ",
        doc: /* Send PROCESS the signal with code SIGCODE.
-PROCESS may also be an integer specifying the process id of the
+PROCESS may also be a number specifying the process id of the
 process to signal; in this case, the process need not be a child of
 this Emacs.
 SIGCODE may be an integer, or a symbol whose name is a signal name.  */)
 process to signal; in this case, the process need not be a child of
 this Emacs.
 SIGCODE may be an integer, or a symbol whose name is a signal name.  */)
@@ -6096,7 +6230,7 @@ SIGCODE may be an integer, or a symbol whose name is a signal name.  */)
 
   if (FLOATP (process))
     {
 
   if (FLOATP (process))
     {
-      pid = (pid_t) XFLOAT (process);
+      pid = (pid_t) XFLOAT_DATA (process);
       goto got_it;
     }
 
       goto got_it;
     }
 
@@ -6124,8 +6258,8 @@ SIGCODE may be an integer, or a symbol whose name is a signal name.  */)
 
  got_it:
 
 
  got_it:
 
-#define handle_signal(NAME, VALUE)             \
-  else if (!strcmp (name, NAME))               \
+#define parse_signal(NAME, VALUE)              \
+  else if (!xstricmp (name, NAME))             \
     XSETINT (sigcode, VALUE)
 
   if (INTEGERP (sigcode))
     XSETINT (sigcode, VALUE)
 
   if (INTEGERP (sigcode))
@@ -6137,106 +6271,106 @@ SIGCODE may be an integer, or a symbol whose name is a signal name.  */)
       CHECK_SYMBOL (sigcode);
       name = SDATA (SYMBOL_NAME (sigcode));
 
       CHECK_SYMBOL (sigcode);
       name = SDATA (SYMBOL_NAME (sigcode));
 
-      if (!strncmp(name, "SIG", 3))
+      if (!strncmp(name, "SIG", 3) || !strncmp(name, "sig", 3))
        name += 3;
 
       if (0)
        ;
        name += 3;
 
       if (0)
        ;
+#ifdef SIGUSR1
+      parse_signal ("usr1", SIGUSR1);
+#endif
+#ifdef SIGUSR2
+      parse_signal ("usr2", SIGUSR2);
+#endif
+#ifdef SIGTERM
+      parse_signal ("term", SIGTERM);
+#endif
 #ifdef SIGHUP
 #ifdef SIGHUP
-      handle_signal ("HUP", SIGHUP);
+      parse_signal ("hup", SIGHUP);
 #endif
 #ifdef SIGINT
 #endif
 #ifdef SIGINT
-      handle_signal ("INT", SIGINT);
+      parse_signal ("int", SIGINT);
 #endif
 #ifdef SIGQUIT
 #endif
 #ifdef SIGQUIT
-      handle_signal ("QUIT", SIGQUIT);
+      parse_signal ("quit", SIGQUIT);
 #endif
 #ifdef SIGILL
 #endif
 #ifdef SIGILL
-      handle_signal ("ILL", SIGILL);
+      parse_signal ("ill", SIGILL);
 #endif
 #ifdef SIGABRT
 #endif
 #ifdef SIGABRT
-      handle_signal ("ABRT", SIGABRT);
+      parse_signal ("abrt", SIGABRT);
 #endif
 #ifdef SIGEMT
 #endif
 #ifdef SIGEMT
-      handle_signal ("EMT", SIGEMT);
+      parse_signal ("emt", SIGEMT);
 #endif
 #ifdef SIGKILL
 #endif
 #ifdef SIGKILL
-      handle_signal ("KILL", SIGKILL);
+      parse_signal ("kill", SIGKILL);
 #endif
 #ifdef SIGFPE
 #endif
 #ifdef SIGFPE
-      handle_signal ("FPE", SIGFPE);
+      parse_signal ("fpe", SIGFPE);
 #endif
 #ifdef SIGBUS
 #endif
 #ifdef SIGBUS
-      handle_signal ("BUS", SIGBUS);
+      parse_signal ("bus", SIGBUS);
 #endif
 #ifdef SIGSEGV
 #endif
 #ifdef SIGSEGV
-      handle_signal ("SEGV", SIGSEGV);
+      parse_signal ("segv", SIGSEGV);
 #endif
 #ifdef SIGSYS
 #endif
 #ifdef SIGSYS
-      handle_signal ("SYS", SIGSYS);
+      parse_signal ("sys", SIGSYS);
 #endif
 #ifdef SIGPIPE
 #endif
 #ifdef SIGPIPE
-      handle_signal ("PIPE", SIGPIPE);
+      parse_signal ("pipe", SIGPIPE);
 #endif
 #ifdef SIGALRM
 #endif
 #ifdef SIGALRM
-      handle_signal ("ALRM", SIGALRM);
-#endif
-#ifdef SIGTERM
-      handle_signal ("TERM", SIGTERM);
+      parse_signal ("alrm", SIGALRM);
 #endif
 #ifdef SIGURG
 #endif
 #ifdef SIGURG
-      handle_signal ("URG", SIGURG);
+      parse_signal ("urg", SIGURG);
 #endif
 #ifdef SIGSTOP
 #endif
 #ifdef SIGSTOP
-      handle_signal ("STOP", SIGSTOP);
+      parse_signal ("stop", SIGSTOP);
 #endif
 #ifdef SIGTSTP
 #endif
 #ifdef SIGTSTP
-      handle_signal ("TSTP", SIGTSTP);
+      parse_signal ("tstp", SIGTSTP);
 #endif
 #ifdef SIGCONT
 #endif
 #ifdef SIGCONT
-      handle_signal ("CONT", SIGCONT);
+      parse_signal ("cont", SIGCONT);
 #endif
 #ifdef SIGCHLD
 #endif
 #ifdef SIGCHLD
-      handle_signal ("CHLD", SIGCHLD);
+      parse_signal ("chld", SIGCHLD);
 #endif
 #ifdef SIGTTIN
 #endif
 #ifdef SIGTTIN
-      handle_signal ("TTIN", SIGTTIN);
+      parse_signal ("ttin", SIGTTIN);
 #endif
 #ifdef SIGTTOU
 #endif
 #ifdef SIGTTOU
-      handle_signal ("TTOU", SIGTTOU);
+      parse_signal ("ttou", SIGTTOU);
 #endif
 #ifdef SIGIO
 #endif
 #ifdef SIGIO
-      handle_signal ("IO", SIGIO);
+      parse_signal ("io", SIGIO);
 #endif
 #ifdef SIGXCPU
 #endif
 #ifdef SIGXCPU
-      handle_signal ("XCPU", SIGXCPU);
+      parse_signal ("xcpu", SIGXCPU);
 #endif
 #ifdef SIGXFSZ
 #endif
 #ifdef SIGXFSZ
-      handle_signal ("XFSZ", SIGXFSZ);
+      parse_signal ("xfsz", SIGXFSZ);
 #endif
 #ifdef SIGVTALRM
 #endif
 #ifdef SIGVTALRM
-      handle_signal ("VTALRM", SIGVTALRM);
+      parse_signal ("vtalrm", SIGVTALRM);
 #endif
 #ifdef SIGPROF
 #endif
 #ifdef SIGPROF
-      handle_signal ("PROF", SIGPROF);
+      parse_signal ("prof", SIGPROF);
 #endif
 #ifdef SIGWINCH
 #endif
 #ifdef SIGWINCH
-      handle_signal ("WINCH", SIGWINCH);
+      parse_signal ("winch", SIGWINCH);
 #endif
 #ifdef SIGINFO
 #endif
 #ifdef SIGINFO
-      handle_signal ("INFO", SIGINFO);
-#endif
-#ifdef SIGUSR1
-      handle_signal ("USR1", SIGUSR1);
-#endif
-#ifdef SIGUSR2
-      handle_signal ("USR2", SIGUSR2);
+      parse_signal ("info", SIGINFO);
 #endif
       else
        error ("Undefined signal name %s", name);
     }
 
 #endif
       else
        error ("Undefined signal name %s", name);
     }
 
-#undef handle_signal
+#undef parse_signal
 
   return make_number (kill (pid, XINT (sigcode)));
 }
 
   return make_number (kill (pid, XINT (sigcode)));
 }
@@ -6383,7 +6517,7 @@ sigchld_handler (signo)
 
   while (1)
     {
 
   while (1)
     {
-      register int pid;
+      pid_t pid;
       WAITTYPE w;
       Lisp_Object tail;
 
       WAITTYPE w;
       Lisp_Object tail;
 
@@ -6393,7 +6527,7 @@ sigchld_handler (signo)
 #endif /* no WUNTRACED */
       /* Keep trying to get a status until we get a definitive result.  */
       do
 #endif /* no WUNTRACED */
       /* Keep trying to get a status until we get a definitive result.  */
       do
-       {
+        {
          errno = 0;
          pid = wait3 (&w, WNOHANG | WUNTRACED, 0);
        }
          errno = 0;
          pid = wait3 (&w, WNOHANG | WUNTRACED, 0);
        }
@@ -6423,11 +6557,15 @@ sigchld_handler (signo)
       /* Find the process that signaled us, and record its status.  */
 
       /* The process can have been deleted by Fdelete_process.  */
       /* Find the process that signaled us, and record its status.  */
 
       /* The process can have been deleted by Fdelete_process.  */
-      tail = Fmember (make_fixnum_or_float (pid), deleted_pid_list);
-      if (!NILP (tail))
+      for (tail = deleted_pid_list; GC_CONSP (tail); tail = XCDR (tail))
        {
        {
-         Fsetcar (tail, Qnil);
-         goto sigchld_end_of_loop;
+         Lisp_Object xpid = XCAR (tail);
+         if ((GC_INTEGERP (xpid) && pid == (pid_t) XINT (xpid))
+             || (GC_FLOATP (xpid) && pid == (pid_t) XFLOAT_DATA (xpid)))
+           {
+             XSETCAR (tail, Qnil);
+             goto sigchld_end_of_loop;
+           }
        }
 
       /* Otherwise, if it is asynchronous, it is in Vprocess_alist.  */
        }
 
       /* Otherwise, if it is asynchronous, it is in Vprocess_alist.  */
@@ -6551,6 +6689,9 @@ exec_sentinel (proc, reason)
   int outer_running_asynch_code = running_asynch_code;
   int waiting = waiting_for_user_input_p;
 
   int outer_running_asynch_code = running_asynch_code;
   int waiting = waiting_for_user_input_p;
 
+  if (inhibit_sentinels)
+    return;
+
   /* 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;
   /* 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;
@@ -6880,6 +7021,8 @@ init_process ()
 {
   register int i;
 
 {
   register int i;
 
+  inhibit_sentinels = 0;
+
 #ifdef SIGCHLD
 #ifndef CANNOT_DUMP
   if (! noninteractive || initialized)
 #ifdef SIGCHLD
 #ifndef CANNOT_DUMP
   if (! noninteractive || initialized)
@@ -7052,7 +7195,7 @@ syms_of_process ()
 
   DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes,
               doc: /* *Non-nil means delete processes immediately when they exit.
 
   DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes,
               doc: /* *Non-nil means delete processes immediately when they exit.
-nil means don't delete them until `list-processes' is run.  */);
+A value of nil means don't delete them until `list-processes' is run.  */);
 
   delete_exited_processes = 1;
 
 
   delete_exited_processes = 1;
 
@@ -7183,7 +7326,7 @@ Lisp_Object QCtype;
    do_display != 0 means redisplay should be done to show subprocess
    output that arrives.
 
    do_display != 0 means redisplay should be done to show subprocess
    output that arrives.
 
-   Return true iff we received input from any process.  */
+   Return true if we received input from any process.  */
 
 int
 wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
 
 int
 wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,