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 imgName;
00132 if ( getEnv(name, imgName) ) {
00133 res = loadWithoutEnvironment(imgName, handle);
00134 } else {
00135
00136 std::string dllName = name;
00137 #if defined(linux) || defined(__APPLE__)
00138 dllName = "lib" + dllName;
00139 #endif
00140 dllName += SHLIB_SUFFIX;
00141
00142 res = loadWithoutEnvironment(dllName, handle);
00143 }
00144 if ( res != 1 ) {
00145 #if defined(linux) || defined(__APPLE__)
00146 errno = 0xAFFEDEAD;
00147 #endif
00148
00149 }
00150 }
00151 return res;
00152 }
00153
00155 unsigned long System::unloadDynamicLib(ImageHandle handle) {
00156 #ifdef _WIN32
00157 if ( !::FreeLibrary((HINSTANCE)handle) ) {
00158 #elif defined(linux) || defined(__APPLE__)
00159 ::dlclose( handle );
00160 if ( 0 ) {
00161 #elif __hpux
00162
00163 Creator pFinalize = 0;
00164 if ( getProcedureByName(handle, "_fini", &pFinalize) ) {
00165 pFinalize();
00166 }
00167 HMODULE* mod = (HMODULE*)handle;
00168 if ( 0 == ::shl_unload( mod->dsc.handle ) ) {
00169 delete mod;
00170 }
00171 else {
00172 #else
00173 if (false){
00174 #endif
00175 return getLastError();
00176 }
00177 return 1;
00178 }
00179
00181 unsigned long System::getProcedureByName(ImageHandle handle, const std::string& name, EntryPoint* pFunction) {
00182 #ifdef _WIN32
00183 *pFunction = (EntryPoint)::GetProcAddress((HINSTANCE)handle, name.data());
00184 if ( 0 == *pFunction ) {
00185 return System::getLastError();
00186 }
00187 return 1;
00188 #elif defined(linux)
00189 #if __GNUC__ < 4
00190 *pFunction = (EntryPoint)::dlsym(handle, name.c_str());
00191 #else
00192 *pFunction = FuncPtrCast<EntryPoint>(::dlsym(handle, name.c_str()));
00193 #endif
00194 if ( 0 == *pFunction ) {
00195 errno = 0xAFFEDEAD;
00196
00197 return 0;
00198 }
00199 return 1;
00200 #elif defined(__APPLE__)
00201 *pFunction = (EntryPoint)::dlsym(handle, name.c_str());
00202 if(!(*pFunction)) {
00203
00204 std::string sname = "_" + name;
00205 *pFunction = (EntryPoint)::dlsym(handle, sname.c_str());
00206 }
00207 if ( 0 == *pFunction ) {
00208 errno = 0xAFFEDEAD;
00209 std::cout << "System::getProcedureByName>" << getLastErrorString() << std::endl;
00210
00211 return 0;
00212 }
00213 return 1;
00214 #elif __hpux
00215 HMODULE* mod = (HMODULE*)handle;
00216 if ( 0 != mod ) {
00217 long ll1 = name.length();
00218 for ( int i = 0; i < mod->numSym; i++ ) {
00219 long ll2 = strlen(mod->sym[i].name);
00220 if ( 0 != ::strncmp(mod->sym[i].name, name.c_str(), (ll1>ll2) ? ll1 : ll2)==0 ) {
00221 *pFunction = (EntryPoint) mod->sym[i].value;
00222 return 1;
00223 }
00224 }
00225 }
00226 return 0;
00227 #endif
00228 }
00229
00231 unsigned long System::getProcedureByName(ImageHandle handle, const std::string& name, Creator* pFunction) {
00232 return getProcedureByName(handle, name, (EntryPoint*)pFunction);
00233 }
00234
00236 unsigned long System::getLastError() {
00237 #ifdef _WIN32
00238 return ::GetLastError();
00239 #else
00240
00241 return static_cast<unsigned long>(static_cast<unsigned int>(errno));
00242 #endif
00243 }
00244
00246 const std::string System::getLastErrorString() {
00247 const std::string errString = getErrorString(getLastError());
00248 return errString;
00249 }
00250
00252 const std::string System::getErrorString(unsigned long error) {
00253 std::string errString = "";
00254 #ifdef _WIN32
00255 LPVOID lpMessageBuffer;
00256 ::FormatMessage(
00257 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
00258 NULL,
00259 error,
00260 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00261 (LPTSTR) &lpMessageBuffer,
00262 0,
00263 NULL );
00264 errString = (const char*)lpMessageBuffer;
00265
00266 ::LocalFree( lpMessageBuffer );
00267 #else
00268 char *cerrString(0);
00269
00270 if ( error == 0xAFFEDEAD ) {
00271 cerrString = (char*)::dlerror();
00272 if ( 0 == cerrString ) {
00273 cerrString = ::strerror(error);
00274 }
00275 if ( 0 == cerrString ) {
00276 cerrString = (char *)"Unknown error. No information found in strerror()!";
00277 }
00278 else {
00279 errString = std::string(cerrString);
00280 }
00281 errno = 0;
00282 }
00283 else {
00284 cerrString = ::strerror(error);
00285 errString = std::string(cerrString);
00286 }
00287 #endif
00288 return errString;
00289 }
00290
00291 const std::string System::typeinfoName( const std::type_info& tinfo) {
00292 return typeinfoName(tinfo.name());
00293 }
00294
00295 const std::string System::typeinfoName( const char* class_name) {
00296 std::string result;
00297 #ifdef _WIN32
00298 long off = 0;
00299 if ( ::strncmp(class_name, "class ", 6) == 0 ) {
00300
00301 off = 6;
00302 }
00303 if ( ::strncmp(class_name, "struct ", 7) == 0 ) {
00304
00305 off = 7;
00306 }
00307 if ( off > 0 ) {
00308 std::string tmp = class_name + off;
00309 long loc = 0;
00310 while( (loc = tmp.find("class ")) > 0 ) {
00311 tmp.erase(loc, 6);
00312 }
00313 loc = 0;
00314 while( (loc = tmp.find("struct ")) > 0 ) {
00315 tmp.erase(loc, 7);
00316 }
00317 result = tmp;
00318 }
00319 else {
00320 result = class_name;
00321 }
00322
00323 while ( (off=result.find(" *")) != std::string::npos ) {
00324 result.replace(off, 2, "*");
00325 }
00326
00327 while ( (off=result.find(" &")) != std::string::npos ) {
00328 result.replace(off, 2, "&");
00329 }
00330
00331 #elif defined(__linux) || defined(__APPLE__)
00332 if ( ::strlen(class_name) == 1 ) {
00333
00334
00335 switch(class_name[0]) {
00336 case 'v':
00337 result = "void";
00338 break;
00339 case 'w':
00340 result = "wchar_t";
00341 break;
00342 case 'b':
00343 result = "bool";
00344 break;
00345 case 'c':
00346 result = "char";
00347 break;
00348 case 'a':
00349 result = "signed char";
00350 break;
00351 case 'h':
00352 result = "unsigned char";
00353 break;
00354 case 's':
00355 result = "short";
00356 break;
00357 case 't':
00358 result = "unsigned short";
00359 break;
00360 case 'i':
00361 result = "int";
00362 break;
00363 case 'j':
00364 result = "unsigned int";
00365 break;
00366 case 'l':
00367 result = "long";
00368 break;
00369 case 'm':
00370 result = "unsigned long";
00371 break;
00372 case 'x':
00373 result = "long long";
00374 break;
00375 case 'y':
00376 result = "unsigned long long";
00377 break;
00378 case 'n':
00379 result = "__int128";
00380 break;
00381 case 'o':
00382 result = "unsigned __int128";
00383 break;
00384 case 'f':
00385 result = "float";
00386 break;
00387 case 'd':
00388 result = "double";
00389 break;
00390 case 'e':
00391 result = "long double";
00392 break;
00393 case 'g':
00394 result = "__float128";
00395 break;
00396 case 'z':
00397 result = "ellipsis";
00398 break;
00399 }
00400 }
00401 else {
00402 int status;
00403 char* realname;
00404 realname = abi::__cxa_demangle(class_name, 0, 0, &status);
00405 if (realname == 0) return class_name;
00406 result = realname;
00407 free(realname);
00409 std::string::size_type pos = result.find(", ");
00410 while( std::string::npos != pos ) {
00411 result.replace( pos , 2 , "," ) ;
00412 pos = result.find(", ");
00413 }
00414 }
00415 #endif
00416 return result;
00417 }
00418
00420 const std::string& System::hostName() {
00421 static std::string host = "";
00422 if ( host == "" ) {
00423 char buffer[512];
00424 memset(buffer,0,sizeof(buffer));
00425 #ifdef _WIN32
00426 unsigned long len = sizeof(buffer);
00427 ::GetComputerName(buffer, &len);
00428 #else
00429 ::gethostname(buffer, sizeof(buffer));
00430 #endif
00431 host = buffer;
00432 }
00433 return host;
00434 }
00435
00437 const std::string& System::osName() {
00438 static std::string osname = "";
00439 #ifdef _WIN32
00440 osname = "Windows";
00441 #else
00442 struct utsname ut;
00443 if (uname(&ut) == 0) {
00444 osname = ut.sysname;
00445 } else {
00446 osname = "UNKNOWN";
00447 }
00448 #endif
00449 return osname;
00450 }
00451
00452
00454 const std::string& System::osVersion() {
00455 static std::string osver = "";
00456 #ifdef _WIN32
00457 OSVERSIONINFO ut;
00458 ut.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
00459 ::GetVersionEx(&ut);
00460 std::ostringstream ver;
00461 ver << ut.dwMajorVersion << '.' << ut.dwMinorVersion;
00462 osver = ver.str();
00463 #else
00464 struct utsname ut;
00465 if (uname(&ut) == 0) {
00466 osver = ut.release;
00467 } else {
00468 osver = "UNKNOWN";
00469 }
00470 #endif
00471 return osver;
00472 }
00473
00475 const std::string& System::machineType() {
00476 static std::string mach = "";
00477 #ifdef _WIN32
00478 SYSTEM_INFO ut;
00479 ::GetSystemInfo(&ut);
00480 std::ostringstream arch;
00481 arch << ut.wProcessorArchitecture;
00482 mach = arch.str();
00483 #else
00484 struct utsname ut;
00485 if (uname(&ut) == 0) {
00486 mach = ut.machine;
00487 } else {
00488 mach = "UNKNOWN";
00489 }
00490 #endif
00491 return mach;
00492 }
00493
00495 const std::string& System::accountName() {
00496 static std::string account = "";
00497 if ( account == "" ) {
00498 #ifdef _WIN32
00499 char buffer[512];
00500 unsigned long buflen = sizeof(buffer);
00501 ::GetUserName(buffer, &buflen);
00502 account = buffer;
00503 #else
00504 const char* acct = ::getlogin();
00505 if ( 0 == acct ) acct = ::getenv("LOGNAME");
00506 if ( 0 == acct ) acct = ::getenv("USER");
00507 account = (acct) ? acct : "Unknown";
00508 #endif
00509 }
00510 return account;
00511 }
00512
00514 long System::numCmdLineArgs() {
00515 return cmdLineArgs().size();
00516 }
00517
00519 long System::argc() {
00520 return cmdLineArgs().size();
00521 }
00522
00524 const std::vector<std::string> System::cmdLineArgs() {
00525 if ( s_argvChars.size() == 0 ) {
00526 char exe[1024];
00527 #ifdef _WIN32
00528
00529
00530 #pragma warning(push)
00531 #pragma warning(disable:4996)
00532
00533
00534
00535
00536 char *next, *tmp1, *tmp2;
00537 for(LPTSTR cmd = ::GetCommandLine(); *cmd; cmd=next) {
00538 memset(exe,0,sizeof(exe));
00539 while ( *cmd == ' ' ) cmd++;
00540 next=::strchr(cmd,' ');
00541 if ( !next ) next = cmd + strlen(cmd);
00542 if ( (tmp1=::strchr(cmd,'\"')) > 0 && tmp1 < next ) {
00543 tmp2 = ::strchr(++tmp1,'\"');
00544 if ( tmp2 > 0 ) {
00545 next = ++tmp2;
00546 if ( cmd < tmp1 ) strncpy(exe, cmd, tmp1-cmd-1);
00547 strncpy(&exe[strlen(exe)], tmp1, tmp2-tmp1-1);
00548 }
00549 else {
00550 std::cout << "Mismatched \" in command line arguments" << std::endl;
00551 s_argvChars.erase(s_argvChars.begin(), s_argvChars.end());
00552 s_argvStrings.erase(s_argvStrings.begin(), s_argvStrings.end());
00553 return s_argvStrings;
00554 }
00555 }
00556 else {
00557 strncpy(exe, cmd, next-cmd);
00558 }
00559 s_argvStrings.push_back(exe);
00560 s_argvChars.push_back( s_argvStrings.back().c_str());
00561 }
00562 #pragma warning(pop)
00563 #elif defined(linux) || defined(__APPLE__)
00564 sprintf(exe, "/proc/%d/cmdline", ::getpid());
00565 FILE *cmdLine = ::fopen(exe,"r");
00566 char cmd[1024];
00567 if ( cmdLine ) {
00568 long len = fread(cmd, sizeof(char), sizeof(cmd), cmdLine);
00569 if ( len > 0 ) {
00570 cmd[len] = 0;
00571 for ( char* token = cmd; token-cmd < len; token += strlen(token)+1 ) {
00572 s_argvStrings.push_back(token);
00573 s_argvChars.push_back( s_argvStrings.back().c_str());
00574 }
00575 s_argvStrings[0] = exeName();
00576 s_argvChars[0] = s_argvStrings[0].c_str();
00577 }
00578 }
00579 ::fclose(cmdLine);
00580 #endif
00581 }
00582 return s_argvStrings;
00583 }
00584
00586 char** System::argv() {
00588 if( s_argvChars.empty() ) { cmdLineArgs(); }
00589
00590
00591 return (char**)&s_argvChars[0];
00592 }
00593
00594 #ifdef WIN32
00595
00596
00597 #pragma warning(disable:4996)
00598 #endif
00599
00601 std::string System::getEnv(const char* var) {
00602 char* env;
00603 if ( (env = getenv(var)) != 0 ) {
00604 return env;
00605 } else {
00606 return "UNKNOWN";
00607 }
00608 }
00609
00611 bool System::getEnv(const char* var, std::string &value) {
00612 char* env;
00613 if ( (env = getenv(var)) != 0 ) {
00614 value = env;
00615 return true;
00616 } else {
00617 return false;
00618 }
00619 }
00620
00621 bool System::isEnvSet(const char* var) {
00622 return getenv(var) != 0;
00623 }
00624
00626 #if defined(__APPLE__)
00627
00628 #include "crt_externs.h"
00629 #endif
00630 std::vector<std::string> System::getEnv() {
00631 #if defined(_WIN32)
00632 # define environ _environ
00633 #elif defined(__APPLE__)
00634 static char **environ = *_NSGetEnviron();
00635 #endif
00636 std::vector<std::string> vars;
00637 for (int i=0; environ[i] != 0; ++i) {
00638 vars.push_back(environ[i]);
00639 }
00640 return vars;
00641 }
00642
00643
00644
00645
00646 #ifdef __linux
00647 #include <execinfo.h>
00648 #endif
00649
00650 int System::backTrace(void** addresses __attribute__ ((unused)),
00651 const int depth __attribute__ ((unused)))
00652 {
00653
00654 #ifdef __linux
00655
00656 int count = backtrace( addresses, depth );
00657 if ( count > 0 ) {
00658 return count;
00659 } else {
00660 return 0;
00661 }
00662
00663 #else // windows and osx parts not implemented
00664 return 0;
00665 #endif
00666
00667 }
00668
00669 bool System::backTrace(std::string& btrace, const int depth, const int offset)
00670 {
00671
00672 const int totalOffset = offset + 2;
00673 const int totalDepth = depth + totalOffset;
00674
00675 std::string fnc, lib;
00676
00677 void** addresses = (void**) malloc(totalDepth*sizeof(void *));
00678 if ( addresses != 0 ){
00679 int count = System::backTrace(addresses,totalDepth);
00680 for (int i = totalOffset; i < count; ++i) {
00681 void *addr = 0;
00682
00683 if (System::getStackLevel(addresses[i],addr,fnc,lib)) {
00684 std::ostringstream ost;
00685 ost << "#" << std::setw(3) << std::setiosflags( std::ios::left ) << i-totalOffset+1;
00686 ost << std::hex << addr << std::dec << " " << fnc << " [" << lib << "]" << std::endl;
00687 btrace += ost.str();
00688 }
00689 }
00690 free(addresses);
00691 }
00692 else {
00693 free(addresses);
00694 return false;
00695 }
00696
00697 return true;
00698 }
00699
00700 bool System::getStackLevel(void* addresses __attribute__ ((unused)),
00701 void*& addr __attribute__ ((unused)),
00702 std::string& fnc __attribute__ ((unused)),
00703 std::string& lib __attribute__ ((unused)))
00704 {
00705
00706 #ifdef __linux
00707
00708 Dl_info info;
00709
00710 if ( dladdr( addresses, &info ) && info.dli_fname
00711 && info.dli_fname[0] != '\0' ) {
00712 const char* symbol = info.dli_sname
00713 && info.dli_sname[0] != '\0' ? info.dli_sname : 0;
00714
00715 lib = info.dli_fname;
00716 addr = info.dli_saddr;
00717 const char* dmg(0);
00718
00719 if (symbol != 0) {
00720 int stat;
00721 dmg = abi::__cxa_demangle(symbol,0,0,&stat);
00722 fnc = (stat == 0) ? dmg : symbol;
00723 } else {
00724 fnc = "local";
00725 }
00726 free((void*)dmg);
00727 return true ;
00728 } else {
00729 return false ;
00730 }
00731
00732 #else // not implemented for windows and osx
00733 return false ;
00734 #endif
00735
00736 }
00737
00739 int System::setEnv(const std::string &name, const std::string &value, int overwrite)
00740 {
00741 #ifndef WIN32
00742
00743 return value.empty() ?
00744
00745 ::unsetenv(name.c_str()) , 0 :
00746
00747 ::setenv(name.c_str(),value.c_str(), overwrite);
00748 #else
00749
00750 if ( value.empty() ) {
00751
00752 return ::_putenv((name+"=").c_str());
00753 }
00754 else {
00755 if ( !getenv(name.c_str()) || overwrite ) {
00756
00757 return ::_putenv((name+"="+value).c_str());
00758 }
00759 }
00760 return 0;
00761
00762
00763 #endif
00764
00765 }