b311480e |
1 | // Copyright (c) 1998-1999 Matra Datavision |
973c2be1 |
2 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
3 | // |
973c2be1 |
4 | // This file is part of Open CASCADE Technology software library. |
b311480e |
5 | // |
d5f74e42 |
6 | // This library is free software; you can redistribute it and/or modify it under |
7 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
8 | // by the Free Software Foundation, with special exception defined in the file |
9 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
10 | // distribution for complete text of the license and disclaimer of any warranty. |
b311480e |
11 | // |
973c2be1 |
12 | // Alternatively, this file may be used under the terms of Open CASCADE |
13 | // commercial license or contractual agreement. |
7fd59977 |
14 | |
57c28b61 |
15 | #ifndef _WIN32 |
7fd59977 |
16 | |
42cf5bc1 |
17 | #include <OSD_Environment.hxx> |
18 | #include <OSD_OSDError.hxx> |
19 | #include <OSD_WhoAmI.hxx> |
7fd59977 |
20 | #include <Standard_ConstructionError.hxx> |
21 | #include <Standard_Failure.hxx> |
22 | #include <Standard_Mutex.hxx> |
42cf5bc1 |
23 | #include <Standard_NullObject.hxx> |
24 | #include <TCollection_AsciiString.hxx> |
8582eb08 |
25 | #include <NCollection_UtfString.hxx> |
7fd59977 |
26 | |
42cf5bc1 |
27 | #include <errno.h> |
7fd59977 |
28 | #include <stdio.h> |
42cf5bc1 |
29 | #include <stdlib.h> |
7fd59977 |
30 | #include <string.h> |
7fd59977 |
31 | static const OSD_WhoAmI Iam = OSD_WEnvironment; |
32 | |
33 | // ---------------------------------------------------------------------- |
34 | // |
35 | // Updated by : JPT Dec,7 1992 |
36 | // What : OSD_Environment::OSD_Environment |
37 | // (const TCollection_AsciiString& Name, |
38 | // const TCollection_AsciiString& Value) |
39 | // Value could contain the character $ (Ex setenv a = $c) |
40 | // |
41 | // ---------------------------------------------------------------------- |
42 | // Create object |
43 | |
44 | OSD_Environment::OSD_Environment() |
45 | { |
46 | } |
47 | |
48 | |
49 | // ---------------------------------------------------------------------- |
50 | // Constructor |
51 | // ---------------------------------------------------------------------- |
52 | |
53 | OSD_Environment::OSD_Environment(const TCollection_AsciiString& Name) |
54 | { |
55 | |
56 | if (!Name.IsAscii() || Name.Search("$") != -1 ) |
9775fa61 |
57 | throw Standard_ConstructionError("OSD_Environment::OSD_Environment: bad argument"); |
7fd59977 |
58 | |
59 | myName = Name; |
60 | } |
61 | |
62 | |
63 | // ---------------------------------------------------------------------- |
64 | // Create an environment variable and initialize it |
65 | // ---------------------------------------------------------------------- |
66 | |
67 | OSD_Environment::OSD_Environment(const TCollection_AsciiString& Name, |
68 | const TCollection_AsciiString& Value) |
69 | { |
70 | |
71 | if (!Name.IsAscii() || !Value.IsAscii() || |
72 | // JPT : Dec-7-1992 Name.Search("$") != -1 || Value.Search("$") != -1) |
73 | Name.Search("$") != -1 ) |
9775fa61 |
74 | throw Standard_ConstructionError("OSD_Environment::OSD_Environment: bad argument"); |
7fd59977 |
75 | |
76 | myName = Name; |
77 | myValue = Value; |
78 | } |
79 | |
80 | |
81 | // ---------------------------------------------------------------------- |
82 | // Returns the name of the symbol |
83 | // ---------------------------------------------------------------------- |
84 | |
85 | TCollection_AsciiString OSD_Environment::Name () const |
86 | { |
87 | return myName; |
88 | } |
89 | |
90 | // ---------------------------------------------------------------------- |
91 | // Set new value for environment variable |
92 | // ---------------------------------------------------------------------- |
93 | |
94 | void OSD_Environment::SetName (const TCollection_AsciiString& Name) |
95 | { |
96 | myError.Reset(); |
97 | if (!Name.IsAscii() || Name.Search("$") != -1 ) |
9775fa61 |
98 | throw Standard_ConstructionError("OSD_Environment::SetName: bad argument"); |
7fd59977 |
99 | |
100 | myName = Name; |
101 | } |
102 | |
103 | // ---------------------------------------------------------------------- |
104 | // Change value |
105 | // ---------------------------------------------------------------------- |
106 | |
107 | void OSD_Environment::SetValue (const TCollection_AsciiString& Value) |
108 | { |
109 | if (!Value.IsAscii() || Value.Search("$") != -1) |
9775fa61 |
110 | throw Standard_ConstructionError("OSD_Environment::Change: bad argument"); |
7fd59977 |
111 | |
112 | myValue = Value; |
113 | } |
114 | |
115 | // ---------------------------------------------------------------------- |
116 | // Get environment variable physically |
117 | // ---------------------------------------------------------------------- |
118 | |
119 | TCollection_AsciiString OSD_Environment::Value() |
120 | { |
121 | char *result = getenv(myName.ToCString()); |
122 | if (result == NULL) myValue.Clear(); |
123 | else myValue = result; |
124 | return myValue; |
125 | } |
126 | |
127 | // ---------------------------------------------------------------------- |
128 | // Sets physically the environment variable |
129 | // ---------------------------------------------------------------------- |
130 | |
131 | void OSD_Environment::Build () |
132 | { |
133 | // Static buffer to hold definitions of new variables for the environment. |
134 | // Note that they need to be static since putenv does not make a copy |
135 | // of the string, but just adds its pointer to the environment. |
136 | static char **buffer = 0 ; // JPT: |
137 | static int Ibuffer = 0 ; // Tout ca pour putenv,getenv |
138 | |
139 | // Use mutex to avoid concurrent access to the buffer |
140 | static Standard_Mutex theMutex; |
141 | Standard_Mutex::Sentry aSentry ( theMutex ); |
142 | |
143 | // check if such variable has already been created in the buffer |
144 | int index = -1, len = myName.Length(); |
145 | for ( int i=0; i < Ibuffer; i++ ) { |
146 | if ( ! strncmp ( buffer[i], myName.ToCString(), len ) && buffer[i][len] == '=' ) { |
147 | index = i; |
148 | break; |
149 | } |
150 | } |
151 | |
152 | // and either add a new entry, or remember the old entry for a while |
153 | char *old_value = 0; |
154 | if ( index >=0 ) { |
155 | old_value = buffer[index]; |
156 | } |
157 | else { |
158 | // Allocation memoire. Surtout tout la heap! |
159 | index = Ibuffer++; |
8413a813 |
160 | char **aTmp; |
161 | aTmp = (char **) realloc ( buffer, Ibuffer * sizeof(char*) ); |
162 | if (aTmp) |
163 | { |
164 | buffer = aTmp; |
165 | } |
166 | else |
167 | { |
168 | myError.SetValue(errno, Iam, "Memory realloc failure"); |
169 | return; |
170 | } |
7fd59977 |
171 | } |
172 | |
173 | // create a new entry in the buffer and add it to environment |
174 | buffer[index] = (char *) malloc ( len + myValue.Length() + 2 ); |
175 | sprintf(buffer[index], "%s=%s", myName.ToCString(), myValue.ToCString()); |
176 | putenv(buffer[index]); |
177 | |
178 | // then (and only then!) free old entry, if existed |
179 | if ( old_value ) |
180 | free ( old_value ); |
181 | |
182 | // check the result |
183 | char *result = getenv(myName.ToCString()); |
184 | if (result == NULL) |
185 | myError.SetValue(errno, Iam, "Set Environment"); |
186 | } |
187 | |
188 | // ---------------------------------------------------------------------- |
189 | // Remove physically the environment variable |
190 | // ---------------------------------------------------------------------- |
191 | |
192 | void OSD_Environment::Remove () |
193 | { |
194 | myValue.Clear(); |
195 | Build(); |
196 | } |
197 | |
198 | |
199 | |
200 | // ---------------------------------------------------------------------- |
201 | // ---------------------------------------------------------------------- |
202 | void OSD_Environment::Reset() |
203 | { |
204 | myError.Reset(); |
205 | } |
206 | |
207 | // ---------------------------------------------------------------------- |
208 | // ---------------------------------------------------------------------- |
209 | Standard_Boolean OSD_Environment::Failed() const |
210 | { |
211 | return myError.Failed(); |
212 | } |
213 | |
214 | // ---------------------------------------------------------------------- |
215 | // ---------------------------------------------------------------------- |
216 | void OSD_Environment::Perror() |
217 | { |
218 | myError.Perror(); |
219 | } |
220 | |
221 | |
222 | // ---------------------------------------------------------------------- |
223 | // ---------------------------------------------------------------------- |
224 | Standard_Integer OSD_Environment::Error() const |
225 | { |
226 | return myError.Error(); |
227 | } |
228 | |
229 | #else |
230 | |
231 | //------------------------------------------------------------------------ |
232 | //------------------- WNT Sources of OSD_Environment -------------------- |
233 | //------------------------------------------------------------------------ |
234 | |
ad03c234 |
235 | #include <windows.h> |
236 | |
7fd59977 |
237 | #include <OSD_Environment.hxx> |
238 | |
1ce0716b |
239 | #include <NCollection_DataMap.hxx> |
8582eb08 |
240 | #include <NCollection_UtfString.hxx> |
1ce0716b |
241 | #include <Standard_Mutex.hxx> |
8582eb08 |
242 | |
1ce0716b |
243 | #ifdef OCCT_UWP |
244 | namespace |
245 | { |
246 | // emulate global map of environment variables |
247 | static Standard_Mutex THE_ENV_LOCK; |
248 | static NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString> THE_ENV_MAP; |
249 | } |
250 | #else |
7fd59977 |
251 | static void __fastcall _set_error ( OSD_Error&, DWORD ); |
742cc8b0 |
252 | #endif |
7fd59977 |
253 | |
254 | OSD_Environment :: OSD_Environment () { |
255 | |
256 | } // end constructor ( 1 ) |
257 | |
258 | OSD_Environment :: OSD_Environment ( const TCollection_AsciiString& Name ) { |
259 | |
260 | myName = Name; |
261 | |
262 | } // end constructor ( 2 ) |
263 | |
264 | OSD_Environment :: OSD_Environment ( |
265 | const TCollection_AsciiString& Name, |
266 | const TCollection_AsciiString& Value |
267 | ) { |
268 | |
269 | myName = Name; |
270 | myValue = Value; |
271 | |
272 | } // end constructor ( 3 ) |
273 | |
274 | void OSD_Environment :: SetValue ( const TCollection_AsciiString& Value ) { |
275 | |
276 | myValue = Value; |
277 | |
278 | } // end OSD_Environment :: SetValue |
279 | |
8582eb08 |
280 | TCollection_AsciiString OSD_Environment::Value() |
281 | { |
282 | myValue.Clear(); |
1ce0716b |
283 | #ifdef OCCT_UWP |
284 | Standard_Mutex::Sentry aLock (THE_ENV_LOCK); |
285 | THE_ENV_MAP.Find (myName, myValue); |
286 | #else |
e87d0237 |
287 | |
288 | // msvc C-runtime (_wputenv()) puts variable using WinAPI internally (calls SetEnvironmentVariableW()) |
289 | // and also caches its value in its own map, |
5e6e5914 |
290 | // so that _wgetenv() ignores WinAPI and retrieves variable from this cache. |
e87d0237 |
291 | // |
292 | // Using _wgetenv() might lead to awkward results in context when several C-runtimes are used |
293 | // at once within application or WinAPI is used directly for setting environment variable. |
294 | // |
295 | // Using _wputenv() + GetEnvironmentVariableW() pair should provide most robust behavior in tricky scenarios. |
296 | // So that _wgetenv() users will retrieve proper value set by OSD_Environment if used C-runtime library is the same as used by OCCT, |
297 | // and OSD_Environment will retreieve most up-to-date value of environment variable nevertheless C-runtime version used (or not used at all) for setting value externally, |
298 | // considering msvc C-runtime implementation details. |
8582eb08 |
299 | SetLastError (ERROR_SUCCESS); |
8582eb08 |
300 | NCollection_UtfWideString aNameWide (myName.ToCString()); |
301 | DWORD aSize = GetEnvironmentVariableW (aNameWide.ToCString(), NULL, 0); |
e87d0237 |
302 | if (aSize == 0 && GetLastError() != ERROR_SUCCESS) |
8582eb08 |
303 | { |
304 | _set_error (myError, ERROR_ENVVAR_NOT_FOUND); |
305 | return myValue; |
306 | } |
7fd59977 |
307 | |
8582eb08 |
308 | NCollection_Utf8String aValue; |
e87d0237 |
309 | aSize += 1; // NULL-terminator |
310 | wchar_t* aBuff = new wchar_t[aSize]; |
311 | GetEnvironmentVariableW (aNameWide.ToCString(), aBuff, aSize); |
312 | aBuff[aSize - 1] = L'\0'; |
313 | aValue.FromUnicode (aBuff); |
314 | delete[] aBuff; |
315 | Reset(); |
316 | |
8582eb08 |
317 | myValue = aValue.ToCString(); |
742cc8b0 |
318 | #endif |
1ce0716b |
319 | return myValue; |
8582eb08 |
320 | } |
7fd59977 |
321 | |
322 | void OSD_Environment :: SetName ( const TCollection_AsciiString& name ) { |
323 | |
324 | myName = name; |
325 | |
326 | } // end OSD_Environment :: SetName |
327 | |
328 | TCollection_AsciiString OSD_Environment :: Name () const { |
329 | |
330 | return myName; |
331 | |
332 | } // end OSD_Environment :: Name |
333 | |
8582eb08 |
334 | void OSD_Environment::Build() |
335 | { |
1ce0716b |
336 | #ifdef OCCT_UWP |
337 | Standard_Mutex::Sentry aLock(THE_ENV_LOCK); |
338 | THE_ENV_MAP.Bind (myName, myValue); |
339 | #else |
8582eb08 |
340 | NCollection_Utf8String aSetVariable = NCollection_Utf8String(myName.ToCString()) + "=" + myValue.ToCString(); |
341 | _wputenv (aSetVariable.ToUtfWide().ToCString()); |
742cc8b0 |
342 | #endif |
8582eb08 |
343 | } |
7fd59977 |
344 | |
8582eb08 |
345 | void OSD_Environment::Remove() |
346 | { |
1ce0716b |
347 | #ifdef OCCT_UWP |
348 | Standard_Mutex::Sentry aLock(THE_ENV_LOCK); |
349 | THE_ENV_MAP.UnBind (myName); |
350 | #else |
8582eb08 |
351 | NCollection_Utf8String aSetVariable = NCollection_Utf8String(myName.ToCString()) + "="; |
352 | _wputenv (aSetVariable.ToUtfWide().ToCString()); |
742cc8b0 |
353 | #endif |
8582eb08 |
354 | } |
7fd59977 |
355 | |
356 | Standard_Boolean OSD_Environment :: Failed () const { |
357 | |
358 | return myError.Failed (); |
359 | |
360 | } // end OSD_Environment :: Failed |
361 | |
362 | void OSD_Environment :: Reset () { |
363 | |
364 | myError.Reset (); |
365 | |
366 | } // end OSD_Environment :: Reset |
367 | |
46802936 |
368 | void OSD_Environment :: Perror () |
369 | { |
370 | myError.Perror (); |
7fd59977 |
371 | } // end OSD_Environment :: Perror |
372 | |
373 | Standard_Integer OSD_Environment :: Error () const { |
374 | |
375 | return myError.Error (); |
376 | |
377 | } // end OSD_Environment :: Error |
378 | |
742cc8b0 |
379 | #ifndef OCCT_UWP |
ad03c234 |
380 | static void __fastcall _set_error (OSD_Error& theErr, DWORD theCode) |
381 | { |
382 | wchar_t aBuffer[2048]; |
383 | const DWORD anErrCode = theCode != 0 ? theCode : GetLastError(); |
384 | if (!FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY, |
385 | 0, anErrCode, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ), |
386 | aBuffer, 2048, NULL)) |
387 | { |
388 | theErr.SetValue (anErrCode, OSD_WEnvironment, TCollection_AsciiString ("error code ") + (Standard_Integer)anErrCode); |
389 | SetLastError (anErrCode); |
390 | } |
391 | else |
392 | { |
393 | theErr.SetValue (anErrCode, OSD_WEnvironment, TCollection_AsciiString (aBuffer)); |
394 | } |
395 | } |
742cc8b0 |
396 | #endif |
7fd59977 |
397 | |
398 | #endif |