* src/callproc.c (Fcall_process): Restore a line that was accidentally commented...
[bpt/emacs.git] / src / callproc.c
index c2c301e..d3ca7eb 100644 (file)
@@ -1,5 +1,5 @@
 /* Synchronous subprocess invocation for GNU Emacs.
-   Copyright (C) 1985-1988, 1993-1995, 1999-2011
+   Copyright (C) 1985-1988, 1993-1995, 1999-2012
                 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -29,6 +29,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <sys/file.h>
 #include <fcntl.h>
 
+#include "lisp.h"
+
 #ifdef WINDOWSNT
 #define NOMINMAX
 #include <windows.h>
@@ -41,7 +43,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <sys/param.h>
 #endif /* MSDOS */
 
-#include "lisp.h"
 #include "commands.h"
 #include "buffer.h"
 #include "character.h"
@@ -113,6 +114,7 @@ call_process_cleanup (Lisp_Object arg)
   Lisp_Object fdpid = Fcdr (arg);
 #if defined (MSDOS)
   Lisp_Object file;
+  int fd;
 #else
   int pid;
 #endif
@@ -121,9 +123,13 @@ call_process_cleanup (Lisp_Object arg)
 
 #if defined (MSDOS)
   /* for MSDOS fdpid is really (fd . tempfile)  */
+  fd = XFASTINT (Fcar (fdpid));
   file = Fcdr (fdpid);
-  emacs_close (XFASTINT (Fcar (fdpid)));
-  if (strcmp (SDATA (file), NULL_DEVICE) != 0)
+  /* FD is -1 and FILE is "" when we didn't actually create a
+     temporary file in call-process.  */
+  if (fd >= 0)
+    emacs_close (fd);
+  if (!(strcmp (SDATA (file), NULL_DEVICE) == 0 || SREF (file, 0) == '\0'))
     unlink (SDATA (file));
 #else /* not MSDOS */
   pid = XFASTINT (Fcdr (fdpid));
@@ -158,7 +164,8 @@ The remaining arguments are optional.
 The program's input comes from file INFILE (nil means `/dev/null').
 Insert output in BUFFER before point; t means current buffer; nil for BUFFER
  means discard it; 0 means discard and don't wait; and `(:file FILE)', where
- FILE is a file name string, means that it should be written to that file.
+ FILE is a file name string, means that it should be written to that file
+ \(if the file already exists it is overwritten).
 BUFFER can also have the form (REAL-BUFFER STDERR-FILE); in that case,
 REAL-BUFFER says what to do with standard output, as above,
 while STDERR-FILE says what to do with standard error in the child.
@@ -178,7 +185,7 @@ and returns a numeric exit status or a signal description string.
 If you quit, the process is killed with SIGINT, or SIGKILL if you quit again.
 
 usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS)  */)
-  (size_t nargs, register Lisp_Object *args)
+  (ptrdiff_t nargs, Lisp_Object *args)
 {
   Lisp_Object infile, buffer, current_dir, path;
   volatile int display_p_volatile;
@@ -198,7 +205,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS)  */)
   Lisp_Object error_file;
   Lisp_Object output_file = Qnil;
 #ifdef MSDOS   /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
-  char *outf, *tempfile;
+  char *outf, *tempfile = NULL;
   int outfilefd;
 #endif
   int fd_output = -1;
@@ -225,7 +232,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS)  */)
   /* Decide the coding-system for giving arguments.  */
   {
     Lisp_Object val, *args2;
-    size_t i;
+    ptrdiff_t i;
 
     /* If arguments are supplied, we may have to encode them.  */
     if (nargs >= 5)
@@ -246,7 +253,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS)  */)
          val = Qraw_text;
        else
          {
-           SAFE_ALLOCA (args2, Lisp_Object *, (nargs + 1) * sizeof *args2);
+           SAFE_NALLOCA (args2, 1, nargs + 1);
            args2[0] = Qcall_process;
            for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
            coding_systems = Ffind_operation_coding_system (nargs + 1, args2);
@@ -416,7 +423,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS)  */)
               (nargs > 4 ? nargs - 2 : 2) * sizeof *new_argv);
   if (nargs > 4)
     {
-      register size_t i;
+      ptrdiff_t i;
       struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
 
       GCPRO5 (infile, buffer, current_dir, path, error_file);
@@ -438,22 +445,23 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS)  */)
   new_argv[0] = SDATA (path);
 
 #ifdef MSDOS /* MW, July 1993 */
-  if ((outf = egetenv ("TMPDIR")))
-    strcpy (tempfile = alloca (strlen (outf) + 20), outf);
-  else
-    {
-      tempfile = alloca (20);
-      *tempfile = '\0';
-    }
-  dostounix_filename (tempfile);
-  if (*tempfile == '\0' || tempfile[strlen (tempfile) - 1] != '/')
-    strcat (tempfile, "/");
-  strcat (tempfile, "detmp.XXX");
-  mktemp (tempfile);
 
-  /* If we're redirecting STDOUT to a file, this is already opened. */
+  /* If we're redirecting STDOUT to a file, that file is already open
+     on fd_output.  */
   if (fd_output < 0)
     {
+      if ((outf = egetenv ("TMPDIR")))
+       strcpy (tempfile = alloca (strlen (outf) + 20), outf);
+      else
+       {
+         tempfile = alloca (20);
+         *tempfile = '\0';
+       }
+      dostounix_filename (tempfile);
+      if (*tempfile == '\0' || tempfile[strlen (tempfile) - 1] != '/')
+       strcat (tempfile, "/");
+      strcat (tempfile, "detmp.XXX");
+      mktemp (tempfile);
       outfilefd = creat (tempfile, S_IREAD | S_IWRITE);
       if (outfilefd < 0) {
        emacs_close (filefd);
@@ -560,15 +568,21 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS)  */)
     if (fd_error != outfilefd)
       emacs_close (fd_error);
     fd1 = -1; /* No harm in closing that one!  */
-    /* Since CRLF is converted to LF within `decode_coding', we can
-       always open a file with binary mode.  */
-    fd[0] = emacs_open (tempfile, O_RDONLY | O_BINARY, 0);
-    if (fd[0] < 0)
+    if (tempfile)
       {
-       unlink (tempfile);
-       emacs_close (filefd);
-       report_file_error ("Cannot re-open temporary file", Qnil);
+       /* Since CRLF is converted to LF within `decode_coding', we
+          can always open a file with binary mode.  */
+       fd[0] = emacs_open (tempfile, O_RDONLY | O_BINARY, 0);
+       if (fd[0] < 0)
+         {
+           unlink (tempfile);
+           emacs_close (filefd);
+           report_file_error ("Cannot re-open temporary file",
+                              Fcons (build_string (tempfile), Qnil));
+         }
       }
+    else
+      fd[0] = -1; /* We are not going to read from tempfile.   */
 #else /* not MSDOS */
 #ifdef WINDOWSNT
     pid = child_setup (filefd, fd1, fd_error, (char **) new_argv,
@@ -583,13 +597,17 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS)  */)
     sigemptyset (&blocked);
     sigaddset (&blocked, SIGPIPE);
     sigaction (SIGPIPE, 0, &sigpipe_action);
-    sigprocmask (SIG_BLOCK, &blocked, &procmask);
+    pthread_sigmask (SIG_BLOCK, &blocked, &procmask);
 #endif
 
     BLOCK_INPUT;
 
     /* vfork, and prevent local vars from being clobbered by the vfork.  */
-   {
+    {
+      Lisp_Object volatile buffer_volatile = buffer;
+      Lisp_Object volatile coding_systems_volatile = coding_systems;
+      Lisp_Object volatile current_dir_volatile = current_dir;
+      int volatile fd1_volatile = fd1;
       int volatile fd_error_volatile = fd_error;
       int volatile fd_output_volatile = fd_output;
       int volatile output_to_buffer_volatile = output_to_buffer;
@@ -597,6 +615,10 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS)  */)
 
       pid = vfork ();
 
+      buffer = buffer_volatile;
+      coding_systems = coding_systems_volatile;
+      current_dir = current_dir_volatile;
+      fd1 = fd1_volatile;
       fd_error = fd_error_volatile;
       fd_output = fd_output_volatile;
       output_to_buffer = output_to_buffer_volatile;
@@ -618,9 +640,9 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS)  */)
 
        /* GConf causes us to ignore SIGPIPE, make sure it is restored
           in the child.  */
-       //signal (SIGPIPE, SIG_DFL);
+       signal (SIGPIPE, SIG_DFL);
 #ifdef HAVE_WORKING_VFORK
-       sigprocmask (SIG_SETMASK, &procmask, 0);
+       pthread_sigmask (SIG_SETMASK, &procmask, 0);
 #endif
 
        child_setup (filefd, fd1, fd_error, (char **) new_argv,
@@ -632,7 +654,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS)  */)
 #ifdef HAVE_WORKING_VFORK
     /* Restore the signal state.  */
     sigaction (SIGPIPE, &sigpipe_action, 0);
-    sigprocmask (SIG_SETMASK, &procmask, 0);
+    pthread_sigmask (SIG_SETMASK, &procmask, 0);
 #endif
 
 #endif /* not WINDOWSNT */
@@ -670,12 +692,12 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS)  */)
   /* Enable sending signal if user quits below.  */
   call_process_exited = 0;
 
-#if defined(MSDOS)
+#if defined (MSDOS)
   /* MSDOS needs different cleanup information.  */
   record_unwind_protect (call_process_cleanup,
                         Fcons (Fcurrent_buffer (),
                                Fcons (make_number (fd[0]),
-                                      build_string (tempfile))));
+                                      build_string (tempfile ? tempfile : ""))));
 #else
   record_unwind_protect (call_process_cleanup,
                         Fcons (Fcurrent_buffer (),
@@ -691,6 +713,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS)  */)
       /* If BUFFER is nil, we must read process output once and then
         discard it, so setup coding system but with nil.  */
       setup_coding_system (Qnil, &process_coding);
+      process_coding.dst_multibyte = 0;
     }
   else
     {
@@ -703,9 +726,9 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS)  */)
        {
          if (EQ (coding_systems, Qt))
            {
-             size_t i;
+             ptrdiff_t i;
 
-             SAFE_ALLOCA (args2, Lisp_Object *, (nargs + 1) * sizeof *args2);
+             SAFE_NALLOCA (args2, 1, nargs + 1);
              args2[0] = Qcall_process;
              for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
              coding_systems
@@ -726,7 +749,10 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS)  */)
          && !NILP (val))
        val = raw_text_coding_system (val);
       setup_coding_system (val, &process_coding);
+      process_coding.dst_multibyte
+       = ! NILP (BVAR (current_buffer, enable_multibyte_characters));
     }
+  process_coding.src_multibyte = 0;
 
   immediate_quit = 1;
   QUIT;
@@ -915,7 +941,7 @@ Delete the text if fourth arg DELETE is non-nil.
 Insert output in BUFFER before point; t means current buffer; nil for
  BUFFER means discard it; 0 means discard and don't wait; and `(:file
  FILE)', where FILE is a file name string, means that it should be
- written to that file.
+ written to that file (if the file already exists it is overwritten).
 BUFFER can also have the form (REAL-BUFFER STDERR-FILE); in that case,
 REAL-BUFFER says what to do with standard output, as above,
 while STDERR-FILE says what to do with standard error in the child.
@@ -931,7 +957,7 @@ and returns a numeric exit status or a signal description string.
 If you quit, the process is killed with SIGINT, or SIGKILL if you quit again.
 
 usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &rest ARGS)  */)
-  (size_t nargs, register Lisp_Object *args)
+  (ptrdiff_t nargs, Lisp_Object *args)
 {
   struct gcpro gcpro1;
   Lisp_Object filename_string;
@@ -940,7 +966,7 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
   /* Qt denotes we have not yet called Ffind_operation_coding_system.  */
   Lisp_Object coding_systems;
   Lisp_Object val, *args2;
-  size_t i;
+  ptrdiff_t i;
   char *tempfile;
   Lisp_Object tmpdir, pattern;
 
@@ -1003,7 +1029,7 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
   else
     {
       USE_SAFE_ALLOCA;
-      SAFE_ALLOCA (args2, Lisp_Object *, (nargs + 1) * sizeof *args2);
+      SAFE_NALLOCA (args2, 1, nargs + 1);
       args2[0] = Qcall_process_region;
       for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
       coding_systems = Ffind_operation_coding_system (nargs + 1, args2);
@@ -1132,7 +1158,7 @@ child_setup (int in, int out, int err, register char **new_argv, int set_pgrp, L
      cleaned up in the usual way. */
   {
     register char *temp;
-    register int i;
+    size_t i; /* size_t, because ptrdiff_t might overflow here!  */
 
     i = SBYTES (current_dir);
 #ifdef MSDOS
@@ -1217,8 +1243,7 @@ child_setup (int in, int out, int err, register char **new_argv, int set_pgrp, L
 
     if (STRINGP (display))
       {
-       int vlen = strlen ("DISPLAY=") + strlen (SSDATA (display)) + 1;
-       char *vdata = (char *) alloca (vlen);
+       char *vdata = (char *) alloca (sizeof "DISPLAY=" + SBYTES (display));
        strcpy (vdata, "DISPLAY=");
        strcat (vdata, SSDATA (display));
        new_env = add_env (env, new_env, vdata);
@@ -1295,7 +1320,7 @@ child_setup (int in, int out, int err, register char **new_argv, int set_pgrp, L
   if (err != in && err != out)
     emacs_close (err);
 
-#if defined(USG)
+#if defined (USG)
 #ifndef SETPGRP_RELEASES_CTTY
   setpgrp ();                  /* No arguments but equivalent in this case */
 #endif
@@ -1365,8 +1390,8 @@ relocate_fd (int fd, int minfd)
 #endif /* not WINDOWSNT */
 
 static int
-getenv_internal_1 (const char *var, int varlen, char **value, int *valuelen,
-                  Lisp_Object env)
+getenv_internal_1 (const char *var, ptrdiff_t varlen, char **value,
+                  ptrdiff_t *valuelen, Lisp_Object env)
 {
   for (; CONSP (env); env = XCDR (env))
     {
@@ -1400,8 +1425,8 @@ getenv_internal_1 (const char *var, int varlen, char **value, int *valuelen,
 }
 
 static int
-getenv_internal (const char *var, int varlen, char **value, int *valuelen,
-                Lisp_Object frame)
+getenv_internal (const char *var, ptrdiff_t varlen, char **value,
+                ptrdiff_t *valuelen, Lisp_Object frame)
 {
   /* Try to find VAR in Vprocess_environment first.  */
   if (getenv_internal_1 (var, varlen, value, valuelen,
@@ -1441,7 +1466,7 @@ If optional parameter ENV is a list, then search this list instead of
   (Lisp_Object variable, Lisp_Object env)
 {
   char *value;
-  int valuelen;
+  ptrdiff_t valuelen;
 
   CHECK_STRING (variable);
   if (CONSP (env))
@@ -1465,7 +1490,7 @@ char *
 egetenv (const char *var)
 {
   char *value;
-  int valuelen;
+  ptrdiff_t valuelen;
 
   if (getenv_internal (var, strlen (var), &value, &valuelen, Qnil))
     return value;
@@ -1590,20 +1615,13 @@ init_callproc (void)
 void
 set_initial_environment (void)
 {
-  register char **envp;
-#ifdef CANNOT_DUMP
-  Vprocess_environment = Qnil;
-#else
-  if (initialized)
-#endif
-    {
-      for (envp = environ; *envp; envp++)
-       Vprocess_environment = Fcons (build_string (*envp),
-                                     Vprocess_environment);
-      /* Ideally, the `copy' shouldn't be necessary, but it seems it's frequent
-        to use `delete' and friends on process-environment.  */
-      Vinitial_environment = Fcopy_sequence (Vprocess_environment);
-    }
+  char **envp;
+  for (envp = environ; *envp; envp++)
+    Vprocess_environment = Fcons (build_string (*envp),
+                                 Vprocess_environment);
+  /* Ideally, the `copy' shouldn't be necessary, but it seems it's frequent
+     to use `delete' and friends on process-environment.  */
+  Vinitial_environment = Fcopy_sequence (Vprocess_environment);
 }
 
 void