Reimplement terminal parameters in C; clean up term.c, create terminal.c.
[bpt/emacs.git] / lisp / env.el
CommitLineData
55535639 1;;; env.el --- functions to manipulate environment variables
c88ab9ce 2
0d30b337
TTN
3;; Copyright (C) 1991, 1994, 2000, 2001, 2002, 2003, 2004,
4;; 2005 Free Software Foundation, Inc.
971571b9 5
e5167999 6;; Maintainer: FSF
d9ecc911 7;; Keywords: processes, unix
e5167999 8
b578f267 9;; This file is part of GNU Emacs.
6449c898 10
b578f267
EN
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
13;; the Free Software Foundation; either version 2, or (at your option)
14;; any later version.
6449c898 15
b578f267
EN
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
6449c898 20
b578f267
EN
21;; You should have received a copy of the GNU General Public License
22;; along with GNU Emacs; see the file COPYING. If not, write to the
086add15
LK
23;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24;; Boston, MA 02110-1301, USA.
6449c898 25
d9ecc911
ER
26;;; Commentary:
27
b578f267
EN
28;; UNIX processes inherit a list of name-to-string associations from their
29;; parents called their `environment'; these are commonly used to control
30;; program options. This package permits you to set environment variables
31;; to be passed to any sub-process run under Emacs.
d9ecc911 32
1a90eae6
DL
33;; Note that the environment string `process-environment' is not
34;; decoded, but the args of `setenv' and `getenv' are normally
35;; multibyte text and get coding conversion.
36
e5167999
ER
37;;; Code:
38
99ac138a
RS
39;; History list for environment variable names.
40(defvar read-envvar-name-history nil)
41
42(defun read-envvar-name (prompt &optional mustmatch)
43 "Read environment variable name, prompting with PROMPT.
8b740009
RS
44Optional second arg MUSTMATCH, if non-nil, means require existing envvar name.
45If it is also not t, RET does not exit if it does non-null completion."
99ac138a 46 (completing-read prompt
1a90eae6
DL
47 (mapcar (lambda (enventry)
48 (list (if enable-multibyte-characters
49 (decode-coding-string
50 (substring enventry 0
51 (string-match "=" enventry))
52 locale-coding-system t)
53 (substring enventry 0
54 (string-match "=" enventry)))))
99ac138a
RS
55 process-environment)
56 nil mustmatch nil 'read-envvar-name-history))
57
58;; History list for VALUE argument to setenv.
59(defvar setenv-history nil)
60
a4a216c5
GM
61
62(defun substitute-env-vars (string)
63 "Substitute environment variables referred to in STRING.
64`$FOO' where FOO is an environment variable name means to substitute
65the value of that variable. The variable name should be terminated
66with a character not a letter, digit or underscore; otherwise, enclose
cccc806d
RS
67the entire variable name in braces. For instance, in `ab$cd-x',
68`$cd' is treated as an environment variable.
69
70Use `$$' to insert a single dollar sign."
a4a216c5 71 (let ((start 0))
71296446 72 (while (string-match
1a90eae6 73 (eval-when-compile
cccc806d 74 (rx (or (and "$" (submatch (1+ (regexp "[[:alnum:]_]"))))
1a90eae6
DL
75 (and "${" (submatch (minimal-match (0+ anything))) "}")
76 "$$")))
a4a216c5
GM
77 string start)
78 (cond ((match-beginning 1)
79 (let ((value (getenv (match-string 1 string))))
80 (setq string (replace-match (or value "") t t string)
81 start (+ (match-beginning 0) (length value)))))
82 ((match-beginning 2)
83 (let ((value (getenv (match-string 2 string))))
84 (setq string (replace-match (or value "") t t string)
85 start (+ (match-beginning 0) (length value)))))
86 (t
87 (setq string (replace-match "$" t t string)
88 start (+ (match-beginning 0) 1)))))
89 string))
90
1a90eae6 91;; Fixme: Should `process-environment' be recoded if LC_CTYPE &c is set?
a4a216c5
GM
92
93(defun setenv (variable &optional value unset substitute-env-vars)
6449c898 94 "Set the value of the environment variable named VARIABLE to VALUE.
b71038b2
JB
95VARIABLE should be a string. VALUE is optional; if not provided or
96nil, the environment variable VARIABLE will be removed. UNSET
a4a216c5
GM
97if non-nil means to remove VARIABLE from the environment.
98SUBSTITUTE-ENV-VARS, if non-nil, means to substitute environment
99variables in VALUE with `substitute-env-vars', where see.
100Value is the new value if VARIABLE, or nil if removed from the
101environment.
cbfe666b
RS
102
103Interactively, a prefix argument means to unset the variable.
99ac138a
RS
104Interactively, the current value (if any) of the variable
105appears at the front of the history list when you type in the new value.
a4a216c5 106Interactively, always replace environment variables in the new value.
99ac138a 107
1a90eae6
DL
108This function works by modifying `process-environment'.
109
110As a special case, setting variable `TZ' calls `set-time-zone-rule' as
111a side-effect."
cbfe666b
RS
112 (interactive
113 (if current-prefix-arg
8b740009 114 (list (read-envvar-name "Clear environment variable: " 'exact) nil t)
2a5becfb
GM
115 (let* ((var (read-envvar-name "Set environment variable: " nil))
116 (value (getenv var)))
117 (when value
118 (push value setenv-history))
99ac138a 119 ;; Here finally we specify the args to give call setenv with.
71296446 120 (list var
a4a216c5
GM
121 (read-from-minibuffer (format "Set %s to value: " var)
122 nil nil nil 'setenv-history
123 value)
71296446 124 nil
a4a216c5 125 t))))
1a90eae6 126 (if (and (multibyte-string-p variable) locale-coding-system)
1ebb05c4
KH
127 (let ((codings (find-coding-systems-string (concat variable value))))
128 (unless (or (eq 'undecided (car codings))
129 (memq (coding-system-base locale-coding-system) codings))
130 (error "Can't encode `%s=%s' with `locale-coding-system'"
131 variable (or value "")))))
b71038b2 132 (if unset
a4a216c5
GM
133 (setq value nil)
134 (if substitute-env-vars
135 (setq value (substitute-env-vars value))))
1a90eae6
DL
136 (if (multibyte-string-p variable)
137 (setq variable (encode-coding-string variable locale-coding-system)))
138 (if (and value (multibyte-string-p value))
139 (setq value (encode-coding-string value locale-coding-system)))
6449c898 140 (if (string-match "=" variable)
1bbda2d6 141 (error "Environment variable name `%s' contains `='" variable)
971571b9 142 (let ((pattern (concat "\\`" (regexp-quote (concat variable "="))))
7e68de56 143 (case-fold-search nil)
cbfe666b
RS
144 (scan process-environment)
145 found)
7fd81709
RS
146 (if (string-equal "TZ" variable)
147 (set-time-zone-rule value))
cbfe666b
RS
148 (while scan
149 (cond ((string-match pattern (car scan))
150 (setq found t)
151 (if (eq nil value)
1a90eae6
DL
152 (setq process-environment (delq (car scan)
153 process-environment))
cbfe666b
RS
154 (setcar scan (concat variable "=" value)))
155 (setq scan nil)))
156 (setq scan (cdr scan)))
157 (or found
158 (if value
a3cda273 159 (setq process-environment
cbfe666b 160 (cons (concat variable "=" value)
a4a216c5
GM
161 process-environment))))))
162 value)
49116ac0 163
b1e11b4f
GM
164(defun getenv (variable)
165 "Get the value of environment variable VARIABLE.
166VARIABLE should be a string. Value is nil if VARIABLE is undefined in
167the environment. Otherwise, value is a string.
168
169This function consults the variable `process-environment'
170for its value."
171 (interactive (list (read-envvar-name "Get environment variable: " t)))
1a90eae6
DL
172 (let ((value (getenv-internal (if (multibyte-string-p variable)
173 (encode-coding-string
174 variable locale-coding-system)
175 variable))))
176 (if (and enable-multibyte-characters value)
177 (setq value (decode-coding-string value locale-coding-system)))
b1e11b4f
GM
178 (when (interactive-p)
179 (message "%s" (if value value "Not set")))
180 value))
181
1bbda2d6
NF
182(provide 'env)
183
ab5796a9 184;;; arch-tag: b7d6a8f7-bc81-46db-8e39-8d721d4ed0b8
1bbda2d6 185;;; env.el ends here