0028110: Configuration - specify Unicode charset instead of multibyte in project...
[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 #include <OSD_Environment.hxx>
18 #include <OSD_OSDError.hxx>
19 #include <OSD_WhoAmI.hxx>
20 #include <Standard_ConstructionError.hxx>
21 #include <Standard_Failure.hxx>
22 #include <Standard_Mutex.hxx>
23 #include <Standard_NullObject.hxx>
24 #include <TCollection_AsciiString.hxx>
25 #include <NCollection_UtfString.hxx>
26
27 #include <errno.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
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 ) 
57    Standard_ConstructionError::Raise("OSD_Environment::OSD_Environment: bad argument");
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 ) 
74    Standard_ConstructionError::Raise("OSD_Environment::OSD_Environment: bad argument");
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 ) 
98    Standard_ConstructionError::Raise("OSD_Environment::SetName: bad argument");
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) 
110    Standard_ConstructionError::Raise("OSD_Environment::Change: bad argument");
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++;
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     }
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
235 #define STRICT
236 #include <windows.h>
237
238 #include <OSD_Environment.hxx>
239
240 #include <OSD_WNT.hxx>
241
242 #include <NCollection_DataMap.hxx>
243 #include <NCollection_UtfString.hxx>
244 #include <Standard_Mutex.hxx>
245
246 #ifdef OCCT_UWP
247 namespace
248 {
249   // emulate global map of environment variables
250   static Standard_Mutex THE_ENV_LOCK;
251   static NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString> THE_ENV_MAP;
252 }
253 #else
254 static void __fastcall _set_error ( OSD_Error&, DWORD );
255 #endif
256
257 OSD_Environment :: OSD_Environment () {
258
259 }  // end constructor ( 1 )
260
261 OSD_Environment :: OSD_Environment ( const TCollection_AsciiString& Name ) {
262
263  myName = Name;
264
265 }  // end constructor ( 2 )
266
267 OSD_Environment :: OSD_Environment (
268                     const TCollection_AsciiString& Name,
269                     const TCollection_AsciiString& Value
270                    ) {
271
272  myName  = Name;
273  myValue = Value;
274
275 }  // end constructor ( 3 )
276
277 void OSD_Environment :: SetValue ( const TCollection_AsciiString& Value ) {
278
279  myValue = Value;
280
281 }  // end OSD_Environment :: SetValue
282
283 TCollection_AsciiString OSD_Environment::Value()
284 {
285   myValue.Clear();
286 #ifdef OCCT_UWP
287   Standard_Mutex::Sentry aLock (THE_ENV_LOCK);
288   THE_ENV_MAP.Find (myName, myValue);
289 #else
290   SetLastError (ERROR_SUCCESS);
291   wchar_t* anEnvVal = NULL;
292   NCollection_UtfWideString aNameWide (myName.ToCString());
293   DWORD aSize = GetEnvironmentVariableW (aNameWide.ToCString(), NULL, 0);
294   if ((aSize == 0 && GetLastError() != ERROR_SUCCESS)
295    || (anEnvVal = _wgetenv (aNameWide.ToCString())) == NULL)
296   {
297     _set_error (myError, ERROR_ENVVAR_NOT_FOUND);
298     return myValue;
299   }
300
301   NCollection_Utf8String aValue;
302   if (anEnvVal != NULL)
303   {
304     aValue.FromUnicode (anEnvVal);
305   }
306   else
307   {
308     aSize += 1; // NULL-terminator
309     wchar_t* aBuff = new wchar_t[aSize];
310     GetEnvironmentVariableW (aNameWide.ToCString(), aBuff, aSize);
311     aBuff[aSize - 1] = L'\0';
312     aValue.FromUnicode (aBuff);
313     delete[] aBuff;
314     Reset();
315   }
316   myValue = aValue.ToCString();
317 #endif
318   return myValue;
319 }
320
321 void OSD_Environment :: SetName ( const TCollection_AsciiString& name ) {
322
323  myName = name;
324
325 }  // end OSD_Environment :: SetName
326
327 TCollection_AsciiString OSD_Environment :: Name () const {
328
329  return myName;
330
331 }  // end OSD_Environment :: Name
332
333 void OSD_Environment::Build()
334 {
335 #ifdef OCCT_UWP
336   Standard_Mutex::Sentry aLock(THE_ENV_LOCK);
337   THE_ENV_MAP.Bind (myName, myValue);
338 #else
339   NCollection_Utf8String aSetVariable = NCollection_Utf8String(myName.ToCString()) + "=" + myValue.ToCString();
340   _wputenv (aSetVariable.ToUtfWide().ToCString());
341 #endif
342 }
343
344 void OSD_Environment::Remove()
345 {
346 #ifdef OCCT_UWP
347   Standard_Mutex::Sentry aLock(THE_ENV_LOCK);
348   THE_ENV_MAP.UnBind (myName);
349 #else
350   NCollection_Utf8String aSetVariable = NCollection_Utf8String(myName.ToCString()) + "=";
351   _wputenv (aSetVariable.ToUtfWide().ToCString());
352 #endif
353 }
354
355 Standard_Boolean OSD_Environment :: Failed () const {
356
357  return myError.Failed ();
358
359 }  // end OSD_Environment :: Failed
360
361 void OSD_Environment :: Reset () {
362
363  myError.Reset ();
364
365 }  // end OSD_Environment :: Reset
366
367 void OSD_Environment :: Perror ()
368 {
369   myError.Perror ();
370 }  // end OSD_Environment :: Perror
371
372 Standard_Integer OSD_Environment :: Error () const {
373
374  return myError.Error ();
375
376 }  // end OSD_Environment :: Error
377
378 #ifndef OCCT_UWP
379 static void __fastcall _set_error (OSD_Error& theErr, DWORD theCode)
380 {
381   wchar_t aBuffer[2048];
382   const DWORD anErrCode = theCode != 0 ? theCode : GetLastError();
383   if (!FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
384                        0, anErrCode, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ),
385                        aBuffer, 2048, NULL))
386   {
387     theErr.SetValue (anErrCode, OSD_WEnvironment, TCollection_AsciiString ("error code ") + (Standard_Integer)anErrCode);
388     SetLastError (anErrCode);
389   }
390   else
391   {
392     theErr.SetValue (anErrCode, OSD_WEnvironment, TCollection_AsciiString (aBuffer));
393   }
394 }
395 #endif
396
397 #endif