(construct_menu_click, construct_mouse_click):
[bpt/emacs.git] / src / callproc.c
index 19bd7f3..9bf6d23 100644 (file)
@@ -1,11 +1,11 @@
 /* Synchronous subprocess invocation for GNU Emacs.
-   Copyright (C) 1985, 1986, 1987, 1988, 1992 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
+the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -20,8 +20,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include <signal.h>
 #include <errno.h>
+#include <stdio.h>
 
-#include "config.h"
+#include <config.h>
+
+extern int errno;
+extern char *strerror ();
 
 /* Define SIGCHLD as an alias for SIGCLD.  */
 
@@ -30,12 +34,19 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #endif /* SIGCLD */
 
 #include <sys/types.h>
-#define PRIO_PROCESS 0
+
 #include <sys/file.h>
 #ifdef USG5
 #include <fcntl.h>
 #endif
 
+#ifdef MSDOS   /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <errno.h>
+#endif /* MSDOS */
+
 #ifndef O_RDONLY
 #define O_RDONLY 0
 #endif
@@ -47,9 +58,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "lisp.h"
 #include "commands.h"
 #include "buffer.h"
-#include "paths.h"
+#include <paths.h>
 #include "process.h"
 #include "syssignal.h"
+#include "systty.h"
 
 #ifdef VMS
 extern noshare char **environ;
@@ -59,7 +71,12 @@ extern char **environ;
 
 #define max(a, b) ((a) > (b) ? (a) : (b))
 
-Lisp_Object Vexec_path, Vexec_directory, Vdata_directory;
+#ifdef MSDOS
+Lisp_Object Vbinary_process;
+#endif
+
+Lisp_Object Vexec_path, Vexec_directory, Vdata_directory, Vdoc_directory;
+Lisp_Object Vconfigure_info_directory;
 
 Lisp_Object Vshell_file_name;
 
@@ -75,7 +92,16 @@ char *synch_process_death;
 /* If synch_process_death is zero,
    this is exit code of synchronous subprocess.  */
 int synch_process_retcode;
+
+extern Lisp_Object Vdoc_file_name;
 \f
+/* Clean up when exiting Fcall_process.
+   On MSDOS, delete the temporary file on any kind of termination.
+   On Unix, kill the process and any children on termination by signal.  */
+
+/* Nonzero if this is termination due to exit.  */
+static int call_process_exited;
+
 #ifndef VMS  /* VMS version is in vmsproc.c.  */
 
 static Lisp_Object
@@ -92,8 +118,23 @@ Lisp_Object
 call_process_cleanup (fdpid)
      Lisp_Object fdpid;
 {
+#ifdef MSDOS
+  /* for MSDOS fdpid is really (fd . tempfile)  */
+  register Lisp_Object file;
+  file = Fcdr (fdpid);
+  close (XFASTINT (Fcar (fdpid)));
+  if (strcmp (XSTRING (file)-> data, NULL_DEVICE) != 0)
+    unlink (XSTRING (file)->data);
+#else /* not MSDOS */
   register int pid = XFASTINT (Fcdr (fdpid));
 
+
+  if (call_process_exited)
+    {
+      close (XFASTINT (Fcar (fdpid)));
+      return Qnil;
+    }
+
   if (EMACS_KILLPG (pid, SIGINT) == 0)
     {
       int count = specpdl_ptr - specpdl;
@@ -108,6 +149,7 @@ call_process_cleanup (fdpid)
     }
   synch_process_alive = 0;
   close (XFASTINT (Fcar (fdpid)));
+#endif /* not MSDOS */
   return Qnil;
 }
 
@@ -126,7 +168,7 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you quit again.")
      int nargs;
      register Lisp_Object *args;
 {
-  Lisp_Object display, infile, buffer, path, current_dir;
+  Lisp_Object infile, buffer, current_dir, display, path;
   int fd[2];
   int filefd;
   register int pid;
@@ -135,22 +177,28 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you quit again.")
   register unsigned char **new_argv
     = (unsigned char **) alloca ((max (2, nargs - 2)) * sizeof (char *));
   struct buffer *old = current_buffer;
+#ifdef MSDOS   /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
+  char *outf, *tempfile;
+  int outfilefd;
+#endif
 #if 0
   int mask;
 #endif
   CHECK_STRING (args[0], 0);
 
+#ifndef subprocesses
+  /* Without asynchronous processes we cannot have BUFFER == 0.  */
+  if (nargs >= 3 && XTYPE (args[2]) == Lisp_Int)
+    error ("Operating system cannot handle asynchronous subprocesses");
+#endif /* subprocesses */
+
   if (nargs >= 2 && ! NILP (args[1]))
     {
       infile = Fexpand_file_name (args[1], current_buffer->directory);
       CHECK_STRING (infile, 1);
     }
   else
-#ifdef VMS
-    infile = build_string ("NLA0:");
-#else
-    infile = build_string ("/dev/null");
-#endif /* not VMS */
+    infile = build_string (NULL_DEVICE);
 
   if (nargs >= 3)
     {
@@ -168,8 +216,54 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you quit again.")
   else 
     buffer = Qnil;
 
+  /* Make sure that the child will be able to chdir to the current
+     buffer's current directory, or its unhandled equivalent.  We
+     can't just have the child check for an error when it does the
+     chdir, since it's in a vfork.
+
+     We have to GCPRO around this because Fexpand_file_name,
+     Funhandled_file_name_directory, and Ffile_accessible_directory_p
+     might call a file name handling function.  The argument list is
+     protected by the caller, so all we really have to worry about is
+     buffer.  */
+  {
+    struct gcpro gcpro1, gcpro2, gcpro3;
+
+    current_dir = current_buffer->directory;
+
+    GCPRO3 (infile, buffer, current_dir);
+
+    current_dir
+      = expand_and_dir_to_file (Funhandled_file_name_directory (current_dir),
+                               Qnil);
+    if (NILP (Ffile_accessible_directory_p (current_dir)))
+      report_file_error ("Setting current directory",
+                        Fcons (current_buffer->directory, Qnil));
+
+    UNGCPRO;
+  }
+
   display = nargs >= 4 ? args[3] : Qnil;
 
+  filefd = open (XSTRING (infile)->data, O_RDONLY, 0);
+  if (filefd < 0)
+    {
+      report_file_error ("Opening process input file", Fcons (infile, Qnil));
+    }
+  /* Search for program; barf if not found.  */
+  {
+    struct gcpro gcpro1;
+
+    GCPRO1 (current_dir);
+    openp (Vexec_path, args[0], EXEC_SUFFIXES, &path, 1);
+    UNGCPRO;
+  }
+  if (NILP (path))
+    {
+      close (filefd);
+      report_file_error ("Searching for program", Fcons (args[0], Qnil));
+    }
+  new_argv[0] = XSTRING (path)->data;
   {
     register int i;
     for (i = 4; i < nargs; i++)
@@ -177,44 +271,50 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you quit again.")
        CHECK_STRING (args[i], i);
        new_argv[i - 3] = XSTRING (args[i])->data;
       }
-    /* Program name is first command arg */
-    new_argv[0] = XSTRING (args[0])->data;
     new_argv[i - 3] = 0;
   }
 
-  filefd = open (XSTRING (infile)->data, O_RDONLY, 0);
-  if (filefd < 0)
+#ifdef MSDOS /* MW, July 1993 */
+  /* These vars record information from process termination.
+     Clear them now before process can possibly terminate,
+     to avoid timing error if process terminates soon.  */
+  synch_process_death = 0;
+  synch_process_retcode = 0;
+
+  if ((outf = egetenv ("TMP")) || (outf = egetenv ("TEMP")))
+    strcpy (tempfile = alloca (strlen (outf) + 20), outf);
+  else
     {
-      report_file_error ("Opening process input file", Fcons (infile, Qnil));
+      tempfile = alloca (20);
+      *tempfile = '\0';
     }
-  /* Search for program; barf if not found.  */
-  openp (Vexec_path, args[0], "", &path, 1);
-  if (NILP (path))
+  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)
     {
       close (filefd);
-      report_file_error ("Searching for program", Fcons (args[0], Qnil));
+      report_file_error ("Opening process output file", Fcons (tempfile, Qnil));
     }
-  new_argv[0] = XSTRING (path)->data;
+#endif
 
   if (XTYPE (buffer) == Lisp_Int)
-    fd[1] = open ("/dev/null", O_WRONLY), fd[0] = -1;
+    fd[1] = open (NULL_DEVICE, O_WRONLY), fd[0] = -1;
   else
     {
+#ifndef MSDOS
       pipe (fd);
+#endif
 #if 0
       /* Replaced by close_process_descs */
       set_exclusive_use (fd[0]);
 #endif
     }
 
-  /* Make sure that the child will be able to chdir to the current
-     buffer's current directory.  We can't just have the child check
-     for an error when it does the chdir, since it's in a vfork.  */
-  current_dir = expand_and_dir_to_file (current_buffer->directory, Qnil);
-  if (NILP (Ffile_accessible_directory_p (current_dir)))
-    report_file_error ("Setting current directory",
-                      Fcons (current_buffer->directory, Qnil));
-
   {
     /* child_setup must clobber environ in systems with true vfork.
        Protect it from permanent change.  */
@@ -228,6 +328,26 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you quit again.")
     /* Record that we're about to create a synchronous process.  */
     synch_process_alive = 1;
 
+    /* These vars record information from process termination.
+       Clear them now before process can possibly terminate,
+       to avoid timing error if process terminates soon.  */
+    synch_process_death = 0;
+    synch_process_retcode = 0;
+
+#ifdef MSDOS /* MW, July 1993 */
+    /* ??? Someone who knows MSDOG needs to check whether this properly
+       closes all descriptors that it opens.  */
+    pid = run_msdos_command (new_argv, current_dir, filefd, outfilefd);
+    close (outfilefd);
+    fd1 = -1; /* No harm in closing that one!  */
+    fd[0] = open (tempfile, NILP (Vbinary_process) ? O_TEXT : O_BINARY);
+    if (fd[0] < 0)
+      {
+       unlink (tempfile);
+       close (filefd);
+       report_file_error ("Cannot re-open temporary file", Qnil);
+      }
+#else /* not MSDOS */
     pid = vfork ();
 
     if (pid == 0)
@@ -241,28 +361,28 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you quit again.")
 #endif /* USG */
        child_setup (filefd, fd1, fd1, new_argv, 0, current_dir);
       }
-
-#if 0
-    /* Tell SIGCHLD handler to look for this pid.  */
-    synch_process_pid = pid;
-    /* Now let SIGCHLD come through.  */
-    sigsetmask (mask);
-#endif
+#endif /* not MSDOS */
 
     environ = save_environ;
 
+    /* Close most of our fd's, but not fd[0]
+       since we will use that to read input from.  */
     close (filefd);
-    close (fd1);
+    if (fd1 >= 0)
+      close (fd1);
   }
 
   if (pid < 0)
     {
-      close (fd[0]);
+      if (fd[0] >= 0)
+       close (fd[0]);
       report_file_error ("Doing vfork", Qnil);
     }
 
   if (XTYPE (buffer) == Lisp_Int)
     {
+      if (fd[0] >= 0)
+       close (fd[0]);
 #ifndef subprocesses
       /* If Emacs has been built with asynchronous subprocess support,
         we don't need to do this, I think because it will then have
@@ -272,11 +392,17 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you quit again.")
       return Qnil;
     }
 
-  synch_process_death = 0;
-  synch_process_retcode = 0;
+  /* Enable sending signal if user quits below.  */
+  call_process_exited = 0;
 
+#ifdef MSDOS
+  /* MSDOS needs different cleanup information.  */
+  record_unwind_protect (call_process_cleanup,
+                        Fcons (make_number (fd[0]), build_string (tempfile)));
+#else
   record_unwind_protect (call_process_cleanup,
                         Fcons (make_number (fd[0]), make_number (pid)));
+#endif /* not MSDOS */
 
 
   if (XTYPE (buffer) == Lisp_Buffer)
@@ -287,6 +413,7 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you quit again.")
 
   {
     register int nread;
+    int first = 1;
 
     while ((nread = read (fd[0], buf, sizeof buf)) > 0)
       {
@@ -294,7 +421,12 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you quit again.")
        if (!NILP (buffer))
          insert (buf, nread);
        if (!NILP (display) && INTERACTIVE)
-         redisplay_preserve_echo_area ();
+         {
+           if (first)
+             prepare_menu_bars ();
+           first = 0;
+           redisplay_preserve_echo_area ();
+         }
        immediate_quit = 1;
        QUIT;
       }
@@ -307,6 +439,10 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you quit again.")
 
   set_buffer_internal (old);
 
+  /* Don't kill any children that the subprocess may have left behind
+     when exiting.  */
+  call_process_exited = 1;
+
   unbind_to (count, Qnil);
 
   if (synch_process_death)
@@ -315,7 +451,7 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you quit again.")
 }
 #endif
 \f
-static void
+static Lisp_Object
 delete_temp_file (name)
      Lisp_Object name;
 {
@@ -339,14 +475,35 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you quit again.")
      register Lisp_Object *args;
 {
   register Lisp_Object filename_string, start, end;
+#ifdef MSDOS
+  char *tempfile;
+#else
   char tempfile[20];
+#endif
   int count = specpdl_ptr - specpdl;
+#ifdef MSDOS
+  char *outf = '\0';
+
+  if ((outf = egetenv ("TMP")) || (outf = egetenv ("TEMP")))
+    strcpy (tempfile = alloca (strlen (outf) + 20), outf);
+  else
+    {
+      tempfile = alloca (20);
+      *tempfile = '\0';
+    }
+  dostounix_filename (tempfile);
+  if (tempfile[strlen (tempfile) - 1] != '/')
+    strcat (tempfile, "/");
+  strcat (tempfile, "detmp.XXX");
+#else /* not MSDOS */
 
 #ifdef VMS
   strcpy (tempfile, "tmp:emacsXXXXXX.");
 #else
   strcpy (tempfile, "/tmp/emacsXXXXXX");
 #endif
+#endif /* not MSDOS */
+
   mktemp (tempfile);
 
   filename_string = build_string (tempfile);
@@ -359,9 +516,8 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you quit again.")
     Fdelete_region (start, end);
 
   args[3] = filename_string;
-  Fcall_process (nargs - 2, args + 2);
 
-  return unbind_to (count, Qnil);
+  return unbind_to (count, Fcall_process (nargs - 2, args + 2));
 }
 \f
 #ifndef VMS /* VMS version is in vmsproc.c.  */
@@ -392,9 +548,13 @@ child_setup (in, out, err, new_argv, set_pgrp, current_dir)
      int set_pgrp;
      Lisp_Object current_dir;
 {
+#ifdef MSDOS
+  /* The MSDOS port of gcc cannot fork, vfork, ... so we must call system
+     instead.  */
+#else /* not MSDOS */
   char **env;
 
-  register int pid = getpid();
+  int pid = getpid ();
 
   {
     extern int emacs_priority;
@@ -406,6 +566,7 @@ child_setup (in, out, err, new_argv, set_pgrp, current_dir)
   /* Close Emacs's descriptors that this process should not have.  */
   close_process_descs ();
 #endif
+  close_load_descs ();
 
   /* Note that use of alloca is always safe here.  It's obvious for systems
      that do not have true vfork or that have true (stack) alloca.
@@ -444,18 +605,55 @@ child_setup (in, out, err, new_argv, set_pgrp, current_dir)
         tem = XCONS (tem)->cdr)
       new_length++;
 
-    /* new_length + 1 to include terminating 0 */
+    /* new_length + 1 to include terminating 0 */
     env = new_env = (char **) alloca ((new_length + 1) * sizeof (char *));
 
-    /* Copy the Vprocess_alist strings into new_env.  */
+    /* Copy the Vprocess_environment strings into new_env.  */
     for (tem = Vprocess_environment;
         (XTYPE (tem) == Lisp_Cons
          && XTYPE (XCONS (tem)->car) == Lisp_String);
         tem = XCONS (tem)->cdr)
-      *new_env++ = (char *) XSTRING (XCONS (tem)->car)->data;
+      {
+       char **ep = env;
+       char *string = (char *) XSTRING (XCONS (tem)->car)->data;
+       /* See if this string duplicates any string already in the env.
+          If so, don't put it in.
+          When an env var has multiple definitions,
+          we keep the definition that comes first in process-environment.  */
+       for (; ep != new_env; ep++)
+         {
+           char *p = *ep, *q = string;
+           while (1)
+             {
+               if (*q == 0)
+                 /* The string is malformed; might as well drop it.  */
+                 goto duplicate;
+               if (*q != *p)
+                 break;
+               if (*q == '=')
+                 goto duplicate;
+               p++, q++;
+             }
+         }
+       *new_env++ = string;
+      duplicate: ;
+      }
     *new_env = 0;
   }
 
+  /* Make sure that in, out, and err are not actually already in
+     descriptors zero, one, or two; this could happen if Emacs is
+     started with its standard in, out, or error closed, as might
+     happen under X.  */
+  in = relocate_fd (in, 3);
+  if (out == err)
+    err = out = relocate_fd (out, 3);
+  else
+    {
+      out = relocate_fd (out, 3);
+      err = relocate_fd (err, 3);
+    }
+
   close (0);
   close (1);
   close (2);
@@ -468,11 +666,14 @@ child_setup (in, out, err, new_argv, set_pgrp, current_dir)
   close (err);
 
 #ifdef USG
+#ifndef SETPGRP_RELEASES_CTTY
   setpgrp ();                  /* No arguments but equivalent in this case */
+#endif
 #else
   setpgrp (pid, pid);
 #endif /* USG */
-  setpgrp_of_tty (pid);
+  /* setpgrp_of_tty is incorrect here; it uses input_fd.  */
+  EMACS_SET_TTY_PGRP (0, &pid);
 
 #ifdef vipc
   something missing here;
@@ -487,6 +688,36 @@ child_setup (in, out, err, new_argv, set_pgrp, current_dir)
   write (1, "Couldn't exec the program ", 26);
   write (1, new_argv[0], strlen (new_argv[0]));
   _exit (1);
+#endif /* not MSDOS */
+}
+
+/* Move the file descriptor FD so that its number is not less than MIN.
+   If the file descriptor is moved at all, the original is freed.  */
+int
+relocate_fd (fd, min)
+     int fd, min;
+{
+  if (fd >= min)
+    return fd;
+  else
+    {
+      int new = dup (fd);
+      if (new == -1)
+       {
+         char *message1 = "Error while setting up child: ";
+         char *errmessage = strerror (errno);
+         char *message2 = "\n";
+         write (2, message1, strlen (message1));
+         write (2, errmessage, strlen (errmessage));
+         write (2, message2, strlen (message2));
+         _exit (1);
+       }
+      /* Note that we hold the original FD open while we recurse,
+        to guarantee we'll get a new FD if we need it.  */
+      new = relocate_fd (new, min);
+      close (fd);
+      return new;
+    }
 }
 
 static int
@@ -500,8 +731,9 @@ getenv_internal (var, varlen, value, valuelen)
 
   for (scan = Vprocess_environment; CONSP (scan); scan = XCONS (scan)->cdr)
     {
-      Lisp_Object entry = XCONS (scan)->car;
-      
+      Lisp_Object entry;
+
+      entry = XCONS (scan)->car;
       if (XTYPE (entry) == Lisp_String
          && XSTRING (entry)->size > varlen
          && XSTRING (entry)->data[varlen] == '='
@@ -516,7 +748,7 @@ getenv_internal (var, varlen, value, valuelen)
   return 0;
 }
 
-DEFUN ("getenv", Fgetenv, Sgetenv, 1, 2, 0,
+DEFUN ("getenv", Fgetenv, Sgetenv, 1, 1, 0,
   "Return the value of environment variable VAR, as a string.\n\
 VAR should be a string.  Value is nil if VAR is undefined in the environment.\n\
 This function consults the variable ``process-environment'' for its value.")
@@ -551,39 +783,73 @@ egetenv (var)
 
 #endif /* not VMS */
 \f
-init_callproc ()
+/* This is run before init_cmdargs.  */
+  
+init_callproc_1 ()
 {
-  register char * sh;
-  register char **envp;
-  Lisp_Object tempdir;
+  char *data_dir = egetenv ("EMACSDATA");
+  char *doc_dir = egetenv ("EMACSDOC");
 
-  {
-    char *data_dir = egetenv ("EMACSDATA");
-    
-    Vdata_directory =
-      Ffile_name_as_directory
-       (build_string (data_dir ? data_dir : PATH_DATA));
-  }
+  Vdata_directory
+    = Ffile_name_as_directory (build_string (data_dir ? data_dir 
+                                            : PATH_DATA));
+  Vdoc_directory
+    = Ffile_name_as_directory (build_string (doc_dir ? doc_dir
+                                            : PATH_DOC));
 
   /* Check the EMACSPATH environment variable, defaulting to the
      PATH_EXEC path from paths.h.  */
   Vexec_path = decode_env_path ("EMACSPATH", PATH_EXEC);
   Vexec_directory = Ffile_name_as_directory (Fcar (Vexec_path));
   Vexec_path = nconc2 (decode_env_path ("PATH", ""), Vexec_path);
+}
+
+/* This is run after init_cmdargs, so that Vinvocation_directory is valid.  */
+
+init_callproc ()
+{
+  char *data_dir = egetenv ("EMACSDATA");
+    
+  register char * sh;
+  Lisp_Object tempdir;
+
+  if (initialized && !NILP (Vinstallation_directory))
+    {
+      /* Add to the path the lib-src subdir of the installation dir.  */
+      Lisp_Object tem;
+      tem = Fexpand_file_name (build_string ("lib-src"),
+                              Vinstallation_directory);
+      if (NILP (Fmember (tem, Vexec_path)))
+       {
+         Vexec_path = nconc2 (Vexec_path, Fcons (tem, Qnil));
+         Vexec_directory = Ffile_name_as_directory (tem);
+
+         /* If we use ../lib-src, maybe use ../etc as well.
+            Do so if ../etc exists and has our DOC-... file in it.  */
+         if (data_dir == 0)
+           {
+             tem = Fexpand_file_name (build_string ("etc"),
+                                      Vinstallation_directory);
+             Vdata_directory = Ffile_name_as_directory (tem);
+           }
+       }
+    }
 
   tempdir = Fdirectory_file_name (Vexec_directory);
   if (access (XSTRING (tempdir)->data, 0) < 0)
     {
-      printf ("Warning: arch-dependent data dir (%s) does not exist.\n",
-             XSTRING (Vexec_directory)->data);
+      fprintf (stderr,
+              "Warning: arch-dependent data dir (%s) does not exist.\n",
+              XSTRING (Vexec_directory)->data);
       sleep (2);
     }
 
   tempdir = Fdirectory_file_name (Vdata_directory);
   if (access (XSTRING (tempdir)->data, 0) < 0)
     {
-      printf ("Warning: arch-independent data dir (%s) does not exist.\n",
-             XSTRING (Vdata_directory)->data);
+      fprintf (stderr,
+              "Warning: arch-independent data dir (%s) does not exist.\n",
+              XSTRING (Vdata_directory)->data);
       sleep (2);
     }
 
@@ -593,6 +859,11 @@ init_callproc ()
   sh = (char *) getenv ("SHELL");
   Vshell_file_name = build_string (sh ? sh : "/bin/sh");
 #endif
+}
+
+set_process_environment ()
+{
+  register char **envp;
 
   Vprocess_environment = Qnil;
 #ifndef CANNOT_DUMP
@@ -605,6 +876,12 @@ init_callproc ()
 
 syms_of_callproc ()
 {
+#ifdef MSDOS
+  DEFVAR_LISP ("binary-process", &Vbinary_process,
+    "*If non-nil then new subprocesses are assumed to produce binary output.");
+  Vbinary_process = Qnil;
+#endif
+
   DEFVAR_LISP ("shell-file-name", &Vshell_file_name,
     "*File name to load inferior shells from.\n\
 Initialized from the SHELL environment variable.");
@@ -621,6 +898,17 @@ especially executable programs intended for Emacs to invoke.");
     "Directory of architecture-independent files that come with GNU Emacs,\n\
 intended for Emacs to use.");
 
+  DEFVAR_LISP ("doc-directory", &Vdoc_directory,
+    "Directory containing the DOC file that comes with GNU Emacs.\n\
+This is usually the same as data-directory.");
+
+  DEFVAR_LISP ("configure-info-directory", &Vconfigure_info_directory,
+    "For internal use by the build procedure only.\n\
+This is the name of the directory in which the build procedure installed\n\
+Emacs's info files; the default value for Info-default-directory-list\n\
+includes this.");
+  Vconfigure_info_directory = build_string (PATH_INFO);
+
   DEFVAR_LISP ("process-environment", &Vprocess_environment,
     "List of environment variables for subprocesses to inherit.\n\
 Each element should be a string of the form ENVVARNAME=VALUE.\n\
@@ -629,7 +917,7 @@ when Emacs starts.");
 
 #ifndef VMS
   defsubr (&Scall_process);
-#endif
   defsubr (&Sgetenv);
+#endif
   defsubr (&Scall_process_region);
 }