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 #else
00174 if (false){
00175 #endif
00176 return getLastError();
00177 }
00178 return 1;
00179 }
00180
00182 unsigned long System::getProcedureByName(ImageHandle handle, const std::string& name, EntryPoint* pFunction) {
00183 #ifdef _WIN32
00184 *pFunction = (EntryPoint)::GetProcAddress((HINSTANCE)handle, name.data());
00185 if ( 0 == *pFunction ) {
00186 return System::getLastError();
00187 }
00188 return 1;
00189 #elif defined(linux)
00190 #if __GNUC__ < 4
00191 *pFunction = (EntryPoint)::dlsym(handle, name.c_str());
00192 #else
00193 *pFunction = FuncPtrCast<EntryPoint>(::dlsym(handle, name.c_str()));
00194 #endif
00195 if ( 0 == *pFunction ) {
00196 errno = 0xAFFEDEAD;
00197
00198 return 0;
00199 }
00200 return 1;
00201 #elif defined(__APPLE__)
00202 *pFunction = (EntryPoint)::dlsym(handle, name.c_str());
00203 if(!(*pFunction)) {
00204
00205 std::string sname = "_" + name;
00206 *pFunction = (EntryPoint)::dlsym(handle, sname.c_str());
00207 }
00208 if ( 0 == *pFunction ) {
00209 errno = 0xAFFEDEAD;
00210 std::cout << "System::getProcedureByName>" << getLastErrorString() << std::endl;
00211
00212 return 0;
00213 }
00214 return 1;
00215 #elif __hpux
00216 HMODULE* mod = (HMODULE*)handle;
00217 if ( 0 != mod ) {
00218 long ll1 = name.length();
00219 for ( int i = 0; i < mod->numSym; i++ ) {
00220 long ll2 = strlen(mod->sym[i].name);
00221 if ( 0 != ::strncmp(mod->sym[i].name, name.c_str(), (ll1>ll2) ? ll1 : ll2)==0 ) {
00222 *pFunction = (EntryPoint) mod->sym[i].value;
00223 return 1;
00224 }
00225 }
00226 }
00227 return 0;
00228 #endif
00229 }
00230
00232 unsigned long System::getProcedureByName(ImageHandle handle, const std::string& name, Creator* pFunction) {
00233 return getProcedureByName(handle, name, (EntryPoint*)pFunction);
00234 }
00235
00237 unsigned long System::getLastError() {
00238 #ifdef _WIN32
00239 return ::GetLastError();
00240 #else
00241
00242 return static_cast<unsigned long>(static_cast<unsigned int>(errno));
00243 #endif
00244 }
00245
00247 const std::string System::getLastErrorString() {
00248 const std::string errString = getErrorString(getLastError());
00249 return errString;
00250 }
00251
00253 const std::string System::getErrorString(unsigned long error) {
00254 std::string errString = "";
00255 #ifdef _WIN32
00256 LPVOID lpMessageBuffer;
00257 ::FormatMessage(
00258 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
00259 NULL,
00260 error,
00261 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00262 (LPTSTR) &lpMessageBuffer,
00263 0,
00264 NULL );
00265 errString = (const char*)lpMessageBuffer;
00266
00267 ::LocalFree( lpMessageBuffer );
00268 #else
00269 char *cerrString(0);
00270
00271 if ( error == 0xAFFEDEAD ) {
00272 cerrString = (char*)::dlerror();
00273 if ( 0 == cerrString ) {
00274 cerrString = ::strerror(error);
00275 }
00276 if ( 0 == cerrString ) {
00277 cerrString = (char *)"Unknown error. No information found in strerror()!";
00278 }
00279 else {
00280 errString = std::string(cerrString);
00281 }
00282 errno = 0;
00283 }
00284 else {
00285 cerrString = ::strerror(error);
00286 errString = std::string(cerrString);
00287 }
00288 #endif
00289 return errString;
00290 }
00291
00292
00293
00294
00295
00296
00297
00298
00299 std::string __typeName(char*& name);
00300 std::string __className(char*& name) {
00301 std::string result;
00302 int j = 0, k, i;
00303 if ( 't' == *name ) {
00304 goto Template;
00305 }
00306 for ( i = ::strtol(name, &name, 10); i > 0; i = ::strtol(name, &name, 10) ) {
00307 if ( j++ != 0 ) result.append("::",2);
00308 result.append(name, i);
00309 if ( *(name+=i) == 't' ) {
00310 result.append("::",2);
00311 Template:
00312 result.append(name, (i=::strtol(++name, &name, 10)));
00313 result.append("<");
00314 for (k = 0, i=::strtol(name+i, &name, 10); k < i; k++ ) {
00315 result += __typeName( ++name );
00316 if ( k+1 < i ) result += ",";
00317 }
00318 result.append(">");
00319 }
00320 }
00321 return result;
00322 }
00323
00324 std::string __typeName(char*& name) {
00325 if ( *name == 'Q' ) {
00326 if ( *(++name) == '_' )
00327 ::strtol(++name, &name, 10);
00328 return __className(++name);
00329 }
00330 else if ( 't' == *name ) {
00331 return __className(name);
00332 }
00333 else {
00334 std::string result;
00335 char* ptr;
00336 long i = ::strtol(name, &ptr, 10);
00337 if ( i <= 0 ) {
00338 name = ptr;
00339 while ( *name != 0 && *name != 'Z' ) {
00340 if ( *name == 'U' ) {
00341 result += "unsigned ";
00342 name++;
00343 }
00344 switch( *name++ ) {
00345 case 'c': result += "char"; break;
00346 case 's': result += "short"; break;
00347 case 'i': result += "int"; break;
00348 case 'l': result += "long"; break;
00349 case 'f': result += "float"; break;
00350 case 'd': result += "double"; break;
00351 default: result += *(name-1);
00352 }
00353 }
00354 return result;
00355 }
00356 else {
00357 return __className(name);
00358 }
00359 }
00360 }
00361 const std::string System::typeinfoName( const std::type_info& tinfo) {
00362 return typeinfoName(tinfo.name());
00363 }
00364 const std::string System::typeinfoName( const char* class_name) {
00365 std::string result;
00366 #ifdef _WIN32
00367 long off = 0;
00368 if ( ::strncmp(class_name, "class ", 6) == 0 ) {
00369
00370 off = 6;
00371 }
00372 if ( ::strncmp(class_name, "struct ", 7) == 0 ) {
00373
00374 off = 7;
00375 }
00376 if ( off > 0 ) {
00377 std::string tmp = class_name + off;
00378 long loc = 0;
00379 while( (loc = tmp.find("class ")) > 0 ) {
00380 tmp.erase(loc, 6);
00381 }
00382 loc = 0;
00383 while( (loc = tmp.find("struct ")) > 0 ) {
00384 tmp.erase(loc, 7);
00385 }
00386 result = tmp;
00387 }
00388 else {
00389 result = class_name;
00390 }
00391
00392 while ( (off=result.find(" *")) != std::string::npos ) {
00393 result.replace(off, 2, "*");
00394 }
00395
00396 while ( (off=result.find(" &")) != std::string::npos ) {
00397 result.replace(off, 2, "&");
00398 }
00399
00400 #elif defined(__linux) || defined(__APPLE__)
00401 if ( ::strlen(class_name) == 1 ) {
00402
00403
00404 switch(class_name[0]) {
00405 case 'v':
00406 result = "void";
00407 break;
00408 case 'w':
00409 result = "wchar_t";
00410 break;
00411 case 'b':
00412 result = "bool";
00413 break;
00414 case 'c':
00415 result = "char";
00416 break;
00417 case 'a':
00418 result = "signed char";
00419 break;
00420 case 'h':
00421 result = "unsigned char";
00422 break;
00423 case 's':
00424 result = "short";
00425 break;
00426 case 't':
00427 result = "unsigned short";
00428 break;
00429 case 'i':
00430 result = "int";
00431 break;
00432 case 'j':
00433 result = "unsigned int";
00434 break;
00435 case 'l':
00436 result = "long";
00437 break;
00438 case 'm':
00439 result = "unsigned long";
00440 break;
00441 case 'x':
00442 result = "long long";
00443 break;
00444 case 'y':
00445 result = "unsigned long long";
00446 break;
00447 case 'n':
00448 result = "__int128";
00449 break;
00450 case 'o':
00451 result = "unsigned __int128";
00452 break;
00453 case 'f':
00454 result = "float";
00455 break;
00456 case 'd':
00457 result = "double";
00458 break;
00459 case 'e':
00460 result = "long double";
00461 break;
00462 case 'g':
00463 result = "__float128";
00464 break;
00465 case 'z':
00466 result = "ellipsis";
00467 break;
00468 }
00469 }
00470 else {
00471 int status;
00472 char* realname;
00473 realname = abi::__cxa_demangle(class_name, 0, 0, &status);
00474 if (realname == 0) return class_name;
00475 result = realname;
00476 free(realname);
00478 std::string::size_type pos = result.find(", ");
00479 while( std::string::npos != pos ) {
00480 result.replace( pos , 2 , "," ) ;
00481 pos = result.find(", ");
00482 }
00483 }
00484 #endif
00485 return result;
00486 }
00487
00489 const std::string& System::hostName() {
00490 static std::string host = "";
00491 if ( host == "" ) {
00492 char buffer[512];
00493 memset(buffer,0,sizeof(buffer));
00494 #ifdef _WIN32
00495 unsigned long len = sizeof(buffer);
00496 ::GetComputerName(buffer, &len);
00497 #else
00498 ::gethostname(buffer, sizeof(buffer));
00499 #endif
00500 host = buffer;
00501 }
00502 return host;
00503 }
00504
00506 const std::string& System::osName() {
00507 static std::string osname = "";
00508 #ifdef _WIN32
00509 osname = "Windows";
00510 #else
00511 struct utsname ut;
00512 if (uname(&ut) == 0) {
00513 osname = ut.sysname;
00514 } else {
00515 osname = "UNKNOWN";
00516 }
00517 #endif
00518 return osname;
00519 }
00520
00521
00523 const std::string& System::osVersion() {
00524 static std::string osver = "";
00525 #ifdef _WIN32
00526 OSVERSIONINFO ut;
00527 ut.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
00528 ::GetVersionEx(&ut);
00529 char ver[64];
00530 sprintf(ver,"%d.%d",ut.dwMajorVersion,ut.dwMinorVersion);
00531 osver = ver;
00532 #else
00533 struct utsname ut;
00534 if (uname(&ut) == 0) {
00535 osver = ut.release;
00536 } else {
00537 osver = "UNKNOWN";
00538 }
00539 #endif
00540 return osver;
00541 }
00542
00544 const std::string& System::machineType() {
00545 static std::string mach = "";
00546 #ifdef _WIN32
00547 SYSTEM_INFO ut;
00548 ::GetSystemInfo(&ut);
00549 char arch[64];
00550 sprintf(arch,"%d",ut.wProcessorArchitecture);
00551 mach = arch;
00552 #else
00553 struct utsname ut;
00554 if (uname(&ut) == 0) {
00555 mach = ut.machine;
00556 } else {
00557 mach = "UNKNOWN";
00558 }
00559 #endif
00560 return mach;
00561 }
00562
00564 const std::string& System::accountName() {
00565 static std::string account = "";
00566 if ( account == "" ) {
00567 #ifdef _WIN32
00568 char buffer[512];
00569 unsigned long buflen = sizeof(buffer);
00570 ::GetUserName(buffer, &buflen);
00571 account = buffer;
00572 #else
00573 const char* acct = ::getlogin();
00574 if ( 0 == acct ) acct = ::getenv("LOGNAME");
00575 if ( 0 == acct ) acct = ::getenv("USER");
00576 account = (acct) ? acct : "Unknown";
00577 #endif
00578 }
00579 return account;
00580 }
00581
00583 long System::numCmdLineArgs() {
00584 return cmdLineArgs().size();
00585 }
00586
00588 long System::argc() {
00589 return cmdLineArgs().size();
00590 }
00591
00593 const std::vector<std::string> System::cmdLineArgs() {
00594 if ( s_argvChars.size() == 0 ) {
00595 char exe[1024];
00596 #ifdef _WIN32
00597
00598
00599
00600
00601 char *next, *tmp1, *tmp2;
00602 for(LPTSTR cmd = ::GetCommandLine(); *cmd; cmd=next) {
00603 memset(exe,0,sizeof(exe));
00604 while ( *cmd == ' ' ) cmd++;
00605 next=::strchr(cmd,' ');
00606 if ( !next ) next = cmd + strlen(cmd);
00607 if ( (tmp1=::strchr(cmd,'\"')) > 0 && tmp1 < next ) {
00608 tmp2 = ::strchr(++tmp1,'\"');
00609 if ( tmp2 > 0 ) {
00610 next = ++tmp2;
00611 if ( cmd < tmp1 ) strncpy(exe, cmd, tmp1-cmd-1);
00612 strncpy(&exe[strlen(exe)], tmp1, tmp2-tmp1-1);
00613 }
00614 else {
00615 std::cout << "Mismatched \" in command line arguments" << std::endl;
00616 s_argvChars.erase(s_argvChars.begin(), s_argvChars.end());
00617 s_argvStrings.erase(s_argvStrings.begin(), s_argvStrings.end());
00618 return s_argvStrings;
00619 }
00620 }
00621 else {
00622 strncpy(exe, cmd, next-cmd);
00623 }
00624 s_argvStrings.push_back(exe);
00625 s_argvChars.push_back( s_argvStrings.back().c_str());
00626 }
00627 #elif defined(linux) || defined(__APPLE__)
00628 sprintf(exe, "/proc/%d/cmdline", ::getpid());
00629 FILE *cmdLine = ::fopen(exe,"r");
00630 char cmd[1024];
00631 if ( cmdLine ) {
00632 long len = fread(cmd, sizeof(char), sizeof(cmd), cmdLine);
00633 if ( len > 0 ) {
00634 cmd[len] = 0;
00635 for ( char* token = cmd; token-cmd < len; token += strlen(token)+1 ) {
00636 s_argvStrings.push_back(token);
00637 s_argvChars.push_back( s_argvStrings.back().c_str());
00638 }
00639 s_argvStrings[0] = exeName();
00640 s_argvChars[0] = s_argvStrings[0].c_str();
00641 }
00642 }
00643 ::fclose(cmdLine);
00644 #endif
00645 }
00646 return s_argvStrings;
00647 }
00648
00650 char** System::argv() {
00652 if( s_argvChars.empty() ) { cmdLineArgs(); }
00653
00654
00655 return (char**)&s_argvChars[0];
00656 }
00657
00659 const std::string System::getEnv(const char* var) {
00660 char* env;
00661 if ( (env = getenv(var)) != 0 ) {
00662 return env;
00663 } else {
00664 return "UNKNOWN";
00665 }
00666 }
00667
00669 #if defined(__APPLE__)
00670
00671 #include "crt_externs.h"
00672 #endif
00673 const std::vector<std::string> System::getEnv() {
00674 #if defined(_WIN32)
00675 # define environ _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 }