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