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