(status_notify): Use assignment, not initialization.
[bpt/emacs.git] / src / process.c
index b8fac56..d954de1 100644 (file)
@@ -1,5 +1,5 @@
 /* Asynchronous subprocess control for GNU Emacs.
-   Copyright (C) 1985, 1986, 1987, 1988, 1993 Free Software Foundation, Inc.
+   Copyright (C) 1985, 86, 87, 88, 93, 94 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -38,6 +38,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <sys/types.h>         /* some typedefs are used in sys/file.h */
 #include <sys/file.h>
 #include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 
 #ifdef HAVE_SOCKETS    /* TCP connection support, if kernel can do it */
 #include <sys/socket.h>
@@ -125,10 +128,13 @@ static Lisp_Object stream_process;
 
 #include "syswait.h"
 
-extern errno;
-extern sys_nerr;
+extern int errno;
+extern char *strerror ();
+#ifdef VMS
 extern char *sys_errlist[];
+#endif
 
+#ifndef SYS_SIGLIST_DECLARED
 #ifndef VMS
 #ifndef BSD4_1
 #ifndef LINUX
@@ -166,6 +172,7 @@ char *sys_siglist[] =
     };
 #endif
 #endif /* VMS */
+#endif /* ! SYS_SIGLIST_DECLARED */
 
 /* t means use pty, nil means use a pipe,
    maybe other values to come.  */
@@ -215,10 +222,10 @@ static int keyboard_descriptor;
 static int delete_exited_processes;
 
 /* Indexed by descriptor, gives the process (if any) for that descriptor */
-static Lisp_Object chan_process[MAXDESC];
+Lisp_Object chan_process[MAXDESC];
 
 /* Alist of elements (NAME . PROCESS) */
-static Lisp_Object Vprocess_alist;
+Lisp_Object Vprocess_alist;
 
 /* Buffered-ahead input char from process, indexed by channel.
    -1 means empty (no char is buffered).
@@ -229,6 +236,9 @@ static Lisp_Object Vprocess_alist;
 static int proc_buffered_char[MAXDESC];
 
 static Lisp_Object get_process ();
+
+/* Maximum number of bytes to send to a pty without an eof.  */
+static int pty_max_bytes;
 \f
 /* Compute the Lisp form of the process status, p->status, from
    the numeric status that was returned by `wait'.  */
@@ -306,11 +316,18 @@ status_message (status)
 
   if (EQ (symbol, Qsignal) || EQ (symbol, Qstop))
     {
+      char *signame = 0;
+      if (code < NSIG)
+       {
 #ifndef VMS
-      string = build_string (code < NSIG ? sys_siglist[code] : "unknown");
+         signame = sys_siglist[code];
 #else
-      string = build_string (code < NSIG ? sys_errlist[code] : "unknown");
+         signame = sys_errlist[code];
 #endif
+       }
+      if (signame == 0)
+       signame = "unknown";
+      string = build_string (signame);
       string2 = build_string (coredump ? " (core dumped)\n" : "\n");
       XSTRING (string)->data[0] = DOWNCASE (XSTRING (string)->data[0]);
       return concat2 (string, string2);
@@ -526,24 +543,34 @@ static Lisp_Object
 get_process (name)
      register Lisp_Object name;
 {
-  register Lisp_Object proc;
-  if (NILP (name))
-    proc = Fget_buffer_process (Fcurrent_buffer ());
+  register Lisp_Object proc, obj;
+  if (STRINGP (name))
+    {
+      obj = Fget_process (name);
+      if (NILP (obj))
+       obj = Fget_buffer (name);
+      if (NILP (obj))
+       error ("Process %s does not exist", XSTRING (name)->data);
+    }
+  else if (NILP (name))
+    obj = Fcurrent_buffer ();
   else
+    obj = name;
+
+  /* Now obj should be either a buffer object or a process object.
+   */
+  if (BUFFERP (obj))
     {
-      proc = Fget_process (name);
+      proc = Fget_buffer_process (obj);
       if (NILP (proc))
-       proc = Fget_buffer_process (Fget_buffer (name));
+       error ("Buffer %s has no process", XSTRING (XBUFFER (obj)->name)->data);
     }
-
-  if (!NILP (proc))
-    return proc;
-
-  if (NILP (name))
-    error ("Current buffer has no process");
   else
-    error ("Process %s does not exist", XSTRING (name)->data);
-  /* NOTREACHED */
+    {
+      CHECK_PROCESS (obj, 0);
+      proc = obj;
+    }
+  return proc;
 }
 
 DEFUN ("delete-process", Fdelete_process, Sdelete_process, 1, 1, 0,
@@ -751,7 +778,7 @@ See `set-process-sentinel' for more info on sentinels.")
 DEFUN ("process-kill-without-query", Fprocess_kill_without_query,
   Sprocess_kill_without_query, 1, 2, 0,
   "Say no query needed if PROCESS is running when Emacs is exited.\n\
-Optional second argument if non-nill says to require a query.\n\
+Optional second argument if non-nil says to require a query.\n\
 Value is t if a query was formerly required.")
   (proc, value)
      register Lisp_Object proc, value;
@@ -997,24 +1024,29 @@ Remaining arguments are strings to give program as arguments.")
 #else /* not VMS */
   new_argv = (unsigned char **) alloca ((nargs - 1) * sizeof (char *));
 
-  for (i = 3; i < nargs; i++)
-    {
-      tem = args[i];
-      CHECK_STRING (tem, i);
-      new_argv[i - 2] = XSTRING (tem)->data;
-    }
-  new_argv[i - 2] = 0;
-  new_argv[0] = XSTRING (program)->data;
-
   /* If program file name is not absolute, search our path for it */
-  if (new_argv[0][0] != '/')
+  if (XSTRING (program)->data[0] != '/')
     {
+      struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+
       tem = Qnil;
+      GCPRO4 (name, program, buffer, current_dir);
       openp (Vexec_path, program, EXEC_SUFFIXES, &tem, 1);
+      UNGCPRO;
       if (NILP (tem))
        report_file_error ("Searching for program", Fcons (program, Qnil));
       new_argv[0] = XSTRING (tem)->data;
     }
+  else
+    new_argv[0] = XSTRING (program)->data;
+
+  for (i = 3; i < nargs; i++)
+    {
+      tem = args[i];
+      CHECK_STRING (tem, i);
+      new_argv[i - 2] = XSTRING (tem)->data;
+    }
+  new_argv[i - 2] = 0;
 #endif /* not VMS */
 
   proc = make_process (name);
@@ -1243,12 +1275,13 @@ create_process (process, new_argv, current_dir)
 #endif /* USG */
 #endif /* not HAVE_SETSID */
 #ifdef NTTYDISC
-       {
-         /* Use new line discipline.  */
-         int ldisc = NTTYDISC;
-         if (ioctl (xforkin, TIOCSETD, &ldisc) < 0)
-           write (1, "create_process/TIOCSETD failed\n", 31);
-       }
+       if (pty_flag && xforkin >= 0)
+         {
+           /* Use new line discipline.  */
+           int ldisc = NTTYDISC;
+           if (ioctl (xforkin, TIOCSETD, &ldisc) < 0)
+             write (1, "create_process/TIOCSETD failed\n", 31);
+         }
 #endif
 #ifdef TIOCNOTTY 
        /* In 4.3BSD, the TIOCSPGRP bug has been fixed, and now you
@@ -1821,7 +1854,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
         condition here; if a SIGIO arrives between now and the select
         and indicates that a frame is trashed, the select may block
         displaying a trashed screen.  */
-      if (frame_garbaged)
+      if (frame_garbaged && do_display)
        redisplay_preserve_echo_area ();
 
       if (XINT (read_kbd) && detect_input_pending ())
@@ -1877,7 +1910,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
 #endif
            }
          else
-           error("select error: %s", sys_errlist[xerrno]);
+           error("select error: %s", strerror (xerrno));
        }
 #if defined(sun) && !defined(USG5_4)
       else if (nfds > 0 && FD_ISSET (keyboard_descriptor, &Available)
@@ -2113,7 +2146,7 @@ read_process_output (proc, channel)
 #ifdef VMS
       start_vms_process_read (vs);
 #endif
-      unbind_to (count);
+      unbind_to (count, Qnil);
       return nchars;
     }
 
@@ -2237,12 +2270,31 @@ send_process (proc, buf, len)
       {
        int this = len;
        SIGTYPE (*old_sigpipe)();
+       int flush_pty = 0;
+
+       if (pty_max_bytes == 0)
+         {
+#if defined (HAVE_FPATHCONF) && defined (_PC_MAX_CANON)
+           pty_max_bytes = fpathconf (XFASTINT (XPROCESS (proc)->outfd),
+                                      _PC_MAX_CANON);
+#else
+           pty_max_bytes = 250;
+#endif
+         }
+
+       /* Don't send more than pty_max_bytes bytes at a time.  */
+       /* Subtract 1 to leave room for the EOF.  */
+       if (this >= pty_max_bytes && XPROCESS (proc)->pty_flag != 0)
+         this = pty_max_bytes - 1;
 
-       /* Don't send more than 500 bytes at a time.  */
-       if (this > 500)
-         this = 500;
        old_sigpipe = (SIGTYPE (*) ()) signal (SIGPIPE, send_process_trap);
        rv = write (XINT (XPROCESS (proc)->outfd), buf, this);
+
+       /* If we sent just part of the string, put in an EOF
+          to force it through, before we send the rest.  */
+       if (this < len)
+         Fprocess_send_eof (proc);
+
        signal (SIGPIPE, old_sigpipe);
        if (rv < 0)
          {
@@ -2824,11 +2876,23 @@ sigchld_handler (signo)
          if (WIFEXITED (w))
            synch_process_retcode = WRETCODE (w);
          else if (WIFSIGNALED (w))
+           {
+             int code = WTERMSIG (w);
+             char *signame = 0;
+
+             if (code < NSIG)
+               {
 #ifndef VMS
-           synch_process_death = (char *) sys_siglist[WTERMSIG (w)];
+                 signame = sys_siglist[code];
 #else
-           synch_process_death = sys_errlist[WTERMSIG (w)];
+                 signame = sys_errlist[code];
 #endif
+               }
+             if (signame == 0)
+               signame = "unknown";
+
+             synch_process_death = signame;
+           }
 
          /* Tell wait_reading_process_input that it needs to wake up and
             look around.  */
@@ -2879,7 +2943,7 @@ exec_sentinel (proc, reason)
   /* Inhibit quit so that random quits don't screw up a running filter.  */
   specbind (Qinhibit_quit, Qt);
   call2 (sentinel, proc, reason);
-  unbind_to (count);
+  unbind_to (count, Qnil);
 }
 
 /* Report all recent events of a change in process status
@@ -2889,10 +2953,11 @@ exec_sentinel (proc, reason)
 status_notify ()
 {
   register Lisp_Object proc, buffer;
-  Lisp_Object tail = Qnil;
-  Lisp_Object msg = Qnil;
+  Lisp_Object tail, msg;
   struct gcpro gcpro1, gcpro2;
 
+  tail = Qnil;
+  msg = Qnil;
   /* We need to gcpro tail; if read_process_output calls a filter
      which deletes a process and removes the cons to which tail points
      from Vprocess_alist, and then causes a GC, tail is an unprotected
@@ -2944,11 +3009,12 @@ status_notify ()
             when a process becomes runnable.  */
          else if (!EQ (symbol, Qrun) && !NILP (buffer))
            {
-             Lisp_Object ro = XBUFFER (buffer)->read_only;
-             Lisp_Object tem;
+             Lisp_Object ro, tem;
              struct buffer *old = current_buffer;
              int opoint;
 
+             ro = XBUFFER (buffer)->read_only;
+
              /* Avoid error if buffer is deleted
                 (probably that's why the process is dead, too) */
              if (NILP (XBUFFER (buffer)->name))
@@ -3131,7 +3197,7 @@ extern int frame_garbaged;
      `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.
+   output that arrives.
 
    Return true iff we received input from any process.  */
 
@@ -3198,7 +3264,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
 
       /* If a frame has been newly mapped and needs updating,
         reprocess its display stuff.  */
-      if (frame_garbaged)
+      if (frame_garbaged && do_display)
        redisplay_preserve_echo_area ();
 
       if (XINT (read_kbd) && detect_input_pending ())
@@ -3242,7 +3308,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
 
 
 DEFUN ("get-buffer-process", Fget_buffer_process, Sget_buffer_process, 1, 1, 0,
-  /* Don't confused make-docfile by having two doc strings for this function.
+  /* Don't confuse make-docfile by having two doc strings for this function.
      make-docfile does not pay attention to #if, for good reason!  */
   0)
   (name)