(mouse-autoselect-window-cancel): Don't cancel for
[bpt/emacs.git] / src / process.c
index ecaf808..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,
-                 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
-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,
@@ -149,8 +149,7 @@ Boston, MA 02110-1301, USA.  */
 #include "atimer.h"
 
 Lisp_Object Qprocessp;
-Lisp_Object Qrun, Qstop;
-extern Lisp_Object Qsignal;
+Lisp_Object Qrun, Qstop, Qsignal;
 Lisp_Object Qopen, Qclosed, Qconnect, Qfailed, Qlisten;
 Lisp_Object Qlocal, Qipv4, Qdatagram;
 #ifdef AF_INET6
@@ -816,9 +815,12 @@ nil, indicating the current buffer's process.  */)
     {
 #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.  */
-      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.  */
@@ -828,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))
-       Fdelete (make_fixnum_or_float (p->pid), deleted_pid_list);
+       deleted_pid_list
+         = Fdelete (make_fixnum_or_float (pid), deleted_pid_list);
       else
 #endif
        {
@@ -913,10 +916,13 @@ For a network connection, this value is nil.  */)
      (process)
      register Lisp_Object process;
 {
+  /* Assignment to EMACS_INT stops GCC whining about limited range of
+     data type.  */
+  EMACS_INT pid;
+
   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,
@@ -1262,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);
-      Lisp_Object args[6];
+      Lisp_Object args[10];
       int nargs, i;
 
       if (p->size == 4 || (p->size == 5 && !NILP (omit_port)))
@@ -1289,7 +1295,20 @@ Returns nil if format of ADDRESS is invalid.  */)
        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);
     }
 
@@ -1299,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);
-
     }
 
   return Qnil;
@@ -1405,7 +1423,6 @@ list_processes_1 (query_only)
       if (CONSP (p->status))
        symbol = XCAR (p->status);
 
-
       if (EQ (symbol, Qsignal))
        {
          Lisp_Object tem;
@@ -1541,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.
- 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.
 
+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;
@@ -1813,7 +1836,8 @@ create_process (process, new_argv, 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;
@@ -2698,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,
-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.
@@ -2757,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.
-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.
@@ -2901,7 +2927,7 @@ usage: (make-network-process &rest ARGS)  */)
   /* 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)))
     {
@@ -3329,13 +3355,17 @@ usage: (make-network-process &rest ARGS)  */)
 #endif
     }
 
+  immediate_quit = 0;
+
 #ifdef HAVE_GETADDRINFO
   if (res != &ai)
-    freeaddrinfo (res);
+    {
+      BLOCK_INPUT;
+      freeaddrinfo (res);
+      UNBLOCK_INPUT;
+    }
 #endif
 
-  immediate_quit = 0;
-
   /* Discard the unwind protect for closing S, if any.  */
   specpdl_ptr = specpdl + count1;
 
@@ -3892,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.
-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;
 {
@@ -4225,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
-     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.
 
-   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.
-   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,
@@ -4795,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))
                ;
-#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
@@ -4807,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
-                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)
-               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
@@ -5655,6 +5691,91 @@ send_process (proc, buf, len, object)
   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.
@@ -5668,19 +5789,10 @@ Output from processes can arrive in between bunches.  */)
      Lisp_Object process, start, end;
 {
   Lisp_Object proc;
-  int start1, end1;
 
   proc = get_process (process);
   validate_region (&start, &end);
-
-  if (XINT (start) < GPT && XINT (end) > GPT)
-    move_gap (XINT (start));
-
-  start1 = CHAR_TO_BYTE (XINT (start));
-  end1 = CHAR_TO_BYTE (XINT (end));
-  send_process (proc, BYTE_POS_ADDR (start1), end1 - start1,
-               Fcurrent_buffer ());
-
+  send_process_object (proc, start, end);
   return Qnil;
 }
 
@@ -5698,8 +5810,7 @@ Output from processes can arrive in between bunches.  */)
   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
@@ -6102,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.
-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.  */)
@@ -6119,7 +6230,7 @@ SIGCODE may be an integer, or a symbol whose name is a signal name.  */)
 
   if (FLOATP (process))
     {
-      pid = (pid_t) XFLOAT (process);
+      pid = (pid_t) XFLOAT_DATA (process);
       goto got_it;
     }
 
@@ -6147,8 +6258,8 @@ SIGCODE may be an integer, or a symbol whose name is a signal name.  */)
 
  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))
@@ -6160,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));
 
-      if (!strncmp(name, "SIG", 3))
+      if (!strncmp(name, "SIG", 3) || !strncmp(name, "sig", 3))
        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
-      handle_signal ("HUP", SIGHUP);
+      parse_signal ("hup", SIGHUP);
 #endif
 #ifdef SIGINT
-      handle_signal ("INT", SIGINT);
+      parse_signal ("int", SIGINT);
 #endif
 #ifdef SIGQUIT
-      handle_signal ("QUIT", SIGQUIT);
+      parse_signal ("quit", SIGQUIT);
 #endif
 #ifdef SIGILL
-      handle_signal ("ILL", SIGILL);
+      parse_signal ("ill", SIGILL);
 #endif
 #ifdef SIGABRT
-      handle_signal ("ABRT", SIGABRT);
+      parse_signal ("abrt", SIGABRT);
 #endif
 #ifdef SIGEMT
-      handle_signal ("EMT", SIGEMT);
+      parse_signal ("emt", SIGEMT);
 #endif
 #ifdef SIGKILL
-      handle_signal ("KILL", SIGKILL);
+      parse_signal ("kill", SIGKILL);
 #endif
 #ifdef SIGFPE
-      handle_signal ("FPE", SIGFPE);
+      parse_signal ("fpe", SIGFPE);
 #endif
 #ifdef SIGBUS
-      handle_signal ("BUS", SIGBUS);
+      parse_signal ("bus", SIGBUS);
 #endif
 #ifdef SIGSEGV
-      handle_signal ("SEGV", SIGSEGV);
+      parse_signal ("segv", SIGSEGV);
 #endif
 #ifdef SIGSYS
-      handle_signal ("SYS", SIGSYS);
+      parse_signal ("sys", SIGSYS);
 #endif
 #ifdef SIGPIPE
-      handle_signal ("PIPE", SIGPIPE);
+      parse_signal ("pipe", SIGPIPE);
 #endif
 #ifdef SIGALRM
-      handle_signal ("ALRM", SIGALRM);
-#endif
-#ifdef SIGTERM
-      handle_signal ("TERM", SIGTERM);
+      parse_signal ("alrm", SIGALRM);
 #endif
 #ifdef SIGURG
-      handle_signal ("URG", SIGURG);
+      parse_signal ("urg", SIGURG);
 #endif
 #ifdef SIGSTOP
-      handle_signal ("STOP", SIGSTOP);
+      parse_signal ("stop", SIGSTOP);
 #endif
 #ifdef SIGTSTP
-      handle_signal ("TSTP", SIGTSTP);
+      parse_signal ("tstp", SIGTSTP);
 #endif
 #ifdef SIGCONT
-      handle_signal ("CONT", SIGCONT);
+      parse_signal ("cont", SIGCONT);
 #endif
 #ifdef SIGCHLD
-      handle_signal ("CHLD", SIGCHLD);
+      parse_signal ("chld", SIGCHLD);
 #endif
 #ifdef SIGTTIN
-      handle_signal ("TTIN", SIGTTIN);
+      parse_signal ("ttin", SIGTTIN);
 #endif
 #ifdef SIGTTOU
-      handle_signal ("TTOU", SIGTTOU);
+      parse_signal ("ttou", SIGTTOU);
 #endif
 #ifdef SIGIO
-      handle_signal ("IO", SIGIO);
+      parse_signal ("io", SIGIO);
 #endif
 #ifdef SIGXCPU
-      handle_signal ("XCPU", SIGXCPU);
+      parse_signal ("xcpu", SIGXCPU);
 #endif
 #ifdef SIGXFSZ
-      handle_signal ("XFSZ", SIGXFSZ);
+      parse_signal ("xfsz", SIGXFSZ);
 #endif
 #ifdef SIGVTALRM
-      handle_signal ("VTALRM", SIGVTALRM);
+      parse_signal ("vtalrm", SIGVTALRM);
 #endif
 #ifdef SIGPROF
-      handle_signal ("PROF", SIGPROF);
+      parse_signal ("prof", SIGPROF);
 #endif
 #ifdef SIGWINCH
-      handle_signal ("WINCH", SIGWINCH);
+      parse_signal ("winch", SIGWINCH);
 #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);
     }
 
-#undef handle_signal
+#undef parse_signal
 
   return make_number (kill (pid, XINT (sigcode)));
 }
@@ -6406,7 +6517,7 @@ sigchld_handler (signo)
 
   while (1)
     {
-      register int pid;
+      pid_t pid;
       WAITTYPE w;
       Lisp_Object tail;
 
@@ -6416,7 +6527,7 @@ sigchld_handler (signo)
 #endif /* no WUNTRACED */
       /* Keep trying to get a status until we get a definitive result.  */
       do
-       {
+        {
          errno = 0;
          pid = wait3 (&w, WNOHANG | WUNTRACED, 0);
        }
@@ -6446,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.  */
-      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.  */
@@ -7005,6 +7120,8 @@ syms_of_process ()
   staticpro (&Qrun);
   Qstop = intern ("stop");
   staticpro (&Qstop);
+  Qsignal = intern ("signal");
+  staticpro (&Qsignal);
 
   /* Qexit is already staticpro'd by syms_of_eval; don't staticpro it
      here again.
@@ -7209,7 +7326,7 @@ Lisp_Object QCtype;
    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,