comparison tango/tango/sys/Environment.d @ 132:1700239cab2e trunk

[svn r136] MAJOR UNSTABLE UPDATE!!! Initial commit after moving to Tango instead of Phobos. Lots of bugfixes... This build is not suitable for most things.
author lindquist
date Fri, 11 Jan 2008 17:57:40 +0100
parents
children
comparison
equal deleted inserted replaced
131:5825d48b27d1 132:1700239cab2e
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