Merge from emacs--devo--0
[bpt/emacs.git] / src / callproc.c
index 2586160..5bd4cee 100644 (file)
@@ -1,12 +1,12 @@
 /* Synchronous subprocess invocation for GNU Emacs.
    Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1999, 2000, 2001,
-                 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+                 2002, 2003, 2004, 2005, 2006, 2007 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 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -113,14 +113,13 @@ Lisp_Object Vtemp_file_name_pattern;
 
 Lisp_Object Vshell_file_name;
 
-Lisp_Object Vglobal_environment;
 Lisp_Object Vprocess_environment;
 
 #ifdef DOS_NT
 Lisp_Object Qbuffer_file_type;
 #endif /* DOS_NT */
 
-/* True iff we are about to fork off a synchronous process or if we
+/* True if we are about to fork off a synchronous process or if we
    are waiting for it.  */
 int synch_process_alive;
 
@@ -134,9 +133,6 @@ int synch_process_termsig;
    this is exit code of synchronous subprocess.  */
 int synch_process_retcode;
 
-/* List of environment variables to look up in emacsclient.  */
-Lisp_Object Vlocal_environment_variables;
-
 \f
 /* Clean up when exiting Fcall_process.
    On MSDOS, delete the temporary file on any kind of termination.
@@ -210,6 +206,10 @@ t (mix it with ordinary output), or a file name string.
 Fourth arg DISPLAY non-nil means redisplay buffer as output is inserted.
 Remaining arguments are strings passed as command arguments to PROGRAM.
 
+If executable PROGRAM can't be found as an executable, `call-process'
+signals a Lisp error.  `call-process' reports errors in execution of
+the program only through its return and output.
+
 If BUFFER is 0, `call-process' returns immediately with value nil.
 Otherwise it waits for PROGRAM to terminate
 and returns a numeric exit status or a signal description string.
@@ -302,6 +302,10 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS)  */)
              val = Qnil;
          }
        setup_coding_system (Fcheck_coding_system (val), &argument_coding);
+       if (argument_coding.common_flags & CODING_ASCII_INCOMPATIBLE_MASK)
+         setup_coding_system (Qraw_text, &argument_coding);
+       if (argument_coding.eol_type == CODING_EOL_UNDECIDED)
+         argument_coding.eol_type = system_eol_type;
       }
   }
 
@@ -1103,7 +1107,11 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
 
 #ifdef HAVE_MKSTEMP
  {
-   int fd = mkstemp (tempfile);
+   int fd;
+
+   BLOCK_INPUT;
+   fd = mkstemp (tempfile);
+   UNBLOCK_INPUT;
    if (fd == -1)
      report_file_error ("Failed to open temporary file",
                        Fcons (Vtemp_file_name_pattern, Qnil));
@@ -1237,6 +1245,8 @@ child_setup (in, out, err, new_argv, set_pgrp, current_dir)
 {
   char **env;
   char *pwd_var;
+  char *term_var;
+  char *display_var;
 #ifdef WINDOWSNT
   int cpid;
   HANDLE handles[3];
@@ -1317,9 +1327,12 @@ child_setup (in, out, err, new_argv, set_pgrp, current_dir)
     register char **new_env;
     char **p, **q;
     register int new_length;
-    Lisp_Object environment = Vglobal_environment;
-    Lisp_Object local;
+    Lisp_Object local = selected_frame; /* get_frame_param (XFRAME (Fframe_with_environment (selected_frame)), */
+/*                                          Qenvironment); */
 
+    Lisp_Object term;
+    Lisp_Object display;
+    
     new_length = 0;
 
     for (tem = Vprocess_environment;
@@ -1327,51 +1340,67 @@ child_setup (in, out, err, new_argv, set_pgrp, current_dir)
          tem = XCDR (tem))
       new_length++;
 
-    if (!NILP (Vlocal_environment_variables))
-      {
-        local = get_frame_param (XFRAME (Fframe_with_environment (selected_frame)),
-                                 Qenvironment);
-        if (EQ (Vlocal_environment_variables, Qt)
-            && !NILP (local))
-          environment = local;
-        else if (CONSP (local))
-          {
-            new_length += Fsafe_length (Vlocal_environment_variables);
-          }
-      }
-
-    for (tem = environment;
+#if 0    
+    for (tem = local;
         CONSP (tem) && STRINGP (XCAR (tem));
         tem = XCDR (tem))
       new_length++;
+#endif
+
+    /* Add TERM and DISPLAY from the frame local values. */
+    term = get_frame_param (XFRAME (local), Qterm_environment_variable);
+    if (! NILP (term))
+      new_length++;
+
+    display = get_frame_param (XFRAME (local), Qdisplay_environment_variable);
+    if (! NILP (display))
+      new_length++;
 
     /* new_length + 2 to include PWD and terminating 0.  */
     env = new_env = (char **) alloca ((new_length + 2) * sizeof (char *));
 
     /* If we have a PWD envvar, pass one down,
        but with corrected value.  */
-    if (getenv ("PWD"))
+    if (egetenv ("PWD"))
       *new_env++ = pwd_var;
  
+    if (! NILP (term))
+      {
+       int vlen = strlen ("TERM=") + strlen (SDATA (term)) + 1;
+       char *vdata = (char *) alloca (vlen);
+       strcpy (vdata, "TERM=");
+       strcat (vdata, SDATA (term));
+       new_env = add_env (env, new_env, vdata);
+      }
+
+    if (! NILP (display))
+      {
+       int vlen = strlen ("DISPLAY=") + strlen (SDATA (display)) + 1;
+       char *vdata = (char *) alloca (vlen);
+       strcpy (vdata, "DISPLAY=");
+       strcat (vdata, SDATA (display));
+       new_env = add_env (env, new_env, vdata);
+      }
+
     /* Overrides.  */
     for (tem = Vprocess_environment;
         CONSP (tem) && STRINGP (XCAR (tem));
         tem = XCDR (tem))
-      new_env = add_env (env, new_env, SDATA (XCAR (tem)));
+      {
+       if ((strcmp (SDATA (XCAR (tem)), "TERM") != 0)
+           && (strcmp (SDATA (XCAR (tem)), "DISPLAY") != 0))
+         new_env = add_env (env, new_env, SDATA (XCAR (tem)));
+      }
 
-    /* Local part of environment, if Vlocal_environment_variables is a list.  */
-    for (tem = Vlocal_environment_variables;
+  
+#if 0    
+    /* Local part of environment.  */
+    for (tem = local;
          CONSP (tem) && STRINGP (XCAR (tem));
          tem = XCDR (tem))
-      new_env = add_env (env, new_env, egetenv (SDATA (XCAR (tem))));
-
-    /* The rest of the environment (either Vglobal_environment or the
-       'environment frame parameter).  */
-    for (tem = environment;
-        CONSP (tem) && STRINGP (XCAR (tem));
-        tem = XCDR (tem))
       new_env = add_env (env, new_env, SDATA (XCAR (tem)));
-
+#endif
+    
     *new_env = 0;
 
     /* Remove variable names without values.  */
@@ -1385,6 +1414,8 @@ child_setup (in, out, err, new_argv, set_pgrp, current_dir)
           p++;
       }
   }
+
+  
 #ifdef WINDOWSNT
   prepare_standard_handles (in, out, err, handles);
   set_process_dir (SDATA (current_dir));
@@ -1506,79 +1537,100 @@ getenv_internal (var, varlen, value, valuelen, frame)
      Lisp_Object frame;
 {
   Lisp_Object scan;
-  Lisp_Object environment = Vglobal_environment;
+  Lisp_Object term;
+  Lisp_Object display;
+  
 
-  /* Try to find VAR in Vprocess_environment first.  */
-  for (scan = Vprocess_environment; CONSP (scan); scan = XCDR (scan))
+  if (NILP (frame))
     {
-      Lisp_Object entry = XCAR (scan);
-      if (STRINGP (entry)
-          && SBYTES (entry) >= varlen
+      /* Try to find VAR in Vprocess_environment first.  */
+      for (scan = Vprocess_environment; CONSP (scan); scan = XCDR (scan))
+        {
+          Lisp_Object entry = XCAR (scan);
+          if (STRINGP (entry)
+              && SBYTES (entry) >= varlen
 #ifdef WINDOWSNT
-          /* NT environment variables are case insensitive.  */
-          && ! strnicmp (SDATA (entry), var, varlen)
+              /* NT environment variables are case insensitive.  */
+              && ! strnicmp (SDATA (entry), var, varlen)
 #else  /* not WINDOWSNT */
-          && ! bcmp (SDATA (entry), var, varlen)
+              && ! bcmp (SDATA (entry), var, varlen)
 #endif /* not WINDOWSNT */
-          )
-        {
-          if (SBYTES (entry) > varlen && SREF (entry, varlen) == '=')
+              )
             {
-              *value = (char *) SDATA (entry) + (varlen + 1);
-              *valuelen = SBYTES (entry) - (varlen + 1);
-              return 1;
-            }
-          else if (SBYTES (entry) == varlen)
-            {
-              /* Lone variable names in Vprocess_environment mean that
-                 variable should be removed from the environment. */
-              return 0;
+              if (SBYTES (entry) > varlen && SREF (entry, varlen) == '=')
+                {
+                  *value = (char *) SDATA (entry) + (varlen + 1);
+                  *valuelen = SBYTES (entry) - (varlen + 1);
+                  return 1;
+                }
+              else if (SBYTES (entry) == varlen)
+                {
+                  /* Lone variable names in Vprocess_environment mean that
+                     variable should be removed from the environment. */
+                  return 0;
+                }
             }
         }
+      frame = selected_frame;
     }
 
-  /* Find the environment in which to search the variable. */
-  if (!NILP (frame))
-    {
-      Lisp_Object local;
-
-      CHECK_FRAME (frame);
-      frame = Fframe_with_environment (frame);
-      local = get_frame_param (XFRAME (frame), Qenvironment);
-      /* Use Vglobal_environment if there is no local environment.  */
-      if (!NILP (local))
-        environment = local;
-    }
-  else if (!NILP (Vlocal_environment_variables)) 
-    {
-      Lisp_Object local = get_frame_param (XFRAME (Fframe_with_environment (selected_frame)),
-                                           Qenvironment);
-      if (EQ (Vlocal_environment_variables, Qt)
-          && !NILP (local))
-        environment = local;
-      else if (CONSP (local))
-        {
-          for (scan = Vlocal_environment_variables; CONSP (scan); scan = XCDR (scan))
-            {
-              Lisp_Object entry = XCAR (scan);
-              if (STRINGP (entry)
-                  && SBYTES (entry) == varlen
+  /* For TERM and DISPLAY first try to get the values from the frame. */
+  term = get_frame_param (XFRAME (frame), Qterm_environment_variable);
+  if (strcmp (var, "TERM") == 0)
+    if (! NILP (term))
+      {
+         *value    = (char *) SDATA (term);
+         *valuelen = SBYTES (term);
+         return 1;
+      }
+  display = get_frame_param (XFRAME (frame), Qdisplay_environment_variable);
+  if (strcmp (var, "DISPLAY") == 0)
+    if (! NILP (display))
+      {
+         *value    = (char *) SDATA (display);
+         *valuelen = SBYTES (display);
+         return 1;
+      }
+
+  {
+    /* Try to find VAR in Vprocess_environment.  */
+    for (scan = Vprocess_environment; CONSP (scan); scan = XCDR (scan))
+      {
+       Lisp_Object entry = XCAR (scan);
+       if (STRINGP (entry)
+           && SBYTES (entry) >= varlen
 #ifdef WINDOWSNT
-                  /* NT environment variables are case insensitive.  */
-                  && ! strnicmp (SDATA (entry), var, varlen)
+           /* NT environment variables are case insensitive.  */
+           && ! strnicmp (SDATA (entry), var, varlen)
 #else  /* not WINDOWSNT */
-                  && ! bcmp (SDATA (entry), var, varlen)
+           && ! bcmp (SDATA (entry), var, varlen)
 #endif /* not WINDOWSNT */
-                  )
-                {
-                  environment = local;
-                  break;
-                } 
-            }
-        }
-    }
+           )
+         {
+           if (SBYTES (entry) > varlen && SREF (entry, varlen) == '=')
+             {
+               *value = (char *) SDATA (entry) + (varlen + 1);
+               *valuelen = SBYTES (entry) - (varlen + 1);
+               return 1;
+             }
+           else if (SBYTES (entry) == varlen)
+             {
+               /* Lone variable names in Vprocess_environment mean that
+                  variable should be removed from the environment. */
+               return 0;
+             }
+         }
+      }
+  }
 
-  for (scan = environment; CONSP (scan); scan = XCDR (scan))
+#if 0
+  /* Find the environment in which to search the variable. */
+  CHECK_FRAME (frame);
+  frame = Fframe_with_environment (frame);
+
+  for (scan = get_frame_param (XFRAME (frame), Qenvironment);
+       CONSP (scan);
+       scan = XCDR (scan))
     {
       Lisp_Object entry;
 
@@ -1599,7 +1651,7 @@ getenv_internal (var, varlen, value, valuelen, frame)
          return 1;
        }
     }
-
+#endif
   return 0;
 }
 
@@ -1608,14 +1660,13 @@ DEFUN ("getenv-internal", Fgetenv_internal, Sgetenv_internal, 1, 2, 0,
 VARIABLE should be a string.  Value is nil if VARIABLE is undefined in
 the environment.  Otherwise, value is a string.
 
-If optional parameter FRAME is non-nil, then it should be a frame.  If
-that frame has its own set of environment variables, this function
-will look up VARIABLE in there.
+This function searches `process-environment' for VARIABLE.  If it is
+not found there, then it continues the search in the environment list
+of the selected frame.
 
-Otherwise, this function searches `process-environment' for VARIABLE.
-If it is not found there, then it continues the search in either
-`global-environment' or the environment list of the selected frame,
-depending on the value of `local-environment-variables'.  */)
+If optional parameter FRAME is non-nil, then this function will ignore
+`process-environment' and will simply look up the variable in that
+frame's environment.  */)
      (variable, frame)
      Lisp_Object variable, frame;
 {
@@ -1762,8 +1813,8 @@ init_callproc ()
     {
       char *dir = getenv ("TMPDIR");
       Vtemp_file_name_pattern
-       = Fexpand_file_name (build_string ("emacsXXXXXX"),
-                            build_string (dir));
+       = Fexpand_file_name (build_string ("emacsXXXXXX"),
+                            build_string (dir));
     }
   else
     Vtemp_file_name_pattern = build_string ("/tmp/emacsXXXXXX");
@@ -1779,17 +1830,19 @@ init_callproc ()
 }
 
 void
-set_global_environment ()
+set_initial_environment ()
 {
   register char **envp;
-
-  Vglobal_environment = Qnil;
+  Lisp_Object env = Vprocess_environment;
 #ifndef CANNOT_DUMP
   if (initialized)
 #endif
-    for (envp = environ; *envp; envp++)
-      Vglobal_environment = Fcons (build_string (*envp),
-                                   Vglobal_environment);
+    {
+      for (envp = environ; *envp; envp++)
+       Vprocess_environment = Fcons (build_string (*envp),
+                                     Vprocess_environment);
+      store_frame_param (SELECTED_FRAME(), Qenvironment, Vprocess_environment);
+    }
 }
 
 void
@@ -1802,7 +1855,8 @@ syms_of_callproc ()
 
   DEFVAR_LISP ("shell-file-name", &Vshell_file_name,
               doc: /* *File name to load inferior shells from.
-Initialized from the SHELL environment variable.  */);
+Initialized from the SHELL environment variable, or to a system-dependent
+default if SHELL is not set.  */);
 
   DEFVAR_LISP ("exec-path", &Vexec_path,
               doc: /* *List of directories to search programs to run in subprocesses.
@@ -1824,12 +1878,12 @@ These are files intended for Emacs to use while it runs.  */);
 
   DEFVAR_LISP ("doc-directory", &Vdoc_directory,
               doc: /* Directory containing the DOC file that comes with GNU Emacs.
-This is usually the same as data-directory.  */);
+This is usually the same as `data-directory'.  */);
 
   DEFVAR_LISP ("configure-info-directory", &Vconfigure_info_directory,
               doc: /* For internal use by the build procedure only.
 This is the name of the directory in which the build procedure installed
-Emacs's info files; the default value for Info-default-directory-list
+Emacs's info files; the default value for `Info-default-directory-list'
 includes this.  */);
   Vconfigure_info_directory = build_string (PATH_INFO);
 
@@ -1847,37 +1901,16 @@ If this variable is nil, then Emacs is unable to use a shared directory.  */);
 This is used by `call-process-region'.  */);
   /* This variable is initialized in init_callproc.  */
 
-  DEFVAR_LISP ("global-environment", &Vglobal_environment,
-              doc: /* Global list of environment variables for subprocesses to inherit.
-Each element should be a string of the form ENVVARNAME=VALUE.
-
-The environment which Emacs inherits is placed in this variable when
-Emacs starts.
-
-Some frames may have their own local list of environment variables in
-their 'environment parameter, which may override this global list; see
-`local-environment-variables' and `frame-with-environment'.  See
-`process-environment' for a way to modify an environment variable on
-all frames.
-
-If multiple entries define the same variable, the first one always
-takes precedence.
-
-Non-ASCII characters are encoded according to the initial value of
-`locale-coding-system', i.e. the elements must normally be decoded for use.
-See `setenv' and `getenv'.  */);
-
   DEFVAR_LISP ("process-environment", &Vprocess_environment,
               doc: /* List of overridden environment variables for subprocesses to inherit.
 Each element should be a string of the form ENVVARNAME=VALUE.
 
-Entries in this list take precedence to those in `global-environment'
-or the frame-local environments.  (See `local-environment-variables'
-and `frame-with-environment'.)  Therefore, let-binding
-`process-environment' is an easy way to temporarily change the value
-of an environment variable, irrespective of where it comes from.  To
-use `process-environment' to remove an environment variable, include
-only its name in the list, without "=VALUE".
+Entries in this list take precedence to those in the frame-local
+environments.  Therefore, let-binding `process-environment' is an easy
+way to temporarily change the value of an environment variable,
+irrespective of where it comes from.  To use `process-environment' to
+remove an environment variable, include only its name in the list,
+without "=VALUE".
 
 This variable is set to nil when Emacs starts.
 
@@ -1896,23 +1929,6 @@ See `setenv' and `getenv'.  */);
   defsubr (&Sgetenv_internal);
 #endif
   defsubr (&Scall_process_region);
-
-  DEFVAR_LISP ("local-environment-variables", &Vlocal_environment_variables,
-               doc: /*         Enable or disable frame-local environment variables.
-If set to t, `getenv', `setenv' and subprocess creation functions use
-the local environment of the selected frame, ignoring
-`global-environment'.
-
-If set to nil, Emacs uses `global-environment' and ignores the
-frame-local environment.
-
-Otherwise, `local-environment-variables' should be a list of variable
-names (represented by Lisp strings) to look up in the frame's
-environment.  The rest will come from `global-environment'.
-
-The frame-local environment is stored in the 'environment frame
-parameter.  See `frame-with-environment'.  */);
-  Vlocal_environment_variables = Qt;
 }
 
 /* arch-tag: 769b8045-1df7-4d2b-8968-e3fb49017f95