diff options
| author | Karoly Lorentey | 2006-05-26 17:37:25 +0000 |
|---|---|---|
| committer | Karoly Lorentey | 2006-05-26 17:37:25 +0000 |
| commit | a13f8f50d4cc544d3bbfa78568e82ce09e68bded (patch) | |
| tree | 9b8e8ddb508e47766875a99c7f1a97655fa11f22 /lisp | |
| parent | 16b555334ab54bd28c46edfed569e203632db228 (diff) | |
| download | emacs-a13f8f50d4cc544d3bbfa78568e82ce09e68bded.tar.gz emacs-a13f8f50d4cc544d3bbfa78568e82ce09e68bded.zip | |
Rework environment variable support. (Reported by Kalle Olavi Niemitalo and Noah Friedman.)
* src/callproc.c (Vglobal_environment, Vlocal_environment_variables): Remove.
(getenv_internal, child_setup): Don't look at global-environment or
local-environment-variables.
(Fgetenv_internal): Update docs.
(set_initial_environment): Rename from set_global_environment. Store
Emacs environment in initial frame parameter.
(syms_of_callproc): Remove obsolete defvars. Update docs.
* lisp/env.el (read-envvar-name): Remove reference to global-environment.
(setenv-internal): New function.
(setenv): Use it. Always set process-environment. Update docs.
(getenv): Update docs.
(environment): Rewrite for the new environment design. Update docs.
* lisp/frame.el (frame-initialize): Copy the environment from the initial frame.
* src/emacs.c (main): Call set_initial_environment, not set_global_environment.
git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-569
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/env.el | 193 | ||||
| -rw-r--r-- | lisp/frame.el | 3 |
2 files changed, 91 insertions, 105 deletions
diff --git a/lisp/env.el b/lisp/env.el index d0c2208fc6f..96ff1f37c3a 100644 --- a/lisp/env.el +++ b/lisp/env.el | |||
| @@ -55,8 +55,7 @@ If it is also not t, RET does not exit if it does non-null completion." | |||
| 55 | (substring enventry 0 | 55 | (substring enventry 0 |
| 56 | (string-match "=" enventry))))) | 56 | (string-match "=" enventry))))) |
| 57 | (append process-environment | 57 | (append process-environment |
| 58 | (frame-parameter (frame-with-environment) 'environment) | 58 | (frame-parameter (frame-with-environment) 'environment))) |
| 59 | global-environment)) | ||
| 60 | nil mustmatch nil 'read-envvar-name-history)) | 59 | nil mustmatch nil 'read-envvar-name-history)) |
| 61 | 60 | ||
| 62 | ;; History list for VALUE argument to setenv. | 61 | ;; History list for VALUE argument to setenv. |
| @@ -92,6 +91,40 @@ Use `$$' to insert a single dollar sign." | |||
| 92 | start (+ (match-beginning 0) 1))))) | 91 | start (+ (match-beginning 0) 1))))) |
| 93 | string)) | 92 | string)) |
| 94 | 93 | ||
| 94 | |||
| 95 | (defun setenv-internal (env variable value keep-empty) | ||
| 96 | "Set VARIABLE to VALUE in ENV, adding empty entries if KEEP-EMPTY. | ||
| 97 | Changes ENV by side-effect, and returns its new value." | ||
| 98 | (let ((pattern (concat "\\`" (regexp-quote variable) "\\(=\\|\\'\\)")) | ||
| 99 | (case-fold-search nil) | ||
| 100 | (scan env) | ||
| 101 | prev found) | ||
| 102 | ;; Handle deletions from the beginning of the list specially. | ||
| 103 | (if (and (null value) | ||
| 104 | (not keep-empty) | ||
| 105 | env | ||
| 106 | (stringp (car env)) | ||
| 107 | (string-match pattern (car env))) | ||
| 108 | (cdr env) | ||
| 109 | ;; Try to find existing entry for VARIABLE in ENV. | ||
| 110 | (while (and scan (stringp (car scan))) | ||
| 111 | (when (string-match pattern (car scan)) | ||
| 112 | (if value | ||
| 113 | (setcar scan (concat variable "=" value)) | ||
| 114 | (if keep-empty | ||
| 115 | (setcar scan variable) | ||
| 116 | (setcdr prev (cdr scan)))) | ||
| 117 | (setq found t | ||
| 118 | scan nil)) | ||
| 119 | (setq prev scan | ||
| 120 | scan (cdr scan))) | ||
| 121 | (if (and (not found) (or value keep-empty)) | ||
| 122 | (cons (if value | ||
| 123 | (concat variable "=" value) | ||
| 124 | variable) | ||
| 125 | env) | ||
| 126 | env)))) | ||
| 127 | |||
| 95 | ;; Fixme: Should the environment be recoded if LC_CTYPE &c is set? | 128 | ;; Fixme: Should the environment be recoded if LC_CTYPE &c is set? |
| 96 | 129 | ||
| 97 | (defun setenv (variable &optional value substitute-env-vars frame) | 130 | (defun setenv (variable &optional value substitute-env-vars frame) |
| @@ -105,26 +138,23 @@ the front of the history list when you type in the new value. | |||
| 105 | This function always replaces environment variables in the new | 138 | This function always replaces environment variables in the new |
| 106 | value when called interactively. | 139 | value when called interactively. |
| 107 | 140 | ||
| 108 | If VARIABLE is set in `process-environment', then this function | ||
| 109 | modifies its value there. Otherwise, this function works by | ||
| 110 | modifying either `global-environment' or the environment | ||
| 111 | belonging to the selected frame, depending on the value of | ||
| 112 | `local-environment-variables'. | ||
| 113 | |||
| 114 | SUBSTITUTE-ENV-VARS, if non-nil, means to substitute environment | 141 | SUBSTITUTE-ENV-VARS, if non-nil, means to substitute environment |
| 115 | variables in VALUE with `substitute-env-vars', which see. | 142 | variables in VALUE with `substitute-env-vars', which see. |
| 116 | This is normally used only for interactive calls. | 143 | This is normally used only for interactive calls. |
| 117 | 144 | ||
| 145 | If optional parameter FRAME is non-nil, this function modifies | ||
| 146 | only the frame-local value of VARIABLE on FRAME, ignoring | ||
| 147 | `process-environment'. Note that frames on the same terminal | ||
| 148 | device usually share their environment, so calling `setenv' on | ||
| 149 | one of them affects the others as well. | ||
| 150 | |||
| 151 | If FRAME is nil, `setenv' changes the global value of VARIABLE by | ||
| 152 | modifying `process-environment'. Note that the global value | ||
| 153 | overrides any frame-local values. | ||
| 154 | |||
| 118 | The return value is the new value of VARIABLE, or nil if | 155 | The return value is the new value of VARIABLE, or nil if |
| 119 | it was removed from the environment. | 156 | it was removed from the environment. |
| 120 | 157 | ||
| 121 | If optional parameter FRAME is non-nil, then it should be a a | ||
| 122 | frame. If the specified frame has its own set of environment | ||
| 123 | variables, this function will modify VARIABLE in it. Note that | ||
| 124 | frames on the same terminal device usually share their | ||
| 125 | environment, so calling `setenv' on one of them affects the | ||
| 126 | others as well. | ||
| 127 | |||
| 128 | As a special case, setting variable `TZ' calls `set-time-zone-rule' as | 158 | As a special case, setting variable `TZ' calls `set-time-zone-rule' as |
| 129 | a side-effect." | 159 | a side-effect." |
| 130 | (interactive | 160 | (interactive |
| @@ -155,57 +185,16 @@ a side-effect." | |||
| 155 | (setq value (encode-coding-string value locale-coding-system))) | 185 | (setq value (encode-coding-string value locale-coding-system))) |
| 156 | (if (string-match "=" variable) | 186 | (if (string-match "=" variable) |
| 157 | (error "Environment variable name `%s' contains `='" variable)) | 187 | (error "Environment variable name `%s' contains `='" variable)) |
| 158 | (let ((pattern (concat "\\`" (regexp-quote variable) "\\(=\\|\\'\\)")) | 188 | (if (string-equal "TZ" variable) |
| 159 | (case-fold-search nil) | 189 | (set-time-zone-rule value)) |
| 160 | (frame-env (frame-parameter (frame-with-environment frame) 'environment)) | 190 | (if (null frame) |
| 161 | (frame-forced (not frame)) | 191 | (setq process-environment (setenv-internal process-environment |
| 162 | (scan process-environment) | 192 | variable value t)) |
| 163 | found) | ||
| 164 | (setq frame (frame-with-environment frame)) | 193 | (setq frame (frame-with-environment frame)) |
| 165 | (if (string-equal "TZ" variable) | 194 | (set-frame-parameter frame 'environment |
| 166 | (set-time-zone-rule value)) | 195 | (setenv-internal (frame-parameter frame 'environment) |
| 167 | (block nil | 196 | variable value nil))) |
| 168 | ;; Look for an existing entry for VARIABLE; try `process-environment' first. | 197 | value) |
| 169 | (while (and scan (stringp (car scan))) | ||
| 170 | (when (string-match pattern (car scan)) | ||
| 171 | (if value | ||
| 172 | (setcar scan (concat variable "=" value)) | ||
| 173 | ;; Leave unset variables in `process-environment', | ||
| 174 | ;; otherwise the overridden value in `global-environment' | ||
| 175 | ;; or frame-env would become unmasked. | ||
| 176 | (setcar scan variable)) | ||
| 177 | (return value)) | ||
| 178 | (setq scan (cdr scan))) | ||
| 179 | |||
| 180 | ;; Look in the local or global environment, whichever is relevant. | ||
| 181 | (let ((local-var-p (and frame-env | ||
| 182 | (or frame-forced | ||
| 183 | (eq t local-environment-variables) | ||
| 184 | (member variable local-environment-variables))))) | ||
| 185 | (setq scan (if local-var-p | ||
| 186 | frame-env | ||
| 187 | global-environment)) | ||
| 188 | (while scan | ||
| 189 | (when (string-match pattern (car scan)) | ||
| 190 | (if value | ||
| 191 | (setcar scan (concat variable "=" value)) | ||
| 192 | (if local-var-p | ||
| 193 | (set-frame-parameter frame 'environment | ||
| 194 | (delq (car scan) frame-env)) | ||
| 195 | (setq global-environment (delq (car scan) global-environment)))) | ||
| 196 | (return value)) | ||
| 197 | (setq scan (cdr scan))) | ||
| 198 | |||
| 199 | ;; VARIABLE is not in any environment list. | ||
| 200 | (if value | ||
| 201 | (if local-var-p | ||
| 202 | (set-frame-parameter frame 'environment | ||
| 203 | (cons (concat variable "=" value) | ||
| 204 | frame-env)) | ||
| 205 | (setq global-environment | ||
| 206 | (cons (concat variable "=" value) | ||
| 207 | global-environment)))) | ||
| 208 | (return value))))) | ||
| 209 | 198 | ||
| 210 | (defun getenv (variable &optional frame) | 199 | (defun getenv (variable &optional frame) |
| 211 | "Get the value of environment variable VARIABLE. | 200 | "Get the value of environment variable VARIABLE. |
| @@ -213,14 +202,12 @@ VARIABLE should be a string. Value is nil if VARIABLE is undefined in | |||
| 213 | the environment. Otherwise, value is a string. | 202 | the environment. Otherwise, value is a string. |
| 214 | 203 | ||
| 215 | If optional parameter FRAME is non-nil, then it should be a | 204 | If optional parameter FRAME is non-nil, then it should be a |
| 216 | frame. If that frame has its own set of environment variables, | 205 | frame. This function will look up VARIABLE in its 'environment |
| 217 | this function will look up VARIABLE in there. | 206 | parameter. |
| 218 | 207 | ||
| 219 | Otherwise, this function searches `process-environment' for | 208 | Otherwise, this function searches `process-environment' for |
| 220 | VARIABLE. If it is not found there, then it continues the | 209 | VARIABLE. If it is not found there, then it continues the search |
| 221 | search in either `global-environment' or the environment list of | 210 | in the environment list of the selected frame." |
| 222 | the selected frame, depending on the value of | ||
| 223 | `local-environment-variables'." | ||
| 224 | (interactive (list (read-envvar-name "Get environment variable: " t))) | 211 | (interactive (list (read-envvar-name "Get environment variable: " t))) |
| 225 | (let ((value (getenv-internal (if (multibyte-string-p variable) | 212 | (let ((value (getenv-internal (if (multibyte-string-p variable) |
| 226 | (encode-coding-string | 213 | (encode-coding-string |
| @@ -239,47 +226,43 @@ Each entry in the list is a string of the form NAME=VALUE. | |||
| 239 | The returned list can not be used to change environment | 226 | The returned list can not be used to change environment |
| 240 | variables, only read them. See `setenv' to do that. | 227 | variables, only read them. See `setenv' to do that. |
| 241 | 228 | ||
| 242 | The list is constructed from elements of `process-environment', | 229 | The list is constructed by concatenating the elements of |
| 243 | `global-environment' and the local environment list of the | 230 | `process-environment' and the 'environment parameter of the |
| 244 | selected frame, as specified by `local-environment-variables'. | 231 | selected frame, and removing duplicated and empty values. |
| 245 | 232 | ||
| 246 | Non-ASCII characters are encoded according to the initial value of | 233 | Non-ASCII characters are encoded according to the initial value of |
| 247 | `locale-coding-system', i.e. the elements must normally be decoded for use. | 234 | `locale-coding-system', i.e. the elements must normally be decoded for use. |
| 248 | See `setenv' and `getenv'." | 235 | See `setenv' and `getenv'." |
| 249 | (let ((env (let ((local-env (frame-parameter (frame-with-environment) | 236 | (let* ((env (append process-environment |
| 250 | 'environment))) | 237 | (frame-parameter (frame-with-environment) |
| 251 | (cond ((or (not local-environment-variables) | 238 | 'environment) |
| 252 | (not local-env)) | 239 | nil)) |
| 253 | (append process-environment global-environment nil)) | 240 | (scan env) |
| 254 | ((consp local-environment-variables) | 241 | prev seen) |
| 255 | (let ((e (reverse process-environment))) | 242 | ;; Remove unset variables from the beginning of the list. |
| 256 | (dolist (entry local-environment-variables) | 243 | (while (and env |
| 257 | (setq e (cons (getenv entry) e))) | 244 | (or (not (stringp (car env))) |
| 258 | (append (nreverse e) global-environment nil))) | 245 | (not (string-match "=" (car env))))) |
| 259 | (t | 246 | (or (member (car env) seen) |
| 260 | (append process-environment local-env nil))))) | 247 | (setq seen (cons (car env) seen))) |
| 261 | scan seen) | 248 | (setq env (cdr env) |
| 262 | ;; Find the first valid entry in env. | 249 | scan env)) |
| 263 | (while (and env (stringp (car env)) | 250 | (let (name) |
| 264 | (or (not (string-match "=" (car env))) | 251 | (while scan |
| 265 | (member (substring (car env) 0 (string-match "=" (car env))) seen))) | 252 | (cond ((or (not (stringp (car scan))) |
| 266 | (setq seen (cons (car env) seen) | 253 | (not (string-match "=" (car scan)))) |
| 267 | env (cdr env))) | ||
| 268 | (setq scan env) | ||
| 269 | (while (and (cdr scan) (stringp (cadr scan))) | ||
| 270 | (let* ((match (string-match "=" (cadr scan))) | ||
| 271 | (name (substring (cadr scan) 0 match))) | ||
| 272 | (cond ((not match) | ||
| 273 | ;; Unset variable. | 254 | ;; Unset variable. |
| 274 | (setq seen (cons name seen)) | 255 | (or (member (car scan) seen) |
| 275 | (setcdr scan (cddr scan))) | 256 | (setq seen (cons (car scan) seen))) |
| 276 | ((member name seen) | 257 | (setcdr prev (cdr scan))) |
| 277 | ;; Duplicate variable. | 258 | ((member (setq name (substring (car scan) 0 (string-match "=" (car scan)))) seen) |
| 278 | (setcdr scan (cddr scan))) | 259 | ;; Duplicated variable. |
| 260 | (setcdr prev (cdr scan))) | ||
| 279 | (t | 261 | (t |
| 280 | ;; New variable. | 262 | ;; New variable. |
| 281 | (setq seen (cons name seen) | 263 | (setq seen (cons name seen)))) |
| 282 | scan (cdr scan)))))) | 264 | (setq prev scan |
| 265 | scan (cdr scan)))) | ||
| 283 | env)) | 266 | env)) |
| 284 | 267 | ||
| 285 | (defmacro let-environment (varlist &rest body) | 268 | (defmacro let-environment (varlist &rest body) |
diff --git a/lisp/frame.el b/lisp/frame.el index 0f255ac77a1..f5d3f4b0c37 100644 --- a/lisp/frame.el +++ b/lisp/frame.el | |||
| @@ -238,6 +238,9 @@ Pass it BUFFER as first arg, and (cdr ARGS) gives the rest of the args." | |||
| 238 | ;; because that would override explicit user resizing. | 238 | ;; because that would override explicit user resizing. |
| 239 | (setq initial-frame-alist | 239 | (setq initial-frame-alist |
| 240 | (frame-remove-geometry-params initial-frame-alist)))) | 240 | (frame-remove-geometry-params initial-frame-alist)))) |
| 241 | ;; Copy the environment of the Emacs process into the new frame. | ||
| 242 | (set-frame-parameter frame-initial-frame 'environment | ||
| 243 | (frame-parameter terminal-frame 'environment)) | ||
| 241 | ;; At this point, we know that we have a frame open, so we | 244 | ;; At this point, we know that we have a frame open, so we |
| 242 | ;; can delete the terminal frame. | 245 | ;; can delete the terminal frame. |
| 243 | (delete-frame terminal-frame) | 246 | (delete-frame terminal-frame) |