diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.in | 2 | ||||
-rw-r--r-- | src/callproc.c | 160 | ||||
-rw-r--r-- | src/termhooks.h | 2 |
3 files changed, 145 insertions, 19 deletions
diff --git a/src/Makefile.in b/src/Makefile.in index f8029d5e246..1054b76ac14 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1078,7 +1078,7 @@ callint.o: callint.c window.h commands.h buffer.h keymap.h \ keyboard.h dispextern.h $(config_h) callproc.o: callproc.c epaths.h buffer.h commands.h $(config_h) \ process.h systty.h syssignal.h charset.h coding.h ccl.h msdos.h \ - composite.h w32.h blockinput.h atimer.h systime.h + composite.h w32.h blockinput.h atimer.h systime.h frame.h termhooks.h casefiddle.o: casefiddle.c syntax.h commands.h buffer.h composite.h \ charset.h keymap.h $(config_h) casetab.o: casetab.c buffer.h $(config_h) diff --git a/src/callproc.c b/src/callproc.c index 47930819c07..35331e4b5dd 100644 --- a/src/callproc.c +++ b/src/callproc.c @@ -84,6 +84,8 @@ extern int errno; #include "syssignal.h" #include "systty.h" #include "blockinput.h" +#include "frame.h" +#include "termhooks.h" #ifdef MSDOS #include "msdos.h" @@ -116,6 +118,7 @@ Lisp_Object Vprocess_environment; #ifdef DOS_NT Lisp_Object Qbuffer_file_type; #endif /* DOS_NT */ +Lisp_Object Qenvironment; /* True iff we are about to fork off a synchronous process or if we are waiting for it. */ @@ -130,6 +133,10 @@ int synch_process_termsig; /* If synch_process_death is zero, 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; + /* Clean up when exiting Fcall_process. On MSDOS, delete the temporary file on any kind of termination. @@ -1264,9 +1271,25 @@ child_setup (in, out, err, new_argv, set_pgrp, current_dir) register Lisp_Object tem; register char **new_env; register int new_length; + Lisp_Object environment = Vprocess_environment; + Lisp_Object local; new_length = 0; - for (tem = Vprocess_environment; + + if (!NILP (Vlocal_environment_variables)) + { + local = get_terminal_param (FRAME_DEVICE (XFRAME (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; CONSP (tem) && STRINGP (XCAR (tem)); tem = XCDR (tem)) new_length++; @@ -1279,8 +1302,42 @@ child_setup (in, out, err, new_argv, set_pgrp, current_dir) if (getenv ("PWD")) *new_env++ = pwd_var; - /* Copy the Vprocess_environment strings into new_env. */ - for (tem = Vprocess_environment; + /* Get the local environment variables first. */ + for (tem = Vlocal_environment_variables; + CONSP (tem) && STRINGP (XCAR (tem)); + tem = XCDR (tem)) + { + char **ep = env; + char *string = egetenv (SDATA (XCAR (tem))); + int ok = 1; + if (string == NULL) + continue; + + /* 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 (ok) + { + if (*q == 0) + /* The string is malformed; might as well drop it. */ + ok = 0; + if (*q != *p) + break; + if (*q == '=') + ok = 0; + p++, q++; + } + } + if (ok) + *new_env++ = string; + } + + /* Copy the environment strings into new_env. */ + for (tem = environment; CONSP (tem) && STRINGP (XCAR (tem)); tem = XCDR (tem)) { @@ -1423,29 +1480,68 @@ relocate_fd (fd, minfd) } static int -getenv_internal (var, varlen, value, valuelen) +getenv_internal (var, varlen, value, valuelen, terminal) char *var; int varlen; char **value; int *valuelen; + Lisp_Object terminal; { Lisp_Object scan; + Lisp_Object environment = Vprocess_environment; + + /* Find the environment in which to search the variable. */ + if (!NILP (terminal)) + { + Lisp_Object local = get_terminal_param (get_device (terminal, 1)); + /* Use Vprocess_environment if there is no local environment. */ + if (!NILP (local)) + environment = local; + } + else if (!NILP (Vlocal_environment_variables)) + { + Lisp_Object local = get_terminal_param (FRAME_DEVICE (XFRAME (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 +#ifdef WINDOWSNT + /* NT environment variables are case insensitive. */ + && ! strnicmp (SDATA (entry), var, varlen) +#else /* not WINDOWSNT */ + && ! bcmp (SDATA (entry), var, varlen) +#endif /* not WINDOWSNT */ + ) + { + environment = local; + break; + } + } + } + } - for (scan = Vprocess_environment; CONSP (scan); scan = XCDR (scan)) + for (scan = environment; CONSP (scan); scan = XCDR (scan)) { Lisp_Object entry; entry = XCAR (scan); if (STRINGP (entry) - && SBYTES (entry) > varlen - && SREF (entry, varlen) == '=' + && SBYTES (entry) > varlen + && SREF (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 */ - ) + ) { *value = (char *) SDATA (entry) + (varlen + 1); *valuelen = SBYTES (entry) - (varlen + 1); @@ -1456,19 +1552,30 @@ getenv_internal (var, varlen, value, valuelen) return 0; } -DEFUN ("getenv-internal", Fgetenv_internal, Sgetenv_internal, 1, 1, 0, +DEFUN ("getenv-internal", Fgetenv_internal, Sgetenv_internal, 1, 2, 0, doc: /* Return the value of environment variable VAR, as a string. -VAR should be a string. Value is nil if VAR is undefined in the environment. -This function consults the variable ``process-environment'' for its value. */) - (var) - Lisp_Object var; +VAR should be a string. Value is nil if VAR is undefined in the +environment. + +If optional parameter TERMINAL is non-nil, then it should be a +terminal id or a frame. If the specified terminal device has its own +set of environment variables, this function will look up VAR in it. + +Otherwise, if `local-environment-variables' specifies that VAR is a +local environment variable, then this function consults the +environment variables belonging to the terminal device of the selected +frame. + +Otherwise, the value of VAR will come from `process-environment'. */) + (var, terminal) + Lisp_Object var, terminal; { char *value; int valuelen; CHECK_STRING (var); if (getenv_internal (SDATA (var), SBYTES (var), - &value, &valuelen)) + &value, &valuelen, terminal)) return make_string (value, valuelen); else return Qnil; @@ -1483,7 +1590,7 @@ egetenv (var) char *value; int valuelen; - if (getenv_internal (var, strlen (var), &value, &valuelen)) + if (getenv_internal (var, strlen (var), &value, &valuelen, Qnil)) return value; else return 0; @@ -1707,6 +1814,23 @@ See `setenv' and `getenv'. */); defsubr (&Sgetenv_internal); #endif defsubr (&Scall_process_region); + + DEFVAR_LISP ("local-environment-variables", &Vlocal_environment_variables, + doc: /* Enable or disable terminal-local environment variables. +If set to t, `getenv', `setenv' and subprocess creation functions use +the environment variables of the emacsclient process that created the +selected frame, ignoring `process-environment'. + +If set to nil, Emacs uses `process-environment' and ignores the client +environment. + +Otherwise, `terminal-local-environment-variables' should be a list of +variable names (represented by Lisp strings) to look up in the client +environment. The rest will come from `process-environment'. */); + Vlocal_environment_variables = Qnil; + + Qenvironment = intern ("environment"); + staticpro (&Qenvironment); } /* arch-tag: 769b8045-1df7-4d2b-8968-e3fb49017f95 diff --git a/src/termhooks.h b/src/termhooks.h index 824cef60351..f12dbadd197 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -595,6 +595,8 @@ extern struct device *device_list; /* Return true if the display device is not suspended. */ #define DEVICE_ACTIVE_P(d) ((d)->type != output_termcap || (d)->display_info.tty->input) +extern Lisp_Object get_terminal_param P_ ((struct device *, Lisp_Object)); + extern struct device *create_device P_ ((void)); extern void delete_device P_ ((struct device *)); |