0030959: OSD_Parallel_TBB: number of execution threads is strictly limited by the...
[occt.git] / src / OSD / OSD_Environment.cxx
CommitLineData
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 31static 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
44OSD_Environment::OSD_Environment()
45{
46}
47
48
49// ----------------------------------------------------------------------
50// Constructor
51// ----------------------------------------------------------------------
52
53OSD_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
67OSD_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
85TCollection_AsciiString OSD_Environment::Name () const
86{
87 return myName;
88}
89
90// ----------------------------------------------------------------------
91// Set new value for environment variable
92// ----------------------------------------------------------------------
93
94void 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
107void 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
119TCollection_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
131void 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
192void OSD_Environment::Remove ()
193{
194 myValue.Clear();
195 Build();
196}
197
198
199
200// ----------------------------------------------------------------------
201// ----------------------------------------------------------------------
202void OSD_Environment::Reset()
203{
204 myError.Reset();
205}
206
207// ----------------------------------------------------------------------
208// ----------------------------------------------------------------------
209Standard_Boolean OSD_Environment::Failed() const
210{
211 return myError.Failed();
212}
213
214// ----------------------------------------------------------------------
215// ----------------------------------------------------------------------
216void OSD_Environment::Perror()
217{
218 myError.Perror();
219}
220
221
222// ----------------------------------------------------------------------
223// ----------------------------------------------------------------------
224Standard_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
239#include <OSD_WNT.hxx>
240
1ce0716b 241#include <NCollection_DataMap.hxx>
8582eb08 242#include <NCollection_UtfString.hxx>
1ce0716b 243#include <Standard_Mutex.hxx>
8582eb08 244
1ce0716b 245#ifdef OCCT_UWP
246namespace
247{
248 // emulate global map of environment variables
249 static Standard_Mutex THE_ENV_LOCK;
250 static NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString> THE_ENV_MAP;
251}
252#else
7fd59977 253static void __fastcall _set_error ( OSD_Error&, DWORD );
742cc8b0 254#endif
7fd59977 255
256OSD_Environment :: OSD_Environment () {
257
258} // end constructor ( 1 )
259
260OSD_Environment :: OSD_Environment ( const TCollection_AsciiString& Name ) {
261
262 myName = Name;
263
264} // end constructor ( 2 )
265
266OSD_Environment :: OSD_Environment (
267 const TCollection_AsciiString& Name,
268 const TCollection_AsciiString& Value
269 ) {
270
271 myName = Name;
272 myValue = Value;
273
274} // end constructor ( 3 )
275
276void OSD_Environment :: SetValue ( const TCollection_AsciiString& Value ) {
277
278 myValue = Value;
279
280} // end OSD_Environment :: SetValue
281
8582eb08 282TCollection_AsciiString OSD_Environment::Value()
283{
284 myValue.Clear();
1ce0716b 285#ifdef OCCT_UWP
286 Standard_Mutex::Sentry aLock (THE_ENV_LOCK);
287 THE_ENV_MAP.Find (myName, myValue);
288#else
e87d0237 289
290 // msvc C-runtime (_wputenv()) puts variable using WinAPI internally (calls SetEnvironmentVariableW())
291 // and also caches its value in its own map,
292 // so that _wgetenv() ignores WinAPI and retieves variable from this cache.
293 //
294 // Using _wgetenv() might lead to awkward results in context when several C-runtimes are used
295 // at once within application or WinAPI is used directly for setting environment variable.
296 //
297 // Using _wputenv() + GetEnvironmentVariableW() pair should provide most robust behavior in tricky scenarios.
298 // So that _wgetenv() users will retrieve proper value set by OSD_Environment if used C-runtime library is the same as used by OCCT,
299 // 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,
300 // considering msvc C-runtime implementation details.
8582eb08 301 SetLastError (ERROR_SUCCESS);
8582eb08 302 NCollection_UtfWideString aNameWide (myName.ToCString());
303 DWORD aSize = GetEnvironmentVariableW (aNameWide.ToCString(), NULL, 0);
e87d0237 304 if (aSize == 0 && GetLastError() != ERROR_SUCCESS)
8582eb08 305 {
306 _set_error (myError, ERROR_ENVVAR_NOT_FOUND);
307 return myValue;
308 }
7fd59977 309
8582eb08 310 NCollection_Utf8String aValue;
e87d0237 311 aSize += 1; // NULL-terminator
312 wchar_t* aBuff = new wchar_t[aSize];
313 GetEnvironmentVariableW (aNameWide.ToCString(), aBuff, aSize);
314 aBuff[aSize - 1] = L'\0';
315 aValue.FromUnicode (aBuff);
316 delete[] aBuff;
317 Reset();
318
8582eb08 319 myValue = aValue.ToCString();
742cc8b0 320#endif
1ce0716b 321 return myValue;
8582eb08 322}
7fd59977 323
324void OSD_Environment :: SetName ( const TCollection_AsciiString& name ) {
325
326 myName = name;
327
328} // end OSD_Environment :: SetName
329
330TCollection_AsciiString OSD_Environment :: Name () const {
331
332 return myName;
333
334} // end OSD_Environment :: Name
335
8582eb08 336void OSD_Environment::Build()
337{
1ce0716b 338#ifdef OCCT_UWP
339 Standard_Mutex::Sentry aLock(THE_ENV_LOCK);
340 THE_ENV_MAP.Bind (myName, myValue);
341#else
8582eb08 342 NCollection_Utf8String aSetVariable = NCollection_Utf8String(myName.ToCString()) + "=" + myValue.ToCString();
343 _wputenv (aSetVariable.ToUtfWide().ToCString());
742cc8b0 344#endif
8582eb08 345}
7fd59977 346
8582eb08 347void OSD_Environment::Remove()
348{
1ce0716b 349#ifdef OCCT_UWP
350 Standard_Mutex::Sentry aLock(THE_ENV_LOCK);
351 THE_ENV_MAP.UnBind (myName);
352#else
8582eb08 353 NCollection_Utf8String aSetVariable = NCollection_Utf8String(myName.ToCString()) + "=";
354 _wputenv (aSetVariable.ToUtfWide().ToCString());
742cc8b0 355#endif
8582eb08 356}
7fd59977 357
358Standard_Boolean OSD_Environment :: Failed () const {
359
360 return myError.Failed ();
361
362} // end OSD_Environment :: Failed
363
364void OSD_Environment :: Reset () {
365
366 myError.Reset ();
367
368} // end OSD_Environment :: Reset
369
46802936 370void OSD_Environment :: Perror ()
371{
372 myError.Perror ();
7fd59977 373} // end OSD_Environment :: Perror
374
375Standard_Integer OSD_Environment :: Error () const {
376
377 return myError.Error ();
378
379} // end OSD_Environment :: Error
380
742cc8b0 381#ifndef OCCT_UWP
ad03c234 382static void __fastcall _set_error (OSD_Error& theErr, DWORD theCode)
383{
384 wchar_t aBuffer[2048];
385 const DWORD anErrCode = theCode != 0 ? theCode : GetLastError();
386 if (!FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
387 0, anErrCode, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ),
388 aBuffer, 2048, NULL))
389 {
390 theErr.SetValue (anErrCode, OSD_WEnvironment, TCollection_AsciiString ("error code ") + (Standard_Integer)anErrCode);
391 SetLastError (anErrCode);
392 }
393 else
394 {
395 theErr.SetValue (anErrCode, OSD_WEnvironment, TCollection_AsciiString (aBuffer));
396 }
397}
742cc8b0 398#endif
7fd59977 399
400#endif