![]() |
|
|
Generated: 18 Jul 2008 |
00001 // $Id: System.cpp,v 1.39 2008/06/05 10:04:53 marcocle Exp $ 00002 //==================================================================== 00003 // System.cpp 00004 //-------------------------------------------------------------------- 00005 // 00006 // Package : System (The LHCb System service) 00007 // 00008 // Description: Implementation of Systems internals 00009 // 00010 // Author : M.Frank 00011 // Created : 13/1/99 00012 // Changes : 00013 //==================================================================== 00014 #define SYSTEM_SYSTEM_CPP 00015 #include <ctime> 00016 #include <cstring> 00017 #include <cstdlib> 00018 #include <iostream> 00019 #include <typeinfo> 00020 00021 #include "GaudiKernel/System.h" 00022 00023 #ifdef _WIN32 00024 #define strcasecmp _stricmp 00025 #define strncasecmp _strnicmp 00026 #define getpid _getpid 00027 #define NOMSG 00028 #define NOGDI 00029 #include "process.h" 00030 #include "windows.h" 00031 #undef NOMSG 00032 #undef NOGDI 00033 static const char* SHLIB_SUFFIX = ".dll"; 00034 #else // UNIX...: first the EGCS stuff, then the OS dependent includes 00035 static const char* SHLIB_SUFFIX = ".so"; 00036 #include <errno.h> 00037 #include <string.h> 00038 #include "sys/times.h" 00039 #include "unistd.h" 00040 #include "libgen.h" 00041 #include <cstdio> 00042 #include <cxxabi.h> 00043 #if defined(linux) || defined(__APPLE__) 00044 #include "dlfcn.h" 00045 #include <sys/utsname.h> 00046 #include <unistd.h> 00047 #elif __hpux 00048 #include "dl.h" 00049 struct HMODULE { 00050 shl_descriptor dsc; 00051 long numSym; 00052 shl_symbol* sym; 00053 }; 00054 #endif 00055 00056 #endif 00057 00058 // Note: __attribute__ is a GCC keyword available since GCC 3.4 00059 #ifdef __GNUC__ 00060 # if __GNUC__ < 3 || \ 00061 (__GNUC__ == 3 && (__GNUC_MINOR__ < 4 )) 00062 // GCC < 3.4 00063 # define __attribute__(x) 00064 # endif 00065 #else 00066 // non-GCC 00067 # define __attribute__(x) 00068 #endif 00069 00070 static std::vector<std::string> s_argvStrings; 00071 static std::vector<const char*> s_argvChars; 00072 00073 static unsigned long doLoad(const std::string& name, System::ImageHandle* handle) { 00074 #ifdef _WIN32 00075 void* mh = ::LoadLibrary( name.length() == 0 ? System::exeName().c_str() : name.c_str()); 00076 *handle = mh; 00077 #else 00078 const char* path = name.c_str(); 00079 #if defined(linux) || defined(__APPLE__) 00080 void *mh = ::dlopen(name.length() == 0 ? 0 : path, RTLD_LAZY | RTLD_GLOBAL); 00081 *handle = mh; 00082 #elif __hpux 00083 shl_t mh = ::shl_load(name.length() == 0 ? 0 : path, BIND_IMMEDIATE | BIND_VERBOSE, 0); 00084 HMODULE* mod = new HMODULE; 00085 if ( 0 != mh ) { 00086 if ( 0 != ::shl_gethandle_r(mh, &mod->dsc) ) { 00087 std::cout << "System::loadDynamicLib>" << ::strerror(getLastError()) << std::endl; 00088 } 00089 else { 00090 typedef void* (*___all)(); 00091 ___all _alloc = (___all)malloc; 00092 mod->numSym = ::shl_getsymbols(mod->dsc.handle, TYPE_PROCEDURE, EXPORT_SYMBOLS, malloc, &mod->sym); 00093 *handle = mod; 00094 } 00095 } 00096 #endif 00097 #endif 00098 if ( 0 == *handle ) { 00099 return System::getLastError(); 00100 } 00101 return 1; 00102 } 00103 00104 static unsigned long loadWithoutEnvironment(const std::string& name, System::ImageHandle* handle) { 00105 00106 std::string dllName = name; 00107 long len = strlen(SHLIB_SUFFIX); 00108 00109 // Add the suffix at the end of the library name only if necessary 00110 // FIXME: cure the logic 00111 if ((dllName.length() != 0) && 00112 ::strncasecmp(dllName.data()+dllName.length()-len, SHLIB_SUFFIX, len) != 0) { 00113 dllName += SHLIB_SUFFIX; 00114 } 00115 00116 // Load the library 00117 return doLoad(dllName, handle); 00118 } 00119 00121 unsigned long System::loadDynamicLib(const std::string& name, ImageHandle* handle) { 00122 unsigned long res; 00123 // if name is empty, just load it 00124 if (name.length() == 0) { 00125 res = loadWithoutEnvironment(name, handle); 00126 } else { 00127 // If the name is a logical name (environment variable), the try 00128 // to load the corresponding library from there. 00129 std::string env = name; 00130 if ( 0 != ::getenv(env.c_str()) ) { 00131 std::string imgName = ::getenv(env.c_str()); 00132 res = loadWithoutEnvironment(imgName, handle); 00133 } else { 00134 // build the dll name 00135 std::string dllName = name; 00136 #if defined(linux) || defined(__APPLE__) 00137 dllName = "lib" + dllName; 00138 #endif 00139 dllName += SHLIB_SUFFIX; 00140 // try to locate the dll using the standard PATH 00141 res = loadWithoutEnvironment(dllName, handle); 00142 } 00143 if ( res != 1 ) { 00144 #if defined(linux) || defined(__APPLE__) 00145 errno = 0xAFFEDEAD; 00146 #endif 00147 // std::cout << "System::loadDynamicLib>" << getLastErrorString() << std::endl; 00148 } 00149 } 00150 return res; 00151 } 00152 00154 unsigned long System::unloadDynamicLib(ImageHandle handle) { 00155 #ifdef _WIN32 00156 if ( !::FreeLibrary((HINSTANCE)handle) ) { 00157 #elif defined(linux) || defined(__APPLE__) 00158 ::dlclose( handle ); 00159 if ( 0 ) { 00160 #elif __hpux 00161 // On HP we have to run finalization ourselves..... 00162 Creator pFinalize = 0; 00163 if ( getProcedureByName(handle, "_fini", &pFinalize) ) { 00164 pFinalize(); 00165 } 00166 HMODULE* mod = (HMODULE*)handle; 00167 if ( 0 == ::shl_unload( mod->dsc.handle ) ) { 00168 delete mod; 00169 } 00170 else { 00171 #endif 00172 return getLastError(); 00173 } 00174 return 1; 00175 } 00176 00178 unsigned long System::getProcedureByName(ImageHandle handle, const std::string& name, EntryPoint* pFunction) { 00179 #ifdef _WIN32 00180 *pFunction = (EntryPoint)::GetProcAddress((HINSTANCE)handle, name.data()); 00181 if ( 0 == *pFunction ) { 00182 return System::getLastError(); 00183 } 00184 return 1; 00185 #elif defined(linux) 00186 *pFunction = (EntryPoint)::dlsym(handle, name.c_str()); 00187 if ( 0 == *pFunction ) { 00188 errno = 0xAFFEDEAD; 00189 // std::cout << "System::getProcedureByName>" << getLastErrorString() << std::endl; 00190 return 0; 00191 } 00192 return 1; 00193 #elif defined(__APPLE__) 00194 *pFunction = (EntryPoint)::dlsym(handle, name.c_str()); 00195 if(!(*pFunction)) { 00196 // Try with an underscore : 00197 std::string sname = "_" + name; 00198 *pFunction = (EntryPoint)::dlsym(handle, sname.c_str()); 00199 } 00200 if ( 0 == *pFunction ) { 00201 errno = 0xAFFEDEAD; 00202 std::cout << "System::getProcedureByName>" << getLastErrorString() << std::endl; 00203 //std::cout << "System::getProcedureByName> failure" << std::endl; 00204 return 0; 00205 } 00206 return 1; 00207 #elif __hpux 00208 HMODULE* mod = (HMODULE*)handle; 00209 if ( 0 != mod ) { 00210 long ll1 = name.length(); 00211 for ( int i = 0; i < mod->numSym; i++ ) { 00212 long ll2 = strlen(mod->sym[i].name); 00213 if ( 0 != ::strncmp(mod->sym[i].name, name.c_str(), (ll1>ll2) ? ll1 : ll2)==0 ) { 00214 *pFunction = (EntryPoint) mod->sym[i].value; 00215 return 1; 00216 } 00217 } 00218 } 00219 return 0; 00220 #endif 00221 } 00222 00224 unsigned long System::getProcedureByName(ImageHandle handle, const std::string& name, Creator* pFunction) { 00225 return getProcedureByName(handle, name, (EntryPoint*)pFunction); 00226 } 00227 00229 unsigned long System::getLastError() { 00230 #ifdef _WIN32 00231 return ::GetLastError(); 00232 #else 00233 return static_cast<unsigned long>(errno); 00234 #endif 00235 } 00236 00238 const std::string System::getLastErrorString() { 00239 const std::string errString = getErrorString(getLastError()); 00240 return errString; 00241 } 00242 00244 const std::string System::getErrorString(unsigned long error) { 00245 std::string errString = ""; 00246 #ifdef _WIN32 00247 LPVOID lpMessageBuffer; 00248 ::FormatMessage( 00249 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 00250 NULL, 00251 error, 00252 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //The user default language 00253 (LPTSTR) &lpMessageBuffer, 00254 0, 00255 NULL ); 00256 errString = (const char*)lpMessageBuffer; 00257 // Free the buffer allocated by the system 00258 ::LocalFree( lpMessageBuffer ); 00259 #else 00260 char *cerrString(0); 00261 // Remember: for linux dl* routines must be handled differently! 00262 if ( error == 0xAFFEDEAD ) { 00263 cerrString = (char*)::dlerror(); 00264 if ( 0 == cerrString ) { 00265 cerrString = ::strerror(error); 00266 } 00267 if ( 0 == cerrString ) { 00268 cerrString = (char *)"Unknown error. No information found in strerror()!"; 00269 } 00270 else { 00271 errString = std::string(cerrString); 00272 } 00273 errno = 0; 00274 } 00275 else { 00276 cerrString = ::strerror(error); 00277 errString = std::string(cerrString); 00278 } 00279 #endif 00280 return errString; 00281 } 00282 00283 // This is a little bit complicated....but at least it gives 00284 // usable results: 00285 // Native class template: 00286 // Spac::templa<Spac::templa<Spac::templ<Spac::templa<AAA::a,Spac::templa<double,unsigned char>>>,B::bbb>,float> 00287 // is translated under egcs to the unreadable string: 00288 // Q24Spact6templa2ZQ24Spact6templa2ZQ24Spact5templ1ZQ24Spact6templa2ZQ23AAA1aZQ24Spact6templa2ZdZUcZQ21B3bbbZf 00289 00290 std::string __typeName(char*& name); 00291 std::string __className(char*& name) { 00292 std::string result; 00293 int j = 0, k, i; 00294 if ( 't' == *name ) { 00295 goto Template; 00296 } 00297 for ( i = ::strtol(name, &name, 10); i > 0; i = ::strtol(name, &name, 10) ) { 00298 if ( j++ != 0 ) result.append("::",2); 00299 result.append(name, i); 00300 if ( *(name+=i) == 't' ) { 00301 result.append("::",2); 00302 Template: 00303 result.append(name, (i=::strtol(++name, &name, 10))); 00304 result.append("<"); 00305 for (k = 0, i=::strtol(name+i, &name, 10); k < i; k++ ) { 00306 result += __typeName( ++name ); 00307 if ( k+1 < i ) result += ","; 00308 } 00309 result.append(">"); 00310 } 00311 } 00312 return result; 00313 } 00314 00315 std::string __typeName(char*& name) { 00316 if ( *name == 'Q' ) { // Handle name spaces 00317 if ( *(++name) == '_' ) // >= 10 nested name spaces 00318 ::strtol(++name, &name, 10); // type Q_##_... 00319 return __className(++name); 00320 } 00321 else if ( 't' == *name ) { 00322 return __className(name); 00323 } 00324 else { 00325 std::string result; 00326 char* ptr; 00327 int i = ::strtol(name, &ptr, 10); 00328 if ( i <= 0 ) { 00329 name = ptr; 00330 while ( *name != 0 && *name != 'Z' ) { 00331 if ( *name == 'U' ) { 00332 result += "unsigned "; 00333 name++; 00334 } 00335 switch( *name++ ) { 00336 case 'c': result += "char"; break; 00337 case 's': result += "short"; break; 00338 case 'i': result += "int"; break; 00339 case 'l': result += "long"; break; 00340 case 'f': result += "float"; break; 00341 case 'd': result += "double"; break; 00342 default: result += *(name-1); 00343 } 00344 } 00345 return result; 00346 } 00347 else { 00348 return __className(name); 00349 } 00350 } 00351 } 00352 const std::string System::typeinfoName( const std::type_info& tinfo) { 00353 return typeinfoName(tinfo.name()); 00354 } 00355 const std::string System::typeinfoName( const char* class_name) { 00356 std::string result; 00357 #ifdef _WIN32 00358 long off = 0; 00359 if ( ::strncmp(class_name, "class ", 6) == 0 ) { 00360 // The returned name is prefixed with "class " 00361 off = 6; 00362 } 00363 if ( ::strncmp(class_name, "struct ", 7) == 0 ) { 00364 // The returned name is prefixed with "struct " 00365 off = 7; 00366 } 00367 if ( off > 0 ) { 00368 std::string tmp = class_name + off; 00369 long loc = 0; 00370 while( (loc = tmp.find("class ")) > 0 ) { 00371 tmp.erase(loc, 6); 00372 } 00373 loc = 0; 00374 while( (loc = tmp.find("struct ")) > 0 ) { 00375 tmp.erase(loc, 7); 00376 } 00377 result = tmp; 00378 } 00379 else { 00380 result = class_name; 00381 } 00382 // Change any " *" to "*" 00383 while ( (off=result.find(" *")) != std::string::npos ) { 00384 result.replace(off, 2, "*"); 00385 } 00386 // Change any " &" to "&" 00387 while ( (off=result.find(" &")) != std::string::npos ) { 00388 result.replace(off, 2, "&"); 00389 } 00390 00391 #elif defined(__linux) || defined(__APPLE__) 00392 if ( ::strlen(class_name) == 1 ) { 00393 // See http://www.realitydiluted.com/mirrors/reality.sgi.com/dehnert_engr/cxx/abi.pdf 00394 // for details 00395 switch(class_name[0]) { 00396 case 'v': 00397 result = "void"; 00398 break; 00399 case 'w': 00400 result = "wchar_t"; 00401 break; 00402 case 'b': 00403 result = "bool"; 00404 break; 00405 case 'c': 00406 result = "char"; 00407 break; 00408 case 'h': 00409 result = "unsigned char"; 00410 break; 00411 case 's': 00412 result = "short"; 00413 break; 00414 case 't': 00415 result = "unsigned short"; 00416 break; 00417 case 'i': 00418 result = "int"; 00419 break; 00420 case 'j': 00421 result = "unsigned int"; 00422 break; 00423 case 'l': 00424 result = "long"; 00425 break; 00426 case 'm': 00427 result = "unsigned long"; 00428 break; 00429 case 'x': 00430 result = "long long"; 00431 break; 00432 case 'y': 00433 result = "unsigned long long"; 00434 break; 00435 case 'n': 00436 result = "__int128"; 00437 break; 00438 case 'o': 00439 result = "unsigned __int128"; 00440 break; 00441 case 'f': 00442 result = "float"; 00443 break; 00444 case 'd': 00445 result = "double"; 00446 break; 00447 case 'e': 00448 result = "long double"; 00449 break; 00450 case 'g': 00451 result = "__float128"; 00452 break; 00453 case 'z': 00454 result = "ellipsis"; 00455 break; 00456 } 00457 } 00458 else { 00459 int status; 00460 char* realname; 00461 realname = abi::__cxa_demangle(class_name, 0, 0, &status); 00462 if (realname == 0) return class_name; 00463 result = realname; 00464 free(realname); 00466 std::string::size_type pos = result.find(", "); 00467 while( std::string::npos != pos ) { 00468 result.replace( pos , 2 , "," ) ; 00469 pos = result.find(", "); 00470 } 00471 } 00472 #endif 00473 return result; 00474 } 00475 00477 const std::string& System::hostName() { 00478 static std::string host = ""; 00479 if ( host == "" ) { 00480 char buffer[512]; 00481 memset(buffer,0,sizeof(buffer)); 00482 #ifdef _WIN32 00483 unsigned long len = sizeof(buffer); 00484 ::GetComputerName(buffer, &len); 00485 #else 00486 ::gethostname(buffer, sizeof(buffer)); 00487 #endif 00488 host = buffer; 00489 } 00490 return host; 00491 } 00492 00494 const std::string& System::osName() { 00495 static std::string osname = ""; 00496 #ifdef _WIN32 00497 osname = "Windows"; 00498 #else 00499 struct utsname ut; 00500 if (uname(&ut) == 0) { 00501 osname = ut.sysname; 00502 } else { 00503 osname = "UNKNOWN"; 00504 } 00505 #endif 00506 return osname; 00507 } 00508 00509 00511 const std::string& System::osVersion() { 00512 static std::string osver = ""; 00513 #ifdef _WIN32 00514 OSVERSIONINFO ut; 00515 ut.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 00516 ::GetVersionEx(&ut); 00517 char ver[64]; 00518 sprintf(ver,"%d.%d",ut.dwMajorVersion,ut.dwMinorVersion); 00519 osver = ver; 00520 #else 00521 struct utsname ut; 00522 if (uname(&ut) == 0) { 00523 osver = ut.release; 00524 } else { 00525 osver = "UNKNOWN"; 00526 } 00527 #endif 00528 return osver; 00529 } 00530 00532 const std::string& System::machineType() { 00533 static std::string mach = ""; 00534 #ifdef _WIN32 00535 SYSTEM_INFO ut; 00536 ::GetSystemInfo(&ut); 00537 char arch[64]; 00538 sprintf(arch,"%d",ut.wProcessorArchitecture); 00539 mach = arch; 00540 #else 00541 struct utsname ut; 00542 if (uname(&ut) == 0) { 00543 mach = ut.machine; 00544 } else { 00545 mach = "UNKNOWN"; 00546 } 00547 #endif 00548 return mach; 00549 } 00550 00552 const std::string& System::accountName() { 00553 static std::string account = ""; 00554 if ( account == "" ) { 00555 #ifdef _WIN32 00556 char buffer[512]; 00557 unsigned long buflen = sizeof(buffer); 00558 ::GetUserName(buffer, &buflen); 00559 account = buffer; 00560 #else 00561 const char* acct = ::getlogin(); 00562 if ( 0 == acct ) acct = ::getenv("LOGNAME"); 00563 if ( 0 == acct ) acct = ::getenv("USER"); 00564 account = (acct) ? acct : "Unknown"; 00565 #endif 00566 } 00567 return account; 00568 } 00569 00571 long System::numCmdLineArgs() { 00572 return cmdLineArgs().size(); 00573 } 00574 00576 long System::argc() { 00577 return cmdLineArgs().size(); 00578 } 00579 00581 const std::vector<std::string> System::cmdLineArgs() { 00582 if ( s_argvChars.size() == 0 ) { 00583 char exe[1024]; 00584 #ifdef _WIN32 00585 // For compatibility with UNIX we CANNOT use strtok! 00586 // If we would use strtok, options like -g="My world" at 00587 // the command line level would result on NT in TWO options 00588 // instead in one as in UNIX. 00589 char *next, *tmp1, *tmp2; 00590 for(LPTSTR cmd = ::GetCommandLine(); *cmd; cmd=next) { 00591 memset(exe,0,sizeof(exe)); 00592 while ( *cmd == ' ' ) cmd++; 00593 next=::strchr(cmd,' '); 00594 if ( !next ) next = cmd + strlen(cmd); 00595 if ( (tmp1=::strchr(cmd,'\"')) > 0 && tmp1 < next ) { 00596 tmp2 = ::strchr(++tmp1,'\"'); 00597 if ( tmp2 > 0 ) { 00598 next = ++tmp2; 00599 if ( cmd < tmp1 ) strncpy(exe, cmd, tmp1-cmd-1); 00600 strncpy(&exe[strlen(exe)], tmp1, tmp2-tmp1-1); 00601 } 00602 else { 00603 std::cout << "Mismatched \" in command line arguments" << std::endl; 00604 s_argvChars.erase(s_argvChars.begin(), s_argvChars.end()); 00605 s_argvStrings.erase(s_argvStrings.begin(), s_argvStrings.end()); 00606 return s_argvStrings; 00607 } 00608 } 00609 else { 00610 strncpy(exe, cmd, next-cmd); 00611 } 00612 s_argvStrings.push_back(exe); 00613 s_argvChars.push_back( s_argvStrings.back().c_str()); 00614 } 00615 #elif defined(linux) || defined(__APPLE__) 00616 sprintf(exe, "/proc/%d/cmdline", ::getpid()); 00617 FILE *cmdLine = ::fopen(exe,"r"); 00618 char cmd[1024]; 00619 if ( cmdLine ) { 00620 long len = fread(cmd, sizeof(char), sizeof(cmd), cmdLine); 00621 if ( len > 0 ) { 00622 cmd[len] = 0; 00623 for ( char* token = cmd; token-cmd < len; token += strlen(token)+1 ) { 00624 s_argvStrings.push_back(token); 00625 s_argvChars.push_back( s_argvStrings.back().c_str()); 00626 } 00627 s_argvStrings[0] = exeName(); 00628 s_argvChars[0] = s_argvStrings[0].c_str(); 00629 } 00630 } 00631 ::fclose(cmdLine); 00632 #endif 00633 } 00634 return s_argvStrings; 00635 } 00636 00638 char** System::argv() { 00640 if( s_argvChars.empty() ) { cmdLineArgs(); } 00641 00642 // We rely here on the fact that a vector's allocation table is contiguous 00643 return (char**)&s_argvChars[0]; 00644 } 00645 00647 const std::string System::getEnv(const char* var) { 00648 char* env; 00649 if ( (env = getenv(var)) != 0 ) { 00650 return env; 00651 } else { 00652 return "UNKNOWN"; 00653 } 00654 } 00655 00657 #if defined(__APPLE__) 00658 // Needed for _NSGetEnviron(void) 00659 #include "crt_externs.h" 00660 #endif 00661 const std::vector<std::string> System::getEnv() { 00662 #if defined(_WIN32) 00663 # define environ _environ 00664 #elif defined(linux) 00665 extern char **environ; 00666 #elif defined(__APPLE__) 00667 static char **environ = *_NSGetEnviron(); 00668 #endif 00669 std::vector<std::string> vars; 00670 for (int i=0; environ[i] != 0; ++i) { 00671 vars.push_back(environ[i]); 00672 } 00673 return vars; 00674 } 00675 00676 bool System::backTrace(void** addresses __attribute__ ((unused)), 00677 const size_t depth __attribute__ ((unused))) 00678 { 00679 00680 #ifdef __linux 00681 00682 if ( backtrace( addresses, depth ) > 0 ) { 00683 return true ; 00684 } else { 00685 return false ; 00686 } 00687 00688 #else // windows and osx parts not implemented 00689 return false ; 00690 #endif 00691 00692 } 00693 00694 00695 00696 bool System::getStackLevel(void* addresses __attribute__ ((unused)), 00697 void*& addr __attribute__ ((unused)), 00698 std::string& fnc __attribute__ ((unused)), 00699 std::string& lib __attribute__ ((unused))) 00700 { 00701 00702 #ifdef __linux 00703 00704 Dl_info info; 00705 00706 if ( dladdr( addresses, &info ) && info.dli_fname 00707 && info.dli_fname[0] != '\0' ) { 00708 const char* symbol = info.dli_sname 00709 && info.dli_sname[0] != '\0' ? info.dli_sname : 0; 00710 00711 lib = info.dli_fname; 00712 addr = info.dli_saddr; 00713 const char* dmg(0); 00714 00715 if (symbol != 0) { 00716 int stat; 00717 dmg = abi::__cxa_demangle(symbol,0,0,&stat); 00718 fnc = (stat == 0) ? dmg : symbol; 00719 } else { 00720 fnc = "local"; 00721 } 00722 free((void*)dmg); 00723 return true ; 00724 } else { 00725 return false ; 00726 } 00727 00728 #else // not implemented for windows and osx 00729 return false ; 00730 #endif 00731 00732 } 00733 00735 int System::setEnv(const std::string &name, const std::string &value, int overwrite) 00736 { 00737 #ifndef WIN32 00738 // UNIX version 00739 return value.empty() ? 00740 // remove if set to nothing (and return success) 00741 ::unsetenv(name.c_str()) , 0 : 00742 // set the value 00743 ::setenv(name.c_str(),value.c_str(), overwrite); 00744 #else 00745 // Windows version 00746 if ( value.empty() ) { 00747 // equivalent to unsetenv 00748 return ::_putenv((name+"=").c_str()); 00749 } 00750 else { 00751 if ( !getenv(name.c_str()) || overwrite ) { 00752 // set if not yet present or overwrite is set (force) 00753 return ::_putenv((name+"="+value).c_str()); 00754 } 00755 } 00756 return 0; // if we get here, we are trying to set a variable already set, but 00757 // not to overwrite. 00758 // It is considered a success on Linux (man P setenv) 00759 #endif 00760 00761 } 00762