Merge from emacs-24; up to 2012-12-15T12:19:04Z!juri@jurta.org
[bpt/emacs.git] / src / callproc.c
index 70e349d..cb11ee0 100644 (file)
@@ -402,10 +402,8 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS)  */)
 
   filefd = emacs_open (SSDATA (infile), O_RDONLY, 0);
   if (filefd < 0)
-    {
-      infile = DECODE_FILE (infile);
-      report_file_error ("Opening process input file", Fcons (infile, Qnil));
-    }
+    report_file_error ("Opening process input file",
+                      Fcons (DECODE_FILE (infile), Qnil));
 
   if (STRINGP (output_file))
     {
@@ -447,28 +445,34 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS)  */)
     path = Fsubstring (path, make_number (2), Qnil);
 
   new_argv = SAFE_ALLOCA ((nargs > 4 ? nargs - 2 : 2) * sizeof *new_argv);
-  if (nargs > 4)
-    {
-      ptrdiff_t i;
-      struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
 
-      GCPRO5 (infile, buffer, current_dir, path, error_file);
-      argument_coding.dst_multibyte = 0;
-      for (i = 4; i < nargs; i++)
-       {
-         argument_coding.src_multibyte = STRING_MULTIBYTE (args[i]);
-         if (CODING_REQUIRE_ENCODING (&argument_coding))
-           /* We must encode this argument.  */
-           args[i] = encode_coding_string (&argument_coding, args[i], 1);
-       }
-      UNGCPRO;
-      for (i = 4; i < nargs; i++)
-       new_argv[i - 3] = SSDATA (args[i]);
-      new_argv[i - 3] = 0;
-    }
-  else
-    new_argv[1] = 0;
-  new_argv[0] = SSDATA (path);
+  {
+    struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
+
+    GCPRO5 (infile, buffer, current_dir, path, error_file);
+    if (nargs > 4)
+      {
+       ptrdiff_t i;
+
+       argument_coding.dst_multibyte = 0;
+       for (i = 4; i < nargs; i++)
+         {
+           argument_coding.src_multibyte = STRING_MULTIBYTE (args[i]);
+           if (CODING_REQUIRE_ENCODING (&argument_coding))
+             /* We must encode this argument.  */
+             args[i] = encode_coding_string (&argument_coding, args[i], 1);
+         }
+       for (i = 4; i < nargs; i++)
+         new_argv[i - 3] = SSDATA (args[i]);
+       new_argv[i - 3] = 0;
+      }
+    else
+      new_argv[1] = 0;
+    if (STRING_MULTIBYTE (path))
+      path = ENCODE_FILE (path);
+    new_argv[0] = SSDATA (path);
+    UNGCPRO;
+  }
 
 #ifdef MSDOS /* MW, July 1993 */
 
@@ -483,7 +487,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS)  */)
          tempfile = alloca (20);
          *tempfile = '\0';
        }
-      dostounix_filename (tempfile);
+      dostounix_filename (tempfile, 0);
       if (*tempfile == '\0' || tempfile[strlen (tempfile) - 1] != '/')
        strcat (tempfile, "/");
       strcat (tempfile, "detmp.XXX");
@@ -612,6 +616,15 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS)  */)
 
 #ifdef WINDOWSNT
     pid = child_setup (filefd, fd1, fd_error, new_argv, 0, current_dir);
+    /* We need to record the input file of this child, for when we are
+       called from call-process-region to create an async subprocess.
+       That's because call-process-region's unwind procedure will
+       attempt to delete the temporary input file, which will fail
+       because that file is still in use.  Recording it with the child
+       will allow us to delete the file when the subprocess exits.
+       The second part of this is in delete_temp_file, q.v.  */
+    if (pid > 0 && INTEGERP (buffer) && nargs >= 2 && !NILP (args[1]))
+      record_infile (pid, xstrdup (SSDATA (infile)));
 #else  /* not WINDOWSNT */
 
     /* vfork, and prevent local vars from being clobbered by the vfork.  */
@@ -924,7 +937,21 @@ delete_temp_file (Lisp_Object name)
   /* Suppress jka-compr handling, etc.  */
   ptrdiff_t count = SPECPDL_INDEX ();
   specbind (intern ("file-name-handler-alist"), Qnil);
+#ifdef WINDOWSNT
+  /* If this is called when the subprocess didn't exit yet, the
+     attempt to delete its input file will fail.  In that case, we
+     schedule the file for deletion when the subprocess exits.  This
+     is the 2nd part of handling this situation; see the call to
+     record_infile in call-process above, for the first part.  */
+  if (!internal_delete_file (name))
+    {
+      Lisp_Object encoded_file = ENCODE_FILE (name);
+
+      record_pending_deletion (SSDATA (encoded_file));
+    }
+#else
   internal_delete_file (name);
+#endif
   unbind_to (count, Qnil);
   return Qnil;
 }
@@ -989,8 +1016,26 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
   {
     USE_SAFE_ALLOCA;
     Lisp_Object pattern = Fexpand_file_name (Vtemp_file_name_pattern, tmpdir);
-    Lisp_Object encoded_tem = ENCODE_FILE (pattern);
-    char *tempfile = SAFE_ALLOCA (SBYTES (encoded_tem) + 1);
+    Lisp_Object encoded_tem;
+    char *tempfile;
+
+#ifdef WINDOWSNT
+    /* Cannot use the result of Fexpand_file_name, because it
+       downcases the XXXXXX part of the pattern, and mktemp then
+       doesn't recognize it.  */
+    if (!NILP (Vw32_downcase_file_names))
+      {
+       Lisp_Object dirname = Ffile_name_directory (pattern);
+
+       if (NILP (dirname))
+         pattern = Vtemp_file_name_pattern;
+       else
+         pattern = concat2 (dirname, Vtemp_file_name_pattern);
+      }
+#endif
+
+    encoded_tem = ENCODE_FILE (pattern);
+    tempfile = SAFE_ALLOCA (SBYTES (encoded_tem) + 1);
     memcpy (tempfile, SDATA (encoded_tem), SBYTES (encoded_tem) + 1);
     coding_systems = Qt;
 
@@ -1274,7 +1319,7 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
 #ifdef WINDOWSNT
   prepare_standard_handles (in, out, err, handles);
   set_process_dir (SDATA (current_dir));
-  /* Spawn the child.  (See ntproc.c:Spawnve).  */
+  /* Spawn the child.  (See w32proc.c:sys_spawnve).  */
   cpid = spawnve (_P_NOWAIT, new_argv[0], new_argv, env);
   reset_standard_handles (in, out, err, handles);
   if (cpid == -1)