diff options
| author | Karoly Lorentey | 2005-12-29 01:28:33 +0000 |
|---|---|---|
| committer | Karoly Lorentey | 2005-12-29 01:28:33 +0000 |
| commit | 5990851d423fbd407f2d8cb4eb09b1fdc0b3c44e (patch) | |
| tree | 3576481025a018195a655faa39652bc57f3f2f04 | |
| parent | b2a300dc19a9449c4b8b0138937193ac36b39b1c (diff) | |
| download | emacs-5990851d423fbd407f2d8cb4eb09b1fdc0b3c44e.tar.gz emacs-5990851d423fbd407f2d8cb4eb09b1fdc0b3c44e.zip | |
Fix semantics of let-binding `process-environment'.
* lisp/env.el: Require cl for byte compilation. (For `block' and `return'.)
(read-envvar-name): Update for rename. Include `process-environment'
as well.
(setenv): Update for rename also handle `process-environment'. Update doc.
(getenv): Update doc.
(environment): New function.
(let-environment): New macro.
* lisp/font-lock.el (lisp-font-lock-keywords-2): Add `let-environment'.
* src/callproc.c (Vglobal_environment): New variable, taking over the
previous role of `Vprocess_environment', which is now something else.
(add_env): New function.
(child_setup): Use it.
(child_setup, getenv_internal): Rename Vprocess_environment to
Vglobal_environment. Handle the new Vprocess_environment.
(Fgetenv_internal, egetenv): Update doc.
(set_process_environment): Rename to `set_global_environment'. Rename
Vprocess_environment to Vglobal_environment.
(syms_of_callproc): Rename process-environment to global-environment,
add new process-environment, update docs.
* src/emacs.c (main): Call set_global_environment instead of
set_process_environment.
* fileio.c (Fread_file_name): Update comment.
git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-465
| -rw-r--r-- | lisp/env.el | 191 | ||||
| -rw-r--r-- | lisp/font-lock.el | 2 | ||||
| -rw-r--r-- | src/callproc.c | 251 | ||||
| -rw-r--r-- | src/emacs.c | 6 | ||||
| -rw-r--r-- | src/fileio.c | 2 |
5 files changed, 313 insertions, 139 deletions
diff --git a/lisp/env.el b/lisp/env.el index 378b7f078be..7099a72ca2c 100644 --- a/lisp/env.el +++ b/lisp/env.el | |||
| @@ -36,6 +36,8 @@ | |||
| 36 | 36 | ||
| 37 | ;;; Code: | 37 | ;;; Code: |
| 38 | 38 | ||
| 39 | (eval-when-compile (require 'cl)) | ||
| 40 | |||
| 39 | ;; History list for environment variable names. | 41 | ;; History list for environment variable names. |
| 40 | (defvar read-envvar-name-history nil) | 42 | (defvar read-envvar-name-history nil) |
| 41 | 43 | ||
| @@ -52,8 +54,9 @@ If it is also not t, RET does not exit if it does non-null completion." | |||
| 52 | locale-coding-system t) | 54 | locale-coding-system t) |
| 53 | (substring enventry 0 | 55 | (substring enventry 0 |
| 54 | (string-match "=" enventry))))) | 56 | (string-match "=" enventry))))) |
| 55 | (append (terminal-parameter nil 'environment) | 57 | (append process-environment |
| 56 | process-environment)) | 58 | (terminal-parameter nil 'environment) |
| 59 | global-environment)) | ||
| 57 | nil mustmatch nil 'read-envvar-name-history)) | 60 | nil mustmatch nil 'read-envvar-name-history)) |
| 58 | 61 | ||
| 59 | ;; History list for VALUE argument to setenv. | 62 | ;; History list for VALUE argument to setenv. |
| @@ -89,7 +92,7 @@ Use `$$' to insert a single dollar sign." | |||
| 89 | start (+ (match-beginning 0) 1))))) | 92 | start (+ (match-beginning 0) 1))))) |
| 90 | string)) | 93 | string)) |
| 91 | 94 | ||
| 92 | ;; Fixme: Should `process-environment' be recoded if LC_CTYPE &c is set? | 95 | ;; Fixme: Should the environment be recoded if LC_CTYPE &c is set? |
| 93 | 96 | ||
| 94 | (defun setenv (variable &optional value unset substitute-env-vars terminal) | 97 | (defun setenv (variable &optional value unset substitute-env-vars terminal) |
| 95 | "Set the value of the environment variable named VARIABLE to VALUE. | 98 | "Set the value of the environment variable named VARIABLE to VALUE. |
| @@ -106,15 +109,16 @@ Interactively, the current value (if any) of the variable | |||
| 106 | appears at the front of the history list when you type in the new value. | 109 | appears at the front of the history list when you type in the new value. |
| 107 | Interactively, always replace environment variables in the new value. | 110 | Interactively, always replace environment variables in the new value. |
| 108 | 111 | ||
| 112 | If VARIABLE is set in `process-environment', then this function | ||
| 113 | modifies its value there. Otherwise, this function works by | ||
| 114 | modifying either `global-environment' or the environment | ||
| 115 | belonging to the terminal device of the selected frame, depending | ||
| 116 | on the value of `local-environment-variables'. | ||
| 117 | |||
| 109 | If optional parameter TERMINAL is non-nil, then it should be a | 118 | If optional parameter TERMINAL is non-nil, then it should be a |
| 110 | terminal id or a frame. If the specified terminal device has its own | 119 | terminal id or a frame. If the specified terminal device has its own |
| 111 | set of environment variables, this function will modify VAR in it. | 120 | set of environment variables, this function will modify VAR in it. |
| 112 | 121 | ||
| 113 | Otherwise, this function works by modifying either | ||
| 114 | `process-environment' or the environment belonging to the | ||
| 115 | terminal device of the selected frame, depending on the value of | ||
| 116 | `local-environment-variables'. | ||
| 117 | |||
| 118 | As a special case, setting variable `TZ' calls `set-time-zone-rule' as | 122 | As a special case, setting variable `TZ' calls `set-time-zone-rule' as |
| 119 | a side-effect." | 123 | a side-effect." |
| 120 | (interactive | 124 | (interactive |
| @@ -147,41 +151,55 @@ a side-effect." | |||
| 147 | (setq value (encode-coding-string value locale-coding-system))) | 151 | (setq value (encode-coding-string value locale-coding-system))) |
| 148 | (if (string-match "=" variable) | 152 | (if (string-match "=" variable) |
| 149 | (error "Environment variable name `%s' contains `='" variable)) | 153 | (error "Environment variable name `%s' contains `='" variable)) |
| 150 | (let* ((pattern (concat "\\`" (regexp-quote (concat variable "=")))) | 154 | (let ((pattern (concat "\\`" (regexp-quote variable) "\\(=\\|\\'\\)")) |
| 151 | (case-fold-search nil) | 155 | (case-fold-search nil) |
| 152 | (local-var-p (and (terminal-parameter terminal 'environment) | 156 | (terminal-env (terminal-parameter terminal 'environment)) |
| 153 | (or terminal | 157 | (scan process-environment) |
| 154 | (eq t local-environment-variables) | 158 | found) |
| 155 | (member variable local-environment-variables)))) | ||
| 156 | (scan (if local-var-p | ||
| 157 | (terminal-parameter terminal 'environment) | ||
| 158 | process-environment)) | ||
| 159 | found) | ||
| 160 | (if (string-equal "TZ" variable) | 159 | (if (string-equal "TZ" variable) |
| 161 | (set-time-zone-rule value)) | 160 | (set-time-zone-rule value)) |
| 162 | (while scan | 161 | (block nil |
| 163 | (cond ((string-match pattern (car scan)) | 162 | ;; Look for an existing entry for VARIABLE; try `process-environment' first. |
| 164 | (setq found t) | 163 | (while (and scan (stringp (car scan))) |
| 165 | (if (eq nil value) | 164 | (when (string-match pattern (car scan)) |
| 166 | (if local-var-p | 165 | (if value |
| 167 | (set-terminal-parameter terminal 'environment | 166 | (setcar scan (concat variable "=" value)) |
| 168 | (delq (car scan) | 167 | ;; Leave unset variables in `process-environment', |
| 169 | (terminal-parameter terminal 'environment))) | 168 | ;; otherwise the overridden value in `global-environment' |
| 170 | (setq process-environment (delq (car scan) | 169 | ;; or terminal-env would become unmasked. |
| 171 | process-environment))) | 170 | (setcar scan variable)) |
| 172 | (setcar scan (concat variable "=" value))) | 171 | (return value)) |
| 173 | (setq scan nil))) | 172 | (setq scan (cdr scan))) |
| 174 | (setq scan (cdr scan))) | 173 | |
| 175 | (or found | 174 | ;; Look in the local or global environment, whichever is relevant. |
| 175 | (let ((local-var-p (and terminal-env | ||
| 176 | (or terminal | ||
| 177 | (eq t local-environment-variables) | ||
| 178 | (member variable local-environment-variables))))) | ||
| 179 | (setq scan (if local-var-p | ||
| 180 | terminal-env | ||
| 181 | global-environment)) | ||
| 182 | (while scan | ||
| 183 | (when (string-match pattern (car scan)) | ||
| 184 | (if value | ||
| 185 | (setcar scan (concat variable "=" value)) | ||
| 186 | (if local-var-p | ||
| 187 | (set-terminal-parameter terminal 'environment | ||
| 188 | (delq (car scan) terminal-env)) | ||
| 189 | (setq global-environment (delq (car scan) global-environment))) | ||
| 190 | (return value))) | ||
| 191 | (setq scan (cdr scan))) | ||
| 192 | |||
| 193 | ;; VARIABLE is not in any environment list. | ||
| 176 | (if value | 194 | (if value |
| 177 | (if local-var-p | 195 | (if local-var-p |
| 178 | (set-terminal-parameter nil 'environment | 196 | (set-terminal-parameter nil 'environment |
| 179 | (cons (concat variable "=" value) | 197 | (cons (concat variable "=" value) |
| 180 | (terminal-parameter nil 'environment))) | 198 | terminal-env)) |
| 181 | (setq process-environment | 199 | (setq global-environment |
| 182 | (cons (concat variable "=" value) | 200 | (cons (concat variable "=" value) |
| 183 | process-environment)))))) | 201 | global-environment)))) |
| 184 | value) | 202 | (return value))))) |
| 185 | 203 | ||
| 186 | (defun getenv (variable &optional terminal) | 204 | (defun getenv (variable &optional terminal) |
| 187 | "Get the value of environment variable VARIABLE. | 205 | "Get the value of environment variable VARIABLE. |
| @@ -190,14 +208,14 @@ the environment. Otherwise, value is a string. | |||
| 190 | 208 | ||
| 191 | If optional parameter TERMINAL is non-nil, then it should be a | 209 | If optional parameter TERMINAL is non-nil, then it should be a |
| 192 | terminal id or a frame. If the specified terminal device has its own | 210 | terminal id or a frame. If the specified terminal device has its own |
| 193 | set of environment variables, this function will look up VAR in it. | 211 | set of environment variables, this function will look up VARIABLE in |
| 194 | 212 | it. | |
| 195 | Otherwise, if `local-environment-variables' specifies that VAR is a | ||
| 196 | local environment variable, then this function consults the | ||
| 197 | environment variables belonging to the terminal device of the selected | ||
| 198 | frame. | ||
| 199 | 213 | ||
| 200 | Otherwise, the value of VAR will come from `process-environment'." | 214 | Otherwise, this function searches `process-environment' for VARIABLE. |
| 215 | If it was not found there, then it continues the search in either | ||
| 216 | `global-environment' or the local environment list of the current | ||
| 217 | terminal device, depending on the value of | ||
| 218 | `local-environment-variables'." | ||
| 201 | (interactive (list (read-envvar-name "Get environment variable: " t))) | 219 | (interactive (list (read-envvar-name "Get environment variable: " t))) |
| 202 | (let ((value (getenv-internal (if (multibyte-string-p variable) | 220 | (let ((value (getenv-internal (if (multibyte-string-p variable) |
| 203 | (encode-coding-string | 221 | (encode-coding-string |
| @@ -209,6 +227,93 @@ Otherwise, the value of VAR will come from `process-environment'." | |||
| 209 | (message "%s" (if value value "Not set"))) | 227 | (message "%s" (if value value "Not set"))) |
| 210 | value)) | 228 | value)) |
| 211 | 229 | ||
| 230 | (defun environment () | ||
| 231 | "Return a list of environment variables with their values. | ||
| 232 | Each entry in the list is a string of the form NAME=VALUE. | ||
| 233 | |||
| 234 | The returned list can not be used to change environment | ||
| 235 | variables, only read them. See `setenv' to do that. | ||
| 236 | |||
| 237 | The list is constructed from elements of `process-environment', | ||
| 238 | `global-environment' and the local environment list of the | ||
| 239 | current terminal, as specified by `local-environment-variables'. | ||
| 240 | |||
| 241 | Non-ASCII characters are encoded according to the initial value of | ||
| 242 | `locale-coding-system', i.e. the elements must normally be decoded for use. | ||
| 243 | See `setenv' and `getenv'." | ||
| 244 | (let ((env (cond ((or (not local-environment-variables) | ||
| 245 | (not (terminal-parameter nil 'environment))) | ||
| 246 | (append process-environment global-environment nil)) | ||
| 247 | ((consp local-environment-variables) | ||
| 248 | (let ((e (reverse process-environment))) | ||
| 249 | (dolist (entry local-environment-variables) | ||
| 250 | (setq e (cons (getenv entry) e))) | ||
| 251 | (append (nreverse e) global-environment nil))) | ||
| 252 | (t | ||
| 253 | (append process-environment (terminal-parameter nil 'environment) nil)))) | ||
| 254 | scan seen) | ||
| 255 | ;; Find the first valid entry in env. | ||
| 256 | (while (and env (stringp (car env)) | ||
| 257 | (or (not (string-match "=" (car env))) | ||
| 258 | (member (substring (car env) 0 (string-match "=" (car env))) seen))) | ||
| 259 | (setq seen (cons (car env) seen) | ||
| 260 | env (cdr env))) | ||
| 261 | (setq scan env) | ||
| 262 | (while (and (cdr scan) (stringp (cadr scan))) | ||
| 263 | (let* ((match (string-match "=" (cadr scan))) | ||
| 264 | (name (substring (cadr scan) 0 match))) | ||
| 265 | (cond ((not match) | ||
| 266 | ;; Unset variable. | ||
| 267 | (setq seen (cons name seen)) | ||
| 268 | (setcdr scan (cddr scan))) | ||
| 269 | ((member name seen) | ||
| 270 | ;; Duplicate variable. | ||
| 271 | (setcdr scan (cddr scan))) | ||
| 272 | (t | ||
| 273 | ;; New variable. | ||
| 274 | (setq seen (cons name seen) | ||
| 275 | scan (cdr scan)))))) | ||
| 276 | env)) | ||
| 277 | |||
| 278 | (defmacro let-environment (varlist &rest body) | ||
| 279 | "Evaluate BODY with environment variables set according to VARLIST. | ||
| 280 | The environment variables are then restored to their previous | ||
| 281 | values. | ||
| 282 | The value of the last form in BODY is returned. | ||
| 283 | |||
| 284 | Each element of VARLIST is either a string (which variable is | ||
| 285 | then removed from the environment), or a list (NAME | ||
| 286 | VALUEFORM) (which sets NAME to the value of VALUEFORM, a string). | ||
| 287 | All the VALUEFORMs are evaluated before any variables are set." | ||
| 288 | (declare (indent 2)) | ||
| 289 | (let ((old-env (make-symbol "old-env")) | ||
| 290 | (name (make-symbol "name")) | ||
| 291 | (value (make-symbol "value")) | ||
| 292 | (entry (make-symbol "entry")) | ||
| 293 | (frame (make-symbol "frame"))) | ||
| 294 | `(let ((,frame (selected-frame)) | ||
| 295 | ,old-env) | ||
| 296 | ;; Evaluate VALUEFORMs and replace them in VARLIST with their values. | ||
| 297 | (dolist (,entry ,varlist) | ||
| 298 | (unless (stringp ,entry) | ||
| 299 | (if (cdr (cdr ,entry)) | ||
| 300 | (error "`let-environment' bindings can have only one value-form")) | ||
| 301 | (setcdr ,entry (eval (cadr ,entry))))) | ||
| 302 | ;; Set the variables. | ||
| 303 | (dolist (,entry ,varlist) | ||
| 304 | (let ((,name (if (stringp ,entry) ,entry (car ,entry))) | ||
| 305 | (,value (if (consp ,entry) (cdr ,entry)))) | ||
| 306 | (setq ,old-env (cons (cons ,name (getenv ,name)) ,old-env)) | ||
| 307 | (setenv ,name ,value))) | ||
| 308 | (unwind-protect | ||
| 309 | (progn ,@body) | ||
| 310 | ;; Restore old values. | ||
| 311 | (with-selected-frame (if (frame-live-p ,frame) | ||
| 312 | ,frame | ||
| 313 | (selected-frame)) | ||
| 314 | (dolist (,entry ,old-env) | ||
| 315 | (setenv (car ,entry) (cdr ,entry)))))))) | ||
| 316 | |||
| 212 | (provide 'env) | 317 | (provide 'env) |
| 213 | 318 | ||
| 214 | ;;; arch-tag: b7d6a8f7-bc81-46db-8e39-8d721d4ed0b8 | 319 | ;;; arch-tag: b7d6a8f7-bc81-46db-8e39-8d721d4ed0b8 |
diff --git a/lisp/font-lock.el b/lisp/font-lock.el index 45feee19744..49e576e59db 100644 --- a/lisp/font-lock.el +++ b/lisp/font-lock.el | |||
| @@ -1996,7 +1996,7 @@ This function could be MATCHER in a MATCH-ANCHORED `font-lock-keywords' item." | |||
| 1996 | `(;; Control structures. Emacs Lisp forms. | 1996 | `(;; Control structures. Emacs Lisp forms. |
| 1997 | (,(concat | 1997 | (,(concat |
| 1998 | "(" (regexp-opt | 1998 | "(" (regexp-opt |
| 1999 | '("cond" "if" "while" "while-no-input" "let" "let*" | 1999 | '("cond" "if" "while" "while-no-input" "let" "let*" "let-environment" |
| 2000 | "prog" "progn" "progv" "prog1" "prog2" "prog*" | 2000 | "prog" "progn" "progv" "prog1" "prog2" "prog*" |
| 2001 | "inline" "lambda" "save-restriction" "save-excursion" | 2001 | "inline" "lambda" "save-restriction" "save-excursion" |
| 2002 | "save-window-excursion" "save-selected-window" | 2002 | "save-window-excursion" "save-selected-window" |
diff --git a/src/callproc.c b/src/callproc.c index a8735d51c9b..c13b653775f 100644 --- a/src/callproc.c +++ b/src/callproc.c | |||
| @@ -113,6 +113,7 @@ Lisp_Object Vtemp_file_name_pattern; | |||
| 113 | 113 | ||
| 114 | Lisp_Object Vshell_file_name; | 114 | Lisp_Object Vshell_file_name; |
| 115 | 115 | ||
| 116 | Lisp_Object Vglobal_environment; | ||
| 116 | Lisp_Object Vprocess_environment; | 117 | Lisp_Object Vprocess_environment; |
| 117 | 118 | ||
| 118 | #ifdef DOS_NT | 119 | #ifdef DOS_NT |
| @@ -1165,6 +1166,40 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r | |||
| 1165 | 1166 | ||
| 1166 | static int relocate_fd (); | 1167 | static int relocate_fd (); |
| 1167 | 1168 | ||
| 1169 | static char ** | ||
| 1170 | add_env (char **env, char **new_env, char *string) | ||
| 1171 | { | ||
| 1172 | char **ep; | ||
| 1173 | int ok = 1; | ||
| 1174 | if (string == NULL) | ||
| 1175 | return new_env; | ||
| 1176 | |||
| 1177 | /* See if this string duplicates any string already in the env. | ||
| 1178 | If so, don't put it in. | ||
| 1179 | When an env var has multiple definitions, | ||
| 1180 | we keep the definition that comes first in process-environment. */ | ||
| 1181 | for (ep = env; ok && ep != new_env; ep++) | ||
| 1182 | { | ||
| 1183 | char *p = *ep, *q = string; | ||
| 1184 | while (ok) | ||
| 1185 | { | ||
| 1186 | if (*q != *p) | ||
| 1187 | break; | ||
| 1188 | if (*q == 0) | ||
| 1189 | /* The string is a lone variable name; keep it for now, we | ||
| 1190 | will remove it later. It is a placeholder for a | ||
| 1191 | variable that is not to be included in the environment. */ | ||
| 1192 | break; | ||
| 1193 | if (*q == '=') | ||
| 1194 | ok = 0; | ||
| 1195 | p++, q++; | ||
| 1196 | } | ||
| 1197 | } | ||
| 1198 | if (ok) | ||
| 1199 | *new_env++ = string; | ||
| 1200 | return new_env; | ||
| 1201 | } | ||
| 1202 | |||
| 1168 | /* This is the last thing run in a newly forked inferior | 1203 | /* This is the last thing run in a newly forked inferior |
| 1169 | either synchronous or asynchronous. | 1204 | either synchronous or asynchronous. |
| 1170 | Copy descriptors IN, OUT and ERR as descriptors 0, 1 and 2. | 1205 | Copy descriptors IN, OUT and ERR as descriptors 0, 1 and 2. |
| @@ -1266,16 +1301,22 @@ child_setup (in, out, err, new_argv, set_pgrp, current_dir) | |||
| 1266 | temp[--i] = 0; | 1301 | temp[--i] = 0; |
| 1267 | } | 1302 | } |
| 1268 | 1303 | ||
| 1269 | /* Set `env' to a vector of the strings in Vprocess_environment. */ | 1304 | /* Set `env' to a vector of the strings in the environment. */ |
| 1270 | { | 1305 | { |
| 1271 | register Lisp_Object tem; | 1306 | register Lisp_Object tem; |
| 1272 | register char **new_env; | 1307 | register char **new_env; |
| 1308 | char **p, **q; | ||
| 1273 | register int new_length; | 1309 | register int new_length; |
| 1274 | Lisp_Object environment = Vprocess_environment; | 1310 | Lisp_Object environment = Vglobal_environment; |
| 1275 | Lisp_Object local; | 1311 | Lisp_Object local; |
| 1276 | 1312 | ||
| 1277 | new_length = 0; | 1313 | new_length = 0; |
| 1278 | 1314 | ||
| 1315 | for (tem = Vprocess_environment; | ||
| 1316 | CONSP (tem) && STRINGP (XCAR (tem)); | ||
| 1317 | tem = XCDR (tem)) | ||
| 1318 | new_length++; | ||
| 1319 | |||
| 1279 | if (!NILP (Vlocal_environment_variables)) | 1320 | if (!NILP (Vlocal_environment_variables)) |
| 1280 | { | 1321 | { |
| 1281 | local = get_terminal_param (FRAME_DEVICE (XFRAME (selected_frame)), | 1322 | local = get_terminal_param (FRAME_DEVICE (XFRAME (selected_frame)), |
| @@ -1301,71 +1342,38 @@ child_setup (in, out, err, new_argv, set_pgrp, current_dir) | |||
| 1301 | but with corrected value. */ | 1342 | but with corrected value. */ |
| 1302 | if (getenv ("PWD")) | 1343 | if (getenv ("PWD")) |
| 1303 | *new_env++ = pwd_var; | 1344 | *new_env++ = pwd_var; |
| 1345 | |||
| 1346 | /* Overrides. */ | ||
| 1347 | for (tem = Vprocess_environment; | ||
| 1348 | CONSP (tem) && STRINGP (XCAR (tem)); | ||
| 1349 | tem = XCDR (tem)) | ||
| 1350 | new_env = add_env (env, new_env, SDATA (XCAR (tem))); | ||
| 1304 | 1351 | ||
| 1305 | /* Get the local environment variables first. */ | 1352 | /* Local part of environment, if Vlocal_environment_variables is a list. */ |
| 1306 | for (tem = Vlocal_environment_variables; | 1353 | for (tem = Vlocal_environment_variables; |
| 1307 | CONSP (tem) && STRINGP (XCAR (tem)); | 1354 | CONSP (tem) && STRINGP (XCAR (tem)); |
| 1308 | tem = XCDR (tem)) | 1355 | tem = XCDR (tem)) |
| 1309 | { | 1356 | new_env = add_env (env, new_env, egetenv (SDATA (XCAR (tem)))); |
| 1310 | char **ep = env; | ||
| 1311 | char *string = egetenv (SDATA (XCAR (tem))); | ||
| 1312 | int ok = 1; | ||
| 1313 | if (string == NULL) | ||
| 1314 | continue; | ||
| 1315 | |||
| 1316 | /* See if this string duplicates any string already in the env. | ||
| 1317 | If so, don't put it in. | ||
| 1318 | When an env var has multiple definitions, | ||
| 1319 | we keep the definition that comes first in process-environment. */ | ||
| 1320 | for (; ep != new_env; ep++) | ||
| 1321 | { | ||
| 1322 | char *p = *ep, *q = string; | ||
| 1323 | while (ok) | ||
| 1324 | { | ||
| 1325 | if (*q == 0) | ||
| 1326 | /* The string is malformed; might as well drop it. */ | ||
| 1327 | ok = 0; | ||
| 1328 | if (*q != *p) | ||
| 1329 | break; | ||
| 1330 | if (*q == '=') | ||
| 1331 | ok = 0; | ||
| 1332 | p++, q++; | ||
| 1333 | } | ||
| 1334 | } | ||
| 1335 | if (ok) | ||
| 1336 | *new_env++ = string; | ||
| 1337 | } | ||
| 1338 | 1357 | ||
| 1339 | /* Copy the environment strings into new_env. */ | 1358 | /* The rest of the environment (either Vglobal_environment or the |
| 1359 | 'environment terminal parameter). */ | ||
| 1340 | for (tem = environment; | 1360 | for (tem = environment; |
| 1341 | CONSP (tem) && STRINGP (XCAR (tem)); | 1361 | CONSP (tem) && STRINGP (XCAR (tem)); |
| 1342 | tem = XCDR (tem)) | 1362 | tem = XCDR (tem)) |
| 1363 | new_env = add_env (env, new_env, SDATA (XCAR (tem))); | ||
| 1364 | |||
| 1365 | *new_env = 0; | ||
| 1366 | |||
| 1367 | /* Remove variable names without values. */ | ||
| 1368 | p = q = env; | ||
| 1369 | while (*p != 0) | ||
| 1343 | { | 1370 | { |
| 1344 | char **ep = env; | 1371 | while (*q != 0 && strchr (*q, '=') == NULL) |
| 1345 | char *string = (char *) SDATA (XCAR (tem)); | 1372 | *q++; |
| 1346 | /* See if this string duplicates any string already in the env. | 1373 | *p = *q++; |
| 1347 | If so, don't put it in. | 1374 | if (*p != 0) |
| 1348 | When an env var has multiple definitions, | 1375 | p++; |
| 1349 | we keep the definition that comes first in process-environment. */ | ||
| 1350 | for (; ep != new_env; ep++) | ||
| 1351 | { | ||
| 1352 | char *p = *ep, *q = string; | ||
| 1353 | while (1) | ||
| 1354 | { | ||
| 1355 | if (*q == 0) | ||
| 1356 | /* The string is malformed; might as well drop it. */ | ||
| 1357 | goto duplicate; | ||
| 1358 | if (*q != *p) | ||
| 1359 | break; | ||
| 1360 | if (*q == '=') | ||
| 1361 | goto duplicate; | ||
| 1362 | p++, q++; | ||
| 1363 | } | ||
| 1364 | } | ||
| 1365 | *new_env++ = string; | ||
| 1366 | duplicate: ; | ||
| 1367 | } | 1376 | } |
| 1368 | *new_env = 0; | ||
| 1369 | } | 1377 | } |
| 1370 | #ifdef WINDOWSNT | 1378 | #ifdef WINDOWSNT |
| 1371 | prepare_standard_handles (in, out, err, handles); | 1379 | prepare_standard_handles (in, out, err, handles); |
| @@ -1488,13 +1496,42 @@ getenv_internal (var, varlen, value, valuelen, terminal) | |||
| 1488 | Lisp_Object terminal; | 1496 | Lisp_Object terminal; |
| 1489 | { | 1497 | { |
| 1490 | Lisp_Object scan; | 1498 | Lisp_Object scan; |
| 1491 | Lisp_Object environment = Vprocess_environment; | 1499 | Lisp_Object environment = Vglobal_environment; |
| 1500 | |||
| 1501 | /* Try to find VAR in Vprocess_environment first. */ | ||
| 1502 | for (scan = Vprocess_environment; CONSP (scan); scan = XCDR (scan)) | ||
| 1503 | { | ||
| 1504 | Lisp_Object entry = XCAR (scan); | ||
| 1505 | if (STRINGP (entry) | ||
| 1506 | && SBYTES (entry) >= varlen | ||
| 1507 | #ifdef WINDOWSNT | ||
| 1508 | /* NT environment variables are case insensitive. */ | ||
| 1509 | && ! strnicmp (SDATA (entry), var, varlen) | ||
| 1510 | #else /* not WINDOWSNT */ | ||
| 1511 | && ! bcmp (SDATA (entry), var, varlen) | ||
| 1512 | #endif /* not WINDOWSNT */ | ||
| 1513 | ) | ||
| 1514 | { | ||
| 1515 | if (SBYTES (entry) > varlen && SREF (entry, varlen) == '=') | ||
| 1516 | { | ||
| 1517 | *value = (char *) SDATA (entry) + (varlen + 1); | ||
| 1518 | *valuelen = SBYTES (entry) - (varlen + 1); | ||
| 1519 | return 1; | ||
| 1520 | } | ||
| 1521 | else if (SBYTES (entry) == varlen) | ||
| 1522 | { | ||
| 1523 | /* Lone variable names in Vprocess_environment mean that | ||
| 1524 | variable should be removed from the environment. */ | ||
| 1525 | return 0; | ||
| 1526 | } | ||
| 1527 | } | ||
| 1528 | } | ||
| 1492 | 1529 | ||
| 1493 | /* Find the environment in which to search the variable. */ | 1530 | /* Find the environment in which to search the variable. */ |
| 1494 | if (!NILP (terminal)) | 1531 | if (!NILP (terminal)) |
| 1495 | { | 1532 | { |
| 1496 | Lisp_Object local = get_terminal_param (get_device (terminal, 1), Qenvironment); | 1533 | Lisp_Object local = get_terminal_param (get_device (terminal, 1), Qenvironment); |
| 1497 | /* Use Vprocess_environment if there is no local environment. */ | 1534 | /* Use Vglobal_environment if there is no local environment. */ |
| 1498 | if (!NILP (local)) | 1535 | if (!NILP (local)) |
| 1499 | environment = local; | 1536 | environment = local; |
| 1500 | } | 1537 | } |
| @@ -1553,36 +1590,36 @@ getenv_internal (var, varlen, value, valuelen, terminal) | |||
| 1553 | } | 1590 | } |
| 1554 | 1591 | ||
| 1555 | DEFUN ("getenv-internal", Fgetenv_internal, Sgetenv_internal, 1, 2, 0, | 1592 | DEFUN ("getenv-internal", Fgetenv_internal, Sgetenv_internal, 1, 2, 0, |
| 1556 | doc: /* Return the value of environment variable VAR, as a string. | 1593 | doc: /* Get the value of environment variable VARIABLE. |
| 1557 | VAR should be a string. Value is nil if VAR is undefined in the | 1594 | VARIABLE should be a string. Value is nil if VARIABLE is undefined in |
| 1558 | environment. | 1595 | the environment. Otherwise, value is a string. |
| 1559 | 1596 | ||
| 1560 | If optional parameter TERMINAL is non-nil, then it should be a | 1597 | If optional parameter TERMINAL is non-nil, then it should be a |
| 1561 | terminal id or a frame. If the specified terminal device has its own | 1598 | terminal id or a frame. If the specified terminal device has its own |
| 1562 | set of environment variables, this function will look up VAR in it. | 1599 | set of environment variables, this function will look up VARIABLE in |
| 1563 | 1600 | it. | |
| 1564 | Otherwise, if `local-environment-variables' specifies that VAR is a | 1601 | |
| 1565 | local environment variable, then this function consults the | 1602 | Otherwise, this function searches `process-environment' for VARIABLE. |
| 1566 | environment variables belonging to the terminal device of the selected | 1603 | If it was not found there, then it continues the search in either |
| 1567 | frame. | 1604 | `global-environment' or the local environment list of the current |
| 1568 | 1605 | terminal device, depending on the value of | |
| 1569 | Otherwise, the value of VAR will come from `process-environment'. */) | 1606 | `local-environment-variables'. */) |
| 1570 | (var, terminal) | 1607 | (variable, terminal) |
| 1571 | Lisp_Object var, terminal; | 1608 | Lisp_Object variable, terminal; |
| 1572 | { | 1609 | { |
| 1573 | char *value; | 1610 | char *value; |
| 1574 | int valuelen; | 1611 | int valuelen; |
| 1575 | 1612 | ||
| 1576 | CHECK_STRING (var); | 1613 | CHECK_STRING (variable); |
| 1577 | if (getenv_internal (SDATA (var), SBYTES (var), | 1614 | if (getenv_internal (SDATA (variable), SBYTES (variable), |
| 1578 | &value, &valuelen, terminal)) | 1615 | &value, &valuelen, terminal)) |
| 1579 | return make_string (value, valuelen); | 1616 | return make_string (value, valuelen); |
| 1580 | else | 1617 | else |
| 1581 | return Qnil; | 1618 | return Qnil; |
| 1582 | } | 1619 | } |
| 1583 | 1620 | ||
| 1584 | /* A version of getenv that consults process_environment, easily | 1621 | /* A version of getenv that consults the Lisp environment lists, |
| 1585 | callable from C. */ | 1622 | easily callable from C. */ |
| 1586 | char * | 1623 | char * |
| 1587 | egetenv (var) | 1624 | egetenv (var) |
| 1588 | char *var; | 1625 | char *var; |
| @@ -1730,17 +1767,17 @@ init_callproc () | |||
| 1730 | } | 1767 | } |
| 1731 | 1768 | ||
| 1732 | void | 1769 | void |
| 1733 | set_process_environment () | 1770 | set_global_environment () |
| 1734 | { | 1771 | { |
| 1735 | register char **envp; | 1772 | register char **envp; |
| 1736 | 1773 | ||
| 1737 | Vprocess_environment = Qnil; | 1774 | Vglobal_environment = Qnil; |
| 1738 | #ifndef CANNOT_DUMP | 1775 | #ifndef CANNOT_DUMP |
| 1739 | if (initialized) | 1776 | if (initialized) |
| 1740 | #endif | 1777 | #endif |
| 1741 | for (envp = environ; *envp; envp++) | 1778 | for (envp = environ; *envp; envp++) |
| 1742 | Vprocess_environment = Fcons (build_string (*envp), | 1779 | Vglobal_environment = Fcons (build_string (*envp), |
| 1743 | Vprocess_environment); | 1780 | Vglobal_environment); |
| 1744 | } | 1781 | } |
| 1745 | 1782 | ||
| 1746 | void | 1783 | void |
| @@ -1798,17 +1835,49 @@ If this variable is nil, then Emacs is unable to use a shared directory. */); | |||
| 1798 | This is used by `call-process-region'. */); | 1835 | This is used by `call-process-region'. */); |
| 1799 | /* This variable is initialized in init_callproc. */ | 1836 | /* This variable is initialized in init_callproc. */ |
| 1800 | 1837 | ||
| 1801 | DEFVAR_LISP ("process-environment", &Vprocess_environment, | 1838 | DEFVAR_LISP ("global-environment", &Vglobal_environment, |
| 1802 | doc: /* List of environment variables for subprocesses to inherit. | 1839 | doc: /* Global list of environment variables for subprocesses to inherit. |
| 1803 | Each element should be a string of the form ENVVARNAME=VALUE. | 1840 | Each element should be a string of the form ENVVARNAME=VALUE. |
| 1841 | |||
| 1842 | The environment which Emacs inherits is placed in this variable when | ||
| 1843 | Emacs starts. | ||
| 1844 | |||
| 1845 | Some terminal devices may have their own local list of environment | ||
| 1846 | variables in their 'environment parameter, which may override this | ||
| 1847 | global list; see `local-environment-variables'. See | ||
| 1848 | `process-environment' for a way to modify an environment variable on | ||
| 1849 | all terminals. | ||
| 1850 | |||
| 1804 | If multiple entries define the same variable, the first one always | 1851 | If multiple entries define the same variable, the first one always |
| 1805 | takes precedence. | 1852 | takes precedence. |
| 1806 | The environment which Emacs inherits is placed in this variable | 1853 | |
| 1807 | when Emacs starts. | ||
| 1808 | Non-ASCII characters are encoded according to the initial value of | 1854 | Non-ASCII characters are encoded according to the initial value of |
| 1809 | `locale-coding-system', i.e. the elements must normally be decoded for use. | 1855 | `locale-coding-system', i.e. the elements must normally be decoded for use. |
| 1810 | See `setenv' and `getenv'. */); | 1856 | See `setenv' and `getenv'. */); |
| 1811 | 1857 | ||
| 1858 | DEFVAR_LISP ("process-environment", &Vprocess_environment, | ||
| 1859 | doc: /* List of overridden environment variables for subprocesses to inherit. | ||
| 1860 | Each element should be a string of the form ENVVARNAME=VALUE. | ||
| 1861 | |||
| 1862 | Entries in this list take precedence to those in `global-environment' | ||
| 1863 | or the terminal environment. (See `local-environment-variables' for | ||
| 1864 | an explanation of the terminal-local environment.) Therefore, | ||
| 1865 | let-binding `process-environment' is an easy way to temporarily change | ||
| 1866 | the value of an environment variable, irrespective of where it comes | ||
| 1867 | from. To use `process-environment' to remove an environment variable, | ||
| 1868 | include only its name in the list, without "=VALUE". | ||
| 1869 | |||
| 1870 | This variable is set to nil when Emacs starts. | ||
| 1871 | |||
| 1872 | If multiple entries define the same variable, the first one always | ||
| 1873 | takes precedence. | ||
| 1874 | |||
| 1875 | Non-ASCII characters are encoded according to the initial value of | ||
| 1876 | `locale-coding-system', i.e. the elements must normally be decoded for | ||
| 1877 | use. | ||
| 1878 | |||
| 1879 | See `setenv' and `getenv'. */); | ||
| 1880 | |||
| 1812 | #ifndef VMS | 1881 | #ifndef VMS |
| 1813 | defsubr (&Scall_process); | 1882 | defsubr (&Scall_process); |
| 1814 | defsubr (&Sgetenv_internal); | 1883 | defsubr (&Sgetenv_internal); |
| @@ -1818,15 +1887,15 @@ See `setenv' and `getenv'. */); | |||
| 1818 | DEFVAR_LISP ("local-environment-variables", &Vlocal_environment_variables, | 1887 | DEFVAR_LISP ("local-environment-variables", &Vlocal_environment_variables, |
| 1819 | doc: /* Enable or disable terminal-local environment variables. | 1888 | doc: /* Enable or disable terminal-local environment variables. |
| 1820 | If set to t, `getenv', `setenv' and subprocess creation functions use | 1889 | If set to t, `getenv', `setenv' and subprocess creation functions use |
| 1821 | the environment variables of the emacsclient process that created the | 1890 | the local environment of the terminal device of the selected frame, |
| 1822 | selected frame, ignoring `process-environment'. | 1891 | ignoring `global-environment'. |
| 1823 | 1892 | ||
| 1824 | If set to nil, Emacs uses `process-environment' and ignores the client | 1893 | If set to nil, Emacs uses `global-environment' and ignores the |
| 1825 | environment. | 1894 | terminal environment. |
| 1826 | 1895 | ||
| 1827 | Otherwise, `terminal-local-environment-variables' should be a list of | 1896 | Otherwise, `local-environment-variables' should be a list of variable |
| 1828 | variable names (represented by Lisp strings) to look up in the client | 1897 | names (represented by Lisp strings) to look up in the terminal's |
| 1829 | environment. The rest will come from `process-environment'. */); | 1898 | environment. The rest will come from `global-environment'. */); |
| 1830 | Vlocal_environment_variables = Qnil; | 1899 | Vlocal_environment_variables = Qnil; |
| 1831 | 1900 | ||
| 1832 | Qenvironment = intern ("environment"); | 1901 | Qenvironment = intern ("environment"); |
diff --git a/src/emacs.c b/src/emacs.c index 28b5f374ccd..142da86df95 100644 --- a/src/emacs.c +++ b/src/emacs.c | |||
| @@ -1515,10 +1515,10 @@ main (argc, argv | |||
| 1515 | /* egetenv is a pretty low-level facility, which may get called in | 1515 | /* egetenv is a pretty low-level facility, which may get called in |
| 1516 | many circumstances; it seems flimsy to put off initializing it | 1516 | many circumstances; it seems flimsy to put off initializing it |
| 1517 | until calling init_callproc. */ | 1517 | until calling init_callproc. */ |
| 1518 | set_process_environment (); | 1518 | set_global_environment (); |
| 1519 | /* AIX crashes are reported in system versions 3.2.3 and 3.2.4 | 1519 | /* AIX crashes are reported in system versions 3.2.3 and 3.2.4 |
| 1520 | if this is not done. Do it after set_process_environment so that we | 1520 | if this is not done. Do it after set_global_environment so that we |
| 1521 | don't pollute Vprocess_environment. */ | 1521 | don't pollute Vglobal_environment. */ |
| 1522 | /* Setting LANG here will defeat the startup locale processing... */ | 1522 | /* Setting LANG here will defeat the startup locale processing... */ |
| 1523 | #ifdef AIX3_2 | 1523 | #ifdef AIX3_2 |
| 1524 | putenv ("LANG=C"); | 1524 | putenv ("LANG=C"); |
diff --git a/src/fileio.c b/src/fileio.c index 4e9ac9541c3..add62fe5426 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -6335,7 +6335,7 @@ and `read-file-name-function'. */) | |||
| 6335 | /* If dir starts with user's homedir, change that to ~. */ | 6335 | /* If dir starts with user's homedir, change that to ~. */ |
| 6336 | homedir = (char *) egetenv ("HOME"); | 6336 | homedir = (char *) egetenv ("HOME"); |
| 6337 | #ifdef DOS_NT | 6337 | #ifdef DOS_NT |
| 6338 | /* homedir can be NULL in temacs, since Vprocess_environment is not | 6338 | /* homedir can be NULL in temacs, since Vglobal_environment is not |
| 6339 | yet set up. We shouldn't crash in that case. */ | 6339 | yet set up. We shouldn't crash in that case. */ |
| 6340 | if (homedir != 0) | 6340 | if (homedir != 0) |
| 6341 | { | 6341 | { |