use dynwind_begin and dynwind_end
[bpt/emacs.git] / src / callproc.c
index a2c52e5..2f6030f 100644 (file)
@@ -82,12 +82,7 @@ static Lisp_Object Vtemp_file_name_pattern;
 /* If nonzero, a process-ID that has not been reaped.  */
 static pid_t synch_process_pid;
 
-/* If a string, the name of a temp file that has not been removed.  */
-#ifdef MSDOS
 static Lisp_Object synch_process_tempfile;
-#else
-# define synch_process_tempfile make_number (0)
-#endif
 
 /* Indexes of file descriptors that need closing on call_process_kill.  */
 enum
@@ -103,31 +98,8 @@ enum
     CALLPROC_FDS
   };
 
-static Lisp_Object call_process (ptrdiff_t, Lisp_Object *, int, ptrdiff_t);
+static Lisp_Object call_process (ptrdiff_t, Lisp_Object *, int *, Lisp_Object *);
 \f
-
-#ifndef MSDOS
-/* Block SIGCHLD.  */
-
-void
-block_child_signal (sigset_t *oldset)
-{
-  sigset_t blocked;
-  sigemptyset (&blocked);
-  sigaddset (&blocked, SIGCHLD);
-  pthread_sigmask (SIG_BLOCK, &blocked, oldset);
-}
-
-/* Unblock SIGCHLD.  */
-
-void
-unblock_child_signal (sigset_t const *oldset)
-{
-  pthread_sigmask (SIG_SETMASK, oldset, 0);
-}
-
-#endif /* !MSDOS */
-
 /* Return the current buffer's working directory, or the home
    directory if it's unreachable, as a string suitable for a system call.
    Signal an error if the result would not be an accessible directory.  */
@@ -184,9 +156,11 @@ record_kill_process (struct Lisp_Process *p, Lisp_Object tempfile)
 /* Clean up files, file descriptors and processes created by Fcall_process.  */
 
 static void
-delete_temp_file (Lisp_Object name)
+delete_temp_file_ptr (Lisp_Object *name_ptr)
 {
-  unlink (SSDATA (name));
+  Lisp_Object name = *name_ptr;
+  if (! NILP (name))
+    unlink (SSDATA (name));
 }
 
 static void
@@ -207,7 +181,7 @@ call_process_kill (void *ptr)
       synch_process_pid = 0;
     }
   else if (STRINGP (synch_process_tempfile))
-    delete_temp_file (synch_process_tempfile);
+    delete_temp_file_ptr (&synch_process_tempfile);
 }
 
 /* Clean up when exiting Fcall_process: restore the buffer, and
@@ -287,9 +261,9 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS)  *
   filefd = emacs_open (SSDATA (encoded_infile), O_RDONLY, 0);
   if (filefd < 0)
     report_file_error ("Opening process input file", infile);
-  record_unwind_protect_int (close_file_unwind, filefd);
+  record_unwind_protect_ptr (close_file_ptr_unwind, &filefd);
   UNGCPRO;
-  return unbind_to (count, call_process (nargs, args, filefd, -1));
+  return unbind_to (count, call_process (nargs, args, &filefd, NULL));
 }
 
 /* Like Fcall_process (NARGS, ARGS), except use FILEFD as the input file.
@@ -301,8 +275,7 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS)  *
    At entry, the specpdl stack top entry must be close_file_unwind (FILEFD).  */
 
 static Lisp_Object
-call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
-             ptrdiff_t tempfile_index)
+call_process (ptrdiff_t nargs, Lisp_Object *args, int *filefd, Lisp_Object *tempfile_ptr)
 {
   Lisp_Object buffer, current_dir, path;
   bool display_p;
@@ -310,7 +283,6 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
   int callproc_fd[CALLPROC_FDS];
   int status;
   ptrdiff_t i;
-  ptrdiff_t count = SPECPDL_INDEX ();
   USE_SAFE_ALLOCA;
 
   char **new_argv;
@@ -333,6 +305,8 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
   Lisp_Object coding_systems;
   bool discard_output;
 
+  dynwind_begin ();
+
   if (synch_process_pid)
     error ("call-process invoked recursively");
 
@@ -593,12 +567,12 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
 #ifdef MSDOS /* MW, July 1993 */
   /* Note that on MSDOS `child_setup' actually returns the child process
      exit status, not its PID, so assign it to status below.  */
-  pid = child_setup (filefd, fd_output, fd_error, new_argv, 0, current_dir);
+  pid = child_setup (*filefd, fd_output, fd_error, new_argv, 0, current_dir);
 
   if (pid < 0)
     {
       child_errno = errno;
-      unbind_to (count, Qnil);
+      dynwind_end ();
       synchronize_system_messages_locale ();
       return
        code_convert_string_norecord (build_string (strerror (child_errno)),
@@ -612,8 +586,8 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
        emacs_close (callproc_fd[i]);
        callproc_fd[i] = -1;
       }
-  emacs_close (filefd);
-  clear_unwind_protect (count - 1);
+  emacs_close (*filefd);
+  *filefd = -1;
 
   if (tempfile)
     {
@@ -642,7 +616,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
   block_child_signal (&oldset);
 
 #ifdef WINDOWSNT
-  pid = child_setup (filefd, fd_output, fd_error, new_argv, 0, current_dir);
+  pid = child_setup (*filefd, fd_output, fd_error, new_argv, 0, current_dir);
 #else  /* not WINDOWSNT */
 
   /* vfork, and prevent local vars from being clobbered by the vfork.  */
@@ -651,11 +625,8 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
     Lisp_Object volatile coding_systems_volatile = coding_systems;
     Lisp_Object volatile current_dir_volatile = current_dir;
     bool volatile display_p_volatile = display_p;
-    bool volatile sa_must_free_volatile = sa_must_free;
     int volatile fd_error_volatile = fd_error;
-    int volatile filefd_volatile = filefd;
-    ptrdiff_t volatile count_volatile = count;
-    ptrdiff_t volatile sa_count_volatile = sa_count;
+    int *volatile filefd_volatile = filefd;
     char **volatile new_argv_volatile = new_argv;
     int volatile callproc_fd_volatile[CALLPROC_FDS];
     for (i = 0; i < CALLPROC_FDS; i++)
@@ -667,11 +638,8 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
     coding_systems = coding_systems_volatile;
     current_dir = current_dir_volatile;
     display_p = display_p_volatile;
-    sa_must_free = sa_must_free_volatile;
     fd_error = fd_error_volatile;
     filefd = filefd_volatile;
-    count = count_volatile;
-    sa_count = sa_count_volatile;
     new_argv = new_argv_volatile;
 
     for (i = 0; i < CALLPROC_FDS; i++)
@@ -692,7 +660,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
       signal (SIGPROF, SIG_DFL);
 #endif
 
-      child_setup (filefd, fd_output, fd_error, new_argv, 0, current_dir);
+      child_setup (*filefd, fd_output, fd_error, new_argv, 0, current_dir);
     }
 
 #endif /* not WINDOWSNT */
@@ -705,14 +673,15 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
 
       if (INTEGERP (buffer))
        {
-         if (tempfile_index < 0)
-           record_deleted_pid (pid, Qnil);
-         else
-           {
-             eassert (1 < nargs);
-             record_deleted_pid (pid, args[1]);
-             clear_unwind_protect (tempfile_index);
-           }
+          if (tempfile_ptr)
+            {
+              record_deleted_pid (pid, *tempfile_ptr);
+              *tempfile_ptr = Qnil;
+            }
+          else
+            {
+              record_deleted_pid (pid, Qnil);
+            }
          synch_process_pid = 0;
        }
     }
@@ -731,13 +700,16 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
        emacs_close (callproc_fd[i]);
        callproc_fd[i] = -1;
       }
-  emacs_close (filefd);
-  clear_unwind_protect (count - 1);
+  emacs_close (*filefd);
+  *filefd = -1;
 
 #endif /* not MSDOS */
 
   if (INTEGERP (buffer))
-    return unbind_to (count, Qnil);
+    {
+      dynwind_end ();
+      return Qnil;
+    }
 
   if (BUFFERP (buffer))
     Fset_buffer (buffer);
@@ -828,15 +800,18 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
          /* Now NREAD is the total amount of data in the buffer.  */
          immediate_quit = 0;
 
-         if (NILP (BVAR (current_buffer, enable_multibyte_characters))
-             && ! CODING_MAY_REQUIRE_DECODING (&process_coding))
+         if (!nread)
+           ;
+         else if (NILP (BVAR (current_buffer, enable_multibyte_characters))
+                  && ! CODING_MAY_REQUIRE_DECODING (&process_coding))
            insert_1_both (buf, nread, nread, 0, 1, 0);
          else
            {                   /* We have to decode the input.  */
              Lisp_Object curbuf;
-             ptrdiff_t count1 = SPECPDL_INDEX ();
 
+              dynwind_begin ();
              XSETBUFFER (curbuf, current_buffer);
+             /* FIXME: Call signal_after_change!  */
              prepare_to_modify_buffer (PT, PT, NULL);
              /* We cannot allow after-change-functions be run
                 during decoding, because that might modify the
@@ -846,7 +821,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
              specbind (Qinhibit_modification_hooks, Qt);
              decode_coding_c_string (&process_coding,
                                      (unsigned char *) buf, nread, curbuf);
-             unbind_to (count1, Qnil);
+              dynwind_end ();
              if (display_on_the_fly
                  && CODING_REQUIRE_DETECTION (&saved_coding)
                  && ! CODING_REQUIRE_DETECTION (&process_coding))
@@ -921,7 +896,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
   synch_process_pid = 0;
 
   SAFE_FREE ();
-  unbind_to (count, Qnil);
+  dynwind_end ();
 
   if (WIFSIGNALED (status))
     {
@@ -948,9 +923,9 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
    Unwind-protect the file, so that the file descriptor will be closed
    and the file removed when the caller unwinds the specpdl stack.  */
 
-static int
+static void
 create_temp_file (ptrdiff_t nargs, Lisp_Object *args,
-                 Lisp_Object *filename_string_ptr)
+                 Lisp_Object *filename_string_ptr, int *fdp)
 {
   int fd;
   struct gcpro gcpro1;
@@ -1000,14 +975,14 @@ create_temp_file (ptrdiff_t nargs, Lisp_Object *args,
     GCPRO1 (filename_string);
     tempfile = SSDATA (filename_string);
 
-    count = SPECPDL_INDEX ();
-    record_unwind_protect_nothing ();
     fd = mkostemp (tempfile, O_CLOEXEC);
     if (fd < 0)
       report_file_error ("Failed to open temporary file using pattern",
                         pattern);
-    set_unwind_protect (count, delete_temp_file, filename_string);
-    record_unwind_protect_int (close_file_unwind, fd);
+    *fdp = fd;
+    *filename_string_ptr = filename_string;
+    record_unwind_protect (delete_temp_file_ptr, filename_string_ptr);
+    record_unwind_protect_ptr (close_file_ptr_unwind, fdp);
   }
 
   start = args[0];
@@ -1049,9 +1024,7 @@ create_temp_file (ptrdiff_t nargs, Lisp_Object *args,
   /* Note that Fcall_process takes care of binding
      coding-system-for-read.  */
 
-  *filename_string_ptr = filename_string;
   UNGCPRO;
-  return fd;
 }
 
 DEFUN ("call-process-region", Fcall_process_region, Scall_process_region,
@@ -1102,14 +1075,14 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
     }
 
   if (!empty_input)
-    fd = create_temp_file (nargs, args, &infile);
+    create_temp_file (nargs, args, &infile, &fd);
   else
     {
       infile = Qnil;
       fd = emacs_open (NULL_DEVICE, O_RDONLY, 0);
       if (fd < 0)
        report_file_error ("Opening null device", Qnil);
-      record_unwind_protect_int (close_file_unwind, fd);
+      record_unwind_protect_ptr (close_file_ptr_unwind, &fd);
     }
 
   GCPRO1 (infile);
@@ -1129,7 +1102,7 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
     }
   args[1] = infile;
 
-  val = call_process (nargs, args, fd, empty_input ? -1 : count);
+  val = call_process (nargs, args, &fd, &infile);
   RETURN_UNGCPRO (unbind_to (count, val));
 }
 \f
@@ -1680,6 +1653,8 @@ set_initial_environment (void)
 void
 syms_of_callproc (void)
 {
+#include "callproc.x"
+
 #ifndef DOS_NT
   Vtemp_file_name_pattern = build_string ("emacsXXXXXX");
 #else  /* DOS_NT */
@@ -1687,10 +1662,8 @@ syms_of_callproc (void)
 #endif
   staticpro (&Vtemp_file_name_pattern);
 
-#ifdef MSDOS
   synch_process_tempfile = make_number (0);
   staticpro (&synch_process_tempfile);
-#endif
 
   DEFVAR_LISP ("shell-file-name", Vshell_file_name,
               doc: /* File name to load inferior shells from.
@@ -1767,8 +1740,4 @@ use.
 
 See `setenv' and `getenv'.  */);
   Vprocess_environment = Qnil;
-
-  defsubr (&Scall_process);
-  defsubr (&Sgetenv_internal);
-  defsubr (&Scall_process_region);
 }