00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
00061 #ifdef __GNUC__
00062 # if __GNUC__ < 3 || \
00063 (__GNUC__ == 3 && (__GNUC_MINOR__ < 4 ))
00064
00065 # define __attribute__(x)
00066 # endif
00067 #else
00068
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
00112
00113 if ((dllName.length() != 0) &&
00114 ::strncasecmp(dllName.data()+dllName.length()-len, SHLIB_SUFFIX, len) != 0) {
00115 dllName += SHLIB_SUFFIX;
00116 }
00117
00118
00119 return doLoad(dllName, handle);
00120 }
00121
00123 unsigned long System::loadDynamicLib(const std::string& name, ImageHandle* handle) {
00124 unsigned long res;
00125
00126 if (name.length() == 0) {
00127 res = loadWithoutEnvironment(name, handle);
00128 } else {
00129
00130
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
00137 std::string dllName = name;
00138 #if defined(linux) || defined(__APPLE__)
00139 dllName = "lib" + dllName;
00140 #endif
00141 dllName += SHLIB_SUFFIX;
00142
00143 res = loadWithoutEnvironment(dllName, handle);
00144 }
00145 if ( res != 1 ) {
00146 #if defined(linux) || defined(__APPLE__)
00147 errno = 0xAFFEDEAD;
00148 #endif
00149
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
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
00196 return 0;
00197 }
00198 return 1;
00199 #elif defined(__APPLE__)
00200 *pFunction = (EntryPoint)::dlsym(handle, name.c_str());
00201 if(!(*pFunction)) {
00202
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
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
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),
00260 (LPTSTR) &lpMessageBuffer,
00261 0,
00262 NULL );
00263 errString = (const char*)lpMessageBuffer;
00264
00265 ::LocalFree( lpMessageBuffer );
00266 #else
00267 char *cerrString(0);
00268
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
00291
00292
00293
00294
00295
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' ) {
00324 if ( *(++name) == '_' )
00325 ::strtol(++name, &name, 10);
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
00368 off = 6;
00369 }
00370 if ( ::strncmp(class_name, "struct ", 7) == 0 ) {
00371
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
00390 while ( (off=result.find(" *")) != std::string::npos ) {
00391 result.replace(off, 2, "*");
00392 }
00393
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
00401
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
00596
00597
00598
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
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
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
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
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
00786 return value.empty() ?
00787
00788 ::unsetenv(name.c_str()) , 0 :
00789
00790 ::setenv(name.c_str(),value.c_str(), overwrite);
00791 #else
00792
00793 if ( value.empty() ) {
00794
00795 return ::_putenv((name+"=").c_str());
00796 }
00797 else {
00798 if ( !getenv(name.c_str()) || overwrite ) {
00799
00800 return ::_putenv((name+"="+value).c_str());
00801 }
00802 }
00803 return 0;
00804
00805
00806 #endif
00807
00808 }