]> code.delx.au - gnu-emacs/blobdiff - src/callproc.c
Fix the MS-Windows build broken by SAFE_ALLOCA changes.
[gnu-emacs] / src / callproc.c
index 2147c173655eb5067ebd259451603b5f734f1da8..271743021b68b7f5661d290969d6cd34c8e9594f 100644 (file)
@@ -105,25 +105,6 @@ enum
 
 static Lisp_Object call_process (ptrdiff_t, Lisp_Object *, int, ptrdiff_t);
 \f
-/* 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);
-}
-
 /* 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.  */
@@ -148,7 +129,7 @@ encode_current_directory (void)
 
   if (STRING_MULTIBYTE (dir))
     dir = ENCODE_FILE (dir);
-  if (! file_accessible_directory_p (SSDATA (dir)))
+  if (! file_accessible_directory_p (dir))
     report_file_error ("Setting current directory",
                       BVAR (current_buffer, directory));
 
@@ -162,6 +143,7 @@ encode_current_directory (void)
 void
 record_kill_process (struct Lisp_Process *p, Lisp_Object tempfile)
 {
+#ifndef MSDOS
   sigset_t oldset;
   block_child_signal (&oldset);
 
@@ -173,6 +155,7 @@ record_kill_process (struct Lisp_Process *p, Lisp_Object tempfile)
     }
 
   unblock_child_signal (&oldset);
+#endif /* !MSDOS */
 }
 
 /* Clean up files, file descriptors and processes created by Fcall_process.  */
@@ -212,6 +195,7 @@ call_process_cleanup (Lisp_Object buffer)
 {
   Fset_buffer (buffer);
 
+#ifndef MSDOS
   if (synch_process_pid)
     {
       kill (-synch_process_pid, SIGINT);
@@ -223,6 +207,7 @@ call_process_cleanup (Lisp_Object buffer)
       immediate_quit = 0;
       message1 ("Waiting for process to die...done");
     }
+#endif /* !MSDOS */
 }
 
 #ifdef DOS_NT
@@ -481,7 +466,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
       && SREF (path, 1) == ':')
     path = Fsubstring (path, make_number (2), Qnil);
 
-  new_argv = SAFE_ALLOCA ((nargs > 4 ? nargs - 2 : 2) * sizeof *new_argv);
+  SAFE_NALLOCA (new_argv, 1, nargs < 4 ? 2 : nargs - 2);
 
   {
     struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
@@ -520,10 +505,10 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
       char const *outf = tmpdir ? tmpdir : "";
       tempfile = alloca (strlen (outf) + 20);
       strcpy (tempfile, outf);
-      dostounix_filename (tempfile, 0);
+      dostounix_filename (tempfile);
       if (*tempfile == '\0' || tempfile[strlen (tempfile) - 1] != '/')
        strcat (tempfile, "/");
-      strcat (tempfile, "detmp.XXX");
+      strcat (tempfile, "emXXXXXX");
       mktemp (tempfile);
       if (!*tempfile)
        report_file_error ("Opening process output file", Qnil);
@@ -712,8 +697,6 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
   unblock_child_signal (&oldset);
   unblock_input ();
 
-#endif /* not MSDOS */
-
   if (pid < 0)
     report_file_errno ("Doing vfork", Qnil, child_errno);
 
@@ -728,6 +711,8 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
   emacs_close (filefd);
   clear_unwind_protect (count - 1);
 
+#endif /* not MSDOS */
+
   if (INTEGERP (buffer))
     return unbind_to (count, Qnil);
 
@@ -820,8 +805,10 @@ 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.  */
@@ -829,6 +816,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
              ptrdiff_t count1 = SPECPDL_INDEX ();
 
              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
@@ -994,7 +982,7 @@ create_temp_file (ptrdiff_t nargs, Lisp_Object *args,
 
     count = SPECPDL_INDEX ();
     record_unwind_protect_nothing ();
-    fd = mkostemp (tempfile, O_CLOEXEC);
+    fd = mkostemp (tempfile, O_BINARY | O_CLOEXEC);
     if (fd < 0)
       report_file_error ("Failed to open temporary file using pattern",
                         pattern);
@@ -1163,6 +1151,25 @@ add_env (char **env, char **new_env, char *string)
   return new_env;
 }
 
+#ifndef DOS_NT
+
+/* 'exec' failed inside a child running NAME, with error number ERR.
+   Report the error and exit the child.  */
+
+static _Noreturn void
+exec_failed (char const *name, int err)
+{
+  /* Avoid deadlock if the child's perror writes to a full pipe; the
+     pipe's reader is the parent, but with vfork the parent can't
+     run until the child exits.  Truncate the diagnostic instead.  */
+  fcntl (STDERR_FILENO, F_SETFL, O_NONBLOCK);
+
+  errno = err;
+  emacs_perror (name);
+  _exit (err == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
+}
+#endif
+
 /* This is the last thing run in a newly forked inferior
    either synchronous or asynchronous.
    Copy descriptors IN, OUT and ERR as descriptors 0, 1 and 2.
@@ -1186,8 +1193,6 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
   int cpid;
   HANDLE handles[3];
 #else
-  int exec_errno;
-
   pid_t pid = getpid ();
 #endif /* WINDOWSNT */
 
@@ -1208,6 +1213,13 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
        on that.  */
     pwd_var = xmalloc (i + 5);
 #else
+    /* WINDOWSNT doesn't define exec_failed, and doesn't need this
+       test, since a directory name cannot be longer than 260
+       characters, i.e. 260 * 4 = 1040 UTF-8 bytes.  */
+#ifndef WINDOWSNT
+    if (MAX_ALLOCA - 5 < i)
+      exec_failed (new_argv[0], ENOMEM);
+#endif
     pwd_var = alloca (i + 5);
 #endif
     temp = pwd_var + 4;
@@ -1274,6 +1286,10 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
       }
 
     /* new_length + 2 to include PWD and terminating 0.  */
+#ifndef WINDOWSNT
+    if (MAX_ALLOCA / sizeof *env - 2 < new_length)
+      exec_failed (new_argv[0], ENOMEM);
+#endif
     env = new_env = alloca ((new_length + 2) * sizeof *env);
     /* If we have a PWD envvar, pass one down,
        but with corrected value.  */
@@ -1282,7 +1298,14 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
 
     if (STRINGP (display))
       {
-       char *vdata = alloca (sizeof "DISPLAY=" + SBYTES (display));
+       char *vdata;
+
+       /* WINDOWSNT doesn't have $DISPLAY.  */
+#ifndef WINDOWSNT
+       if (MAX_ALLOCA - sizeof "DISPLAY=" < SBYTES (display))
+         exec_failed (new_argv[0], ENOMEM);
+#endif
+       vdata = alloca (sizeof "DISPLAY=" + SBYTES (display));
        strcpy (vdata, "DISPLAY=");
        strcat (vdata, SSDATA (display));
        new_env = add_env (env, new_env, vdata);
@@ -1357,16 +1380,7 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
   tcsetpgrp (0, pid);
 
   execve (new_argv[0], new_argv, env);
-  exec_errno = errno;
-
-  /* Avoid deadlock if the child's perror writes to a full pipe; the
-     pipe's reader is the parent, but with vfork the parent can't
-     run until the child exits.  Truncate the diagnostic instead.  */
-  fcntl (STDERR_FILENO, F_SETFL, O_NONBLOCK);
-
-  errno = exec_errno;
-  emacs_perror (new_argv[0]);
-  _exit (exec_errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
+  exec_failed (new_argv[0], errno);
 
 #else /* MSDOS */
   pid = run_msdos_command (new_argv, pwd_var + 4, in, out, err, env);
@@ -1500,14 +1514,14 @@ If optional parameter ENV is a list, then search this list instead of
 }
 
 /* A version of getenv that consults the Lisp environment lists,
-   easily callable from C.  */
+   easily callable from C.  This is usually called from egetenv.  */
 char *
-egetenv (const char *var)
+egetenv_internal (const char *var, ptrdiff_t len)
 {
   char *value;
   ptrdiff_t valuelen;
 
-  if (getenv_internal (var, strlen (var), &value, &valuelen, Qnil))
+  if (getenv_internal (var, len, &value, &valuelen, Qnil))
     return value;
   else
     return 0;
@@ -1555,20 +1569,13 @@ init_callproc_1 (void)
 void
 init_callproc (void)
 {
-  char *data_dir = egetenv ("EMACSDATA");
+  bool data_dir = egetenv ("EMACSDATA") != 0;
 
-  register char * sh;
+  char *sh;
   Lisp_Object tempdir;
 #ifdef HAVE_NS
   if (data_dir == 0)
-    {
-      const char *etc_dir = ns_etc_directory ();
-      if (etc_dir)
-        {
-          data_dir = alloca (strlen (etc_dir) + 1);
-          strcpy (data_dir, etc_dir);
-        }
-    }
+    data_dir == ns_etc_directory () != 0;
 #endif
 
   if (!NILP (Vinstallation_directory))
@@ -1637,12 +1644,12 @@ init_callproc (void)
 #endif
     {
       tempdir = Fdirectory_file_name (Vexec_directory);
-      if (! file_accessible_directory_p (SSDATA (tempdir)))
+      if (! file_accessible_directory_p (tempdir))
        dir_warning ("arch-dependent data dir", Vexec_directory);
     }
 
   tempdir = Fdirectory_file_name (Vdata_directory);
-  if (! file_accessible_directory_p (SSDATA (tempdir)))
+  if (! file_accessible_directory_p (tempdir))
     dir_warning ("arch-independent data dir", Vdata_directory);
 
   sh = getenv ("SHELL");
@@ -1674,10 +1681,8 @@ syms_of_callproc (void)
 {
 #ifndef DOS_NT
   Vtemp_file_name_pattern = build_string ("emacsXXXXXX");
-#elif defined (WINDOWSNT)
+#else  /* DOS_NT */
   Vtemp_file_name_pattern = build_string ("emXXXXXX");
-#else
-  Vtemp_file_name_pattern = build_string ("detmp.XXX");
 #endif
   staticpro (&Vtemp_file_name_pattern);