132
|
1 /*******************************************************************************
|
|
2
|
|
3 copyright: Copyright (c) 2007 Tango. All rights reserved
|
|
4
|
|
5 license: BSD style: $(LICENSE)
|
|
6
|
|
7 version: Feb 2007: Initial release
|
|
8
|
|
9 author: Deewiant, Maxter, Gregor, Kris
|
|
10
|
|
11 *******************************************************************************/
|
|
12
|
|
13 module tango.sys.Environment;
|
|
14
|
|
15 private import tango.sys.Common;
|
|
16
|
|
17 private import tango.io.FilePath,
|
|
18 tango.io.FileConst,
|
|
19 tango.io.FileSystem;
|
|
20
|
|
21 private import tango.core.Exception;
|
|
22
|
|
23 private import Text = tango.text.Util;
|
|
24
|
|
25 /*******************************************************************************
|
|
26
|
|
27 *******************************************************************************/
|
|
28
|
|
29 version (Windows)
|
|
30 {
|
|
31 private import tango.text.convert.Utf;
|
|
32
|
|
33 pragma (lib, "kernel32.lib");
|
|
34
|
|
35 extern (Windows)
|
|
36 {
|
|
37 private void* GetEnvironmentStringsW();
|
|
38 private bool FreeEnvironmentStringsW(wchar**);
|
|
39 }
|
|
40 extern (Windows)
|
|
41 {
|
|
42 private int SetEnvironmentVariableW(wchar*, wchar*);
|
|
43 private uint GetEnvironmentVariableW(wchar*, wchar*, uint);
|
|
44 private const int ERROR_ENVVAR_NOT_FOUND = 203;
|
|
45 }
|
|
46 }
|
|
47 else
|
|
48 {
|
|
49 private extern (C) extern char** environ;
|
|
50
|
|
51 import tango.stdc.posix.stdlib;
|
|
52 import tango.stdc.string;
|
|
53 }
|
|
54
|
|
55
|
|
56 /*******************************************************************************
|
|
57
|
|
58 Exposes the system Environment settings, along with some handy
|
|
59 utilities
|
|
60
|
|
61 *******************************************************************************/
|
|
62
|
|
63 struct Environment
|
|
64 {
|
|
65 /***********************************************************************
|
|
66
|
|
67 Returns the full path location of the provided executable
|
|
68 file, rifling through the PATH as necessary.
|
|
69
|
|
70 Returns null if the provided filename was not found
|
|
71
|
|
72 ***********************************************************************/
|
|
73
|
|
74 static FilePath exePath (char[] file)
|
|
75 {
|
|
76 auto bin = new FilePath (file);
|
|
77
|
|
78 // on Windows, this is a .exe
|
|
79 version (Windows)
|
|
80 if (bin.ext.length is 0)
|
|
81 bin.append (".exe");
|
|
82
|
|
83 // is this a directory? Potentially make it absolute
|
|
84 if (bin.isChild)
|
|
85 return FileSystem.toAbsolute (bin);
|
|
86
|
|
87 // is it in cwd?
|
|
88 version (Windows)
|
|
89 if (bin.path(FileSystem.getDirectory).exists)
|
|
90 return bin;
|
|
91
|
|
92 // rifle through the path
|
|
93 foreach (pe; Text.patterns (get("PATH"), FileConst.SystemPathString))
|
|
94 if (bin.path(pe).exists)
|
|
95 version (Windows)
|
|
96 return bin;
|
|
97 else
|
|
98 {
|
|
99 stat_t stats;
|
|
100 stat(bin.cString.ptr, &stats);
|
|
101 if (stats.st_mode & 0100)
|
|
102 return bin;
|
|
103 }
|
|
104 return null;
|
|
105 }
|
|
106
|
|
107
|
|
108 version (Win32)
|
|
109 {
|
|
110 /**************************************************************
|
|
111
|
|
112 Returns the provided 'def' value if the variable
|
|
113 does not exist
|
|
114
|
|
115 **************************************************************/
|
|
116
|
|
117 static char[] get (char[] variable, char[] def = null)
|
|
118 {
|
|
119 wchar[] var = toString16(variable) ~ "\0";
|
|
120
|
|
121 uint size = GetEnvironmentVariableW(var.ptr, cast(wchar*)null, 0);
|
|
122 if (size is 0)
|
|
123 {
|
|
124 if (SysError.lastCode is ERROR_ENVVAR_NOT_FOUND)
|
|
125 return def;
|
|
126 else
|
|
127 throw new PlatformException (SysError.lastMsg);
|
|
128 }
|
|
129
|
|
130 auto buffer = new wchar[size];
|
|
131 size = GetEnvironmentVariableW(var.ptr, buffer.ptr, size);
|
|
132 if (size is 0)
|
|
133 throw new PlatformException (SysError.lastMsg);
|
|
134
|
|
135 return toString (buffer[0 .. size]);
|
|
136 }
|
|
137
|
|
138 /**************************************************************
|
|
139
|
|
140 clears the variable if value is null or empty
|
|
141
|
|
142 **************************************************************/
|
|
143
|
|
144 static void set (char[] variable, char[] value = null)
|
|
145 {
|
|
146 wchar * var, val;
|
|
147
|
|
148 var = (toString16 (variable) ~ "\0").ptr;
|
|
149
|
|
150 if (value.length > 0)
|
|
151 val = (toString16 (value) ~ "\0").ptr;
|
|
152
|
|
153 if (! SetEnvironmentVariableW(var, val))
|
|
154 throw new PlatformException (SysError.lastMsg);
|
|
155 }
|
|
156
|
|
157 /**************************************************************
|
|
158
|
|
159 **************************************************************/
|
|
160
|
|
161 static char[][char[]] get ()
|
|
162 {
|
|
163 char[][char[]] arr;
|
|
164
|
|
165 wchar[] key = new wchar[20],
|
|
166 value = new wchar[40];
|
|
167
|
|
168 wchar** env = cast(wchar**) GetEnvironmentStringsW();
|
|
169 scope (exit)
|
|
170 FreeEnvironmentStringsW (env);
|
|
171
|
|
172 for (wchar* str = cast(wchar*) env; *str; ++str)
|
|
173 {
|
|
174 size_t k = 0, v = 0;
|
|
175
|
|
176 while (*str != '=')
|
|
177 {
|
|
178 key[k++] = *str++;
|
|
179
|
|
180 if (k is key.length)
|
|
181 key.length = 2 * key.length;
|
|
182 }
|
|
183
|
|
184 ++str;
|
|
185
|
|
186 while (*str)
|
|
187 {
|
|
188 value [v++] = *str++;
|
|
189
|
|
190 if (v is value.length)
|
|
191 value.length = 2 * value.length;
|
|
192 }
|
|
193
|
|
194 arr [toString(key[0 .. k])] = toString(value[0 .. v]);
|
|
195 }
|
|
196
|
|
197 return arr;
|
|
198 }
|
|
199 }
|
|
200 else // POSIX
|
|
201 {
|
|
202 /**************************************************************
|
|
203
|
|
204 Returns the provided 'def' value if the variable
|
|
205 does not exist
|
|
206
|
|
207 **************************************************************/
|
|
208
|
|
209 static char[] get (char[] variable, char[] def = null)
|
|
210 {
|
|
211 char* ptr = getenv (variable.ptr);
|
|
212
|
|
213 if (ptr is null)
|
|
214 return def;
|
|
215
|
|
216 return ptr[0 .. strlen(ptr)].dup;
|
|
217 }
|
|
218
|
|
219 /**************************************************************
|
|
220
|
|
221 clears the variable, if value is null or empty
|
|
222
|
|
223 **************************************************************/
|
|
224
|
|
225 static void set (char[] variable, char[] value = null)
|
|
226 {
|
|
227 int result;
|
|
228
|
|
229 if (value.length is 0)
|
|
230 unsetenv ((variable ~ '\0').ptr);
|
|
231 else
|
|
232 result = setenv ((variable ~ '\0').ptr, (value ~ '\0').ptr, 1);
|
|
233
|
|
234 if (result != 0)
|
|
235 throw new PlatformException (SysError.lastMsg);
|
|
236 }
|
|
237
|
|
238 /**************************************************************
|
|
239
|
|
240 **************************************************************/
|
|
241
|
|
242 static char[][char[]] get ()
|
|
243 {
|
|
244 char[][char[]] arr;
|
|
245
|
|
246 for (char** p = environ; *p; ++p)
|
|
247 {
|
|
248 size_t k = 0;
|
|
249 char* str = *p;
|
|
250
|
|
251 while (*str++ != '=')
|
|
252 ++k;
|
|
253 char[] key = (*p)[0..k];
|
|
254
|
|
255 k = 0;
|
|
256 char* val = str;
|
|
257 while (*str++)
|
|
258 ++k;
|
|
259 arr[key] = val[0 .. k];
|
|
260 }
|
|
261
|
|
262 return arr;
|
|
263 }
|
|
264 }
|
|
265 }
|
|
266
|
|
267 debug (Environment)
|
|
268 {
|
|
269 import tango.io.Console;
|
|
270
|
|
271
|
|
272 void main(char[][] args)
|
|
273 {
|
|
274 const char[] VAR = "TESTENVVAR";
|
|
275 const char[] VAL1 = "VAL1";
|
|
276 const char[] VAL2 = "VAL2";
|
|
277
|
|
278 assert(Environment.get(VAR) is null);
|
|
279
|
|
280 Environment.set(VAR, VAL1);
|
|
281 assert(Environment.get(VAR) == VAL1);
|
|
282
|
|
283 Environment.set(VAR, VAL2);
|
|
284 assert(Environment.get(VAR) == VAL2);
|
|
285
|
|
286 Environment.set(VAR, null);
|
|
287 assert(Environment.get(VAR) is null);
|
|
288
|
|
289 Environment.set(VAR, VAL1);
|
|
290 Environment.set(VAR, "");
|
|
291
|
|
292 assert(Environment.get(VAR) is null);
|
|
293
|
|
294 foreach (key, value; Environment.get)
|
|
295 Cout (key) ("=") (value).newline;
|
|
296
|
|
297 if (args.length > 0)
|
|
298 {
|
|
299 auto p = Environment.exePath (args[0]);
|
|
300 Cout (p).newline;
|
|
301 }
|
|
302
|
|
303 if (args.length > 1)
|
|
304 {
|
|
305 if (auto p = Environment.exePath (args[1]))
|
|
306 Cout (p).newline;
|
|
307 }
|
|
308 }
|
|
309 }
|
|
310
|