]> code.delx.au - gnu-emacs/blobdiff - src/process.c
(Fset_case_table): Doc fix.
[gnu-emacs] / src / process.c
index cedcb38fa8a571fac9f83e44b47a01b3657c91c4..9862bb30e8563ec24dc75eddf9edba6e565ad592 100644 (file)
@@ -52,6 +52,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <netdb.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#ifdef NEED_NET_ERRNO_H
+#include <net/errno.h>
+#endif /* NEED_NET_ERRNO_H */
 #endif /* HAVE_SOCKETS */
 
 /* TERM is a poor-man's SLIP, used on Linux.  */
@@ -1093,10 +1096,16 @@ Remaining arguments are strings to give program as arguments.")
       UNGCPRO;
       if (NILP (tem))
        report_file_error ("Searching for program", Fcons (program, Qnil));
+      tem = Fexpand_file_name (tem, Qnil);
       new_argv[0] = XSTRING (tem)->data;
     }
   else
-    new_argv[0] = XSTRING (program)->data;
+    {
+      if (!NILP (Ffile_directory_p (program)))
+       error ("Specified program for new process is a directory");
+
+      new_argv[0] = XSTRING (program)->data;
+    }
 
   for (i = 3; i < nargs; i++)
     {
@@ -1186,12 +1195,14 @@ create_process (process, new_argv, current_dir)
      char **new_argv;
      Lisp_Object current_dir;
 {
-  int pid, inchannel, outchannel, forkin, forkout;
+  int pid, inchannel, outchannel;
   int sv[2];
 #ifdef SIGCHLD
   SIGTYPE (*sigchld)();
 #endif
-  int pty_flag = 0;
+  /* Use volatile to protect variables from being clobbered by longjmp.  */
+  volatile int forkin, forkout;
+  volatile int pty_flag = 0;
   extern char **environ;
 
   inchannel = outchannel = -1;
@@ -1656,6 +1667,10 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\
        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;
        }
@@ -1998,7 +2013,9 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
        {
          Atemp = input_wait_mask;
          EMACS_SET_SECS_USECS (timeout, 0, 0);
-         if (select (MAXDESC, &Atemp, 0, 0, &timeout) <= 0)
+         if ((select (MAXDESC, &Atemp, (SELECT_TYPE *)0, (SELECT_TYPE *)0,
+                      &timeout)
+              <= 0))
            {
              /* It's okay for us to do this and then continue with
                 the loop, since timeout has already been zeroed out.  */
@@ -2043,7 +2060,8 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
          FD_ZERO (&Available);
        }
       else
-       nfds = select (MAXDESC, &Available, 0, 0, &timeout);
+       nfds = select (MAXDESC, &Available, (SELECT_TYPE *)0, (SELECT_TYPE *)0,
+                      &timeout);
 
       xerrno = errno;
 
@@ -2369,12 +2387,17 @@ read_process_output (proc, channel)
       /* Handling the process output should not deactivate the mark.  */
       Vdeactivate_mark = odeactivate;
 
+#if 0 /* Call record_asynch_buffer_change unconditionally,
+        because we might have changed minor modes or other things
+        that affect key bindings.  */
       if (! EQ (Fcurrent_buffer (), obuffer)
          || ! EQ (current_buffer->keymap, okeymap))
-       record_asynch_buffer_change ();
-
-      if (waiting_for_user_input_p)
-       prepare_menu_bars ();
+#endif
+       /* But do it only if the caller is actually going to read events.
+          Otherwise there's no need to make him wake up, and it could
+          cause trouble (for example it would make Fsit_for return).  */
+       if (waiting_for_user_input_p == -1)
+         record_asynch_buffer_change ();
 
 #ifdef VMS
       start_vms_process_read (vs);
@@ -2476,14 +2499,14 @@ send_process_trap ()
    OBJECT is the Lisp object that the data comes from.  */
 
 send_process (proc, buf, len, object)
-     Lisp_Object proc;
+     volatile Lisp_Object proc;
      char *buf;
      int len;
      Lisp_Object object;
 {
-  /* Don't use register vars; longjmp can lose them.  */
+  /* Use volatile to protect variables from being clobbered by longjmp.  */
   int rv;
-  unsigned char *procname = XSTRING (XPROCESS (proc)->name)->data;
+  volatile unsigned char *procname = XSTRING (XPROCESS (proc)->name)->data;
 
 #ifdef VMS
   struct Lisp_Process *p = XPROCESS (proc);
@@ -3242,8 +3265,8 @@ sigchld_handler (signo)
          
          XSETINT (p->tick, ++process_tick);
          u.wt = w;
-         XSETFASTINT (p->raw_status_low, u.i & 0xffff);
-         XSETFASTINT (p->raw_status_high, u.i >> 16);
+         XSETINT (p->raw_status_low, u.i & 0xffff);
+         XSETINT (p->raw_status_high, u.i >> 16);
          
          /* If process has terminated, stop waiting for its output.  */
          if ((WIFSIGNALED (w) || WIFEXITED (w))
@@ -3368,12 +3391,16 @@ exec_sentinel (proc, reason)
   restore_match_data ();
 
   Vdeactivate_mark = odeactivate;
+#if 0
   if (! EQ (Fcurrent_buffer (), obuffer)
       || ! EQ (current_buffer->keymap, okeymap))
-    record_asynch_buffer_change ();
+#endif
+    /* But do it only if the caller is actually going to read events.
+       Otherwise there's no need to make him wake up, and it could
+       cause trouble (for example it would make Fsit_for return).  */
+    if (waiting_for_user_input_p == -1)
+      record_asynch_buffer_change ();
 
-  if (waiting_for_user_input_p)
-    prepare_menu_bars ();
   unbind_to (count, Qnil);
 }
 
@@ -3386,7 +3413,6 @@ status_notify ()
   register Lisp_Object proc, buffer;
   Lisp_Object tail, msg;
   struct gcpro gcpro1, gcpro2;
-  Lisp_Object old_process_alist;
 
   tail = Qnil;
   msg = Qnil;
@@ -3396,97 +3422,95 @@ status_notify ()
      reference.  */
   GCPRO2 (tail, msg);
 
-  do
+  /* Set this now, so that if new processes are created by sentinels
+     that we run, we get called again to handle their status changes.  */
+  update_tick = process_tick;
+
+  for (tail = Vprocess_alist; !NILP (tail); tail = Fcdr (tail))
     {
-      old_process_alist = Vprocess_alist;
-      for (tail = Vprocess_alist; !NILP (tail); tail = Fcdr (tail))
+      Lisp_Object symbol;
+      register struct Lisp_Process *p;
+
+      proc = Fcdr (Fcar (tail));
+      p = XPROCESS (proc);
+
+      if (XINT (p->tick) != XINT (p->update_tick))
        {
-         Lisp_Object symbol;
-         register struct Lisp_Process *p;
+         XSETINT (p->update_tick, XINT (p->tick));
 
-         proc = Fcdr (Fcar (tail));
-         p = XPROCESS (proc);
+         /* If process is still active, read any output that remains.  */
+         if (XINT (p->infd) >= 0)
+           while (! EQ (p->filter, Qt)
+                  && read_process_output (proc, XINT (p->infd)) > 0);
 
-         if (XINT (p->tick) != XINT (p->update_tick))
-           {
-             XSETINT (p->update_tick, XINT (p->tick));
+         buffer = p->buffer;
 
-             /* If process is still active, read any output that remains.  */
-             if (XINT (p->infd) >= 0)
-               while (! EQ (p->filter, Qt)
-                      && read_process_output (proc, XINT (p->infd)) > 0);
+         /* Get the text to use for the message.  */
+         if (!NILP (p->raw_status_low))
+           update_status (p);
+         msg = status_message (p->status);
 
-             buffer = p->buffer;
+         /* If process is terminated, deactivate it or delete it.  */
+         symbol = p->status;
+         if (CONSP (p->status))
+           symbol = XCONS (p->status)->car;
 
-             /* Get the text to use for the message.  */
-             if (!NILP (p->raw_status_low))
-               update_status (p);
-             msg = status_message (p->status);
+         if (EQ (symbol, Qsignal) || EQ (symbol, Qexit)
+             || EQ (symbol, Qclosed))
+           {
+             if (delete_exited_processes)
+               remove_process (proc);
+             else
+               deactivate_process (proc);
+           }
 
-             /* If process is terminated, deactivate it or delete it.  */
-             symbol = p->status;
-             if (CONSP (p->status))
-               symbol = XCONS (p->status)->car;
+         /* Now output the message suitably.  */
+         if (!NILP (p->sentinel))
+           exec_sentinel (proc, msg);
+         /* Don't bother with a message in the buffer
+            when a process becomes runnable.  */
+         else if (!EQ (symbol, Qrun) && !NILP (buffer))
+           {
+             Lisp_Object ro, tem;
+             struct buffer *old = current_buffer;
+             int opoint;
 
-             if (EQ (symbol, Qsignal) || EQ (symbol, Qexit)
-                 || EQ (symbol, Qclosed))
-               {
-                 if (delete_exited_processes)
-                   remove_process (proc);
-                 else
-                   deactivate_process (proc);
-               }
+             ro = XBUFFER (buffer)->read_only;
 
-             /* Now output the message suitably.  */
-             if (!NILP (p->sentinel))
-               exec_sentinel (proc, msg);
-             /* Don't bother with a message in the buffer
-                when a process becomes runnable.  */
-             else if (!EQ (symbol, Qrun) && !NILP (buffer))
-               {
-                 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))
-                   continue;
-                 Fset_buffer (buffer);
-                 opoint = point;
-                 /* Insert new output into buffer
-                    at the current end-of-output marker,
-                    thus preserving logical ordering of input and output.  */
-                 if (XMARKER (p->mark)->buffer)
-                   SET_PT (marker_position (p->mark));
-                 else
-                   SET_PT (ZV);
-                 if (point <= opoint)
-                   opoint += XSTRING (msg)->size + XSTRING (p->name)->size + 10;
-
-                 tem = current_buffer->read_only;
-                 current_buffer->read_only = Qnil;
-                 insert_string ("\nProcess ");
-                 Finsert (1, &p->name);
-                 insert_string (" ");
-                 Finsert (1, &msg);
-                 current_buffer->read_only = tem;
-                 Fset_marker (p->mark, make_number (point), p->buffer);
-
-                 SET_PT (opoint);
-                 set_buffer_internal (old);
-               }
+             /* Avoid error if buffer is deleted
+                (probably that's why the process is dead, too) */
+             if (NILP (XBUFFER (buffer)->name))
+               continue;
+             Fset_buffer (buffer);
+             opoint = point;
+             /* Insert new output into buffer
+                at the current end-of-output marker,
+                thus preserving logical ordering of input and output.  */
+             if (XMARKER (p->mark)->buffer)
+               SET_PT (marker_position (p->mark));
+             else
+               SET_PT (ZV);
+             if (point <= opoint)
+               opoint += XSTRING (msg)->size + XSTRING (p->name)->size + 10;
+
+             tem = current_buffer->read_only;
+             current_buffer->read_only = Qnil;
+             insert_string ("\nProcess ");
+             Finsert (1, &p->name);
+             insert_string (" ");
+             Finsert (1, &msg);
+             current_buffer->read_only = tem;
+             Fset_marker (p->mark, make_number (point), p->buffer);
+
+             SET_PT (opoint);
+             set_buffer_internal (old);
            }
-       } /* end for */
-    } while (! EQ (old_process_alist, Vprocess_alist));
+       }
+    } /* end for */
 
   update_mode_lines++;  /* in case buffers use %s in mode-line-format */
   redisplay_preserve_echo_area ();
 
-  update_tick = process_tick;
-
   UNGCPRO;
 }
 \f
@@ -3536,7 +3560,7 @@ keyboard_bit_set (mask)
 {
   int fd;
 
-  for (fd = 0; fd < max_keyboard_desc; fd++)
+  for (fd = 0; fd <= max_keyboard_desc; fd++)
     if (FD_ISSET (fd, mask) && FD_ISSET (fd, &input_wait_mask)
        && !FD_ISSET (fd, &non_keyboard_wait_mask))
       return 1;
@@ -3661,6 +3685,7 @@ The value takes effect when `start-process' is called.");
 #include "lisp.h"
 #include "systime.h"
 #include "termopts.h"
+#include "sysselect.h"
 
 extern int frame_garbaged;
 
@@ -3716,9 +3741,6 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
     /* It's infinite.  */
     timeout_p = 0;
 
-  /* This must come before stop_polling.  */
-  prepare_menu_bars ();
-
   /* Turn off periodic alarms (in case they are in use)
      because the select emulator uses alarms.  */
   stop_polling ();
@@ -3756,7 +3778,8 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
       if (XINT (read_kbd) && detect_input_pending ())
        nfds = 0;
       else
-       nfds = select (1, &waitchannels, 0, 0, timeout_p);
+       nfds = select (1, &waitchannels, (SELECT_TYPE *)0, (SELECT_TYPE *)0,
+                      timeout_p);
 
       /* Make C-g and alarm signals set flags again */
       clear_waiting_for_input ();