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 <iostream>
00019 #include <typeinfo>
00020
00021 #include "GaudiKernel/System.h"
00022
00023 #ifdef _WIN32
00024 # define strcasecmp _stricmp
00025 # define strncasecmp _strnicmp
00026 #include "process.h"
00027 #include "windows.h"
00028
00029 #define getpid _getpid
00030 const char* SHLIB_SUFFIX = ".dll";
00031
00032 #else // UNIX...: first the EGCS stuff, then the OS dependent includes
00033 const char* SHLIB_SUFFIX = ".so";
00034 #include <errno.h>
00035 #include <string.h>
00036 #include "sys/times.h"
00037 #include "unistd.h"
00038 #include "libgen.h"
00039 #include <cstdio>
00040 #if defined(linux) || defined(sun)
00041 #include "dlfcn.h"
00042 #elif __hpux
00043 #include "dl.h"
00044 struct HMODULE {
00045 shl_descriptor dsc;
00046 long numSym;
00047 shl_symbol* sym;
00048 };
00049 #endif
00050
00051 #endif
00052
00053 static std::vector<std::string> s_argvStrings;
00054 static std::vector<const char*> s_argvChars;
00055
00056 static unsigned long doLoad(const std::string& name, System::ImageHandle* handle) {
00057 #ifdef _WIN32
00058 void* mh = ::LoadLibrary( name.length() == 0 ? System::exeName().c_str() : name.c_str());
00059 *handle = mh;
00060 #else
00061 const char* path = name.c_str();
00062 #if defined(linux) || defined(sun)
00063 void *mh = ::dlopen(name.length() == 0 ? 0 : path, RTLD_LAZY);
00064 *handle = mh;
00065 #elif __hpux
00066 shl_t mh = ::shl_load(name.length() == 0 ? 0 : path, BIND_IMMEDIATE | BIND_VERBOSE, 0);
00067 HMODULE* mod = new HMODULE;
00068 if ( 0 != mh ) {
00069 if ( 0 != ::shl_gethandle_r(mh, &mod->dsc) ) {
00070 std::cout << "System::loadDynamicLib>" << ::strerror(getLastError()) << std::endl;
00071 }
00072 else {
00073 typedef void* (*___all)();
00074 ___all _alloc = (___all)malloc;
00075 mod->numSym = ::shl_getsymbols(mod->dsc.handle, TYPE_PROCEDURE, EXPORT_SYMBOLS, malloc, &mod->sym);
00076 *handle = mod;
00077 }
00078 }
00079 #endif
00080 #endif
00081 if ( 0 == *handle ) {
00082 return System::getLastError();
00083 }
00084 return 1;
00085 }
00086
00087 static unsigned long loadWithoutEnvironment(const std::string& name, System::ImageHandle* handle) {
00088
00089 unsigned long res;
00090 std::string dllName = name;
00091 long len = strlen(SHLIB_SUFFIX);
00092
00093
00094 if ( (dllName.length() != 0) &&
00095 ::strncasecmp(dllName.data()+dllName.length()-len, SHLIB_SUFFIX, len) != 0 ) {
00096 dllName += SHLIB_SUFFIX;
00097 }
00098
00099 res = doLoad(dllName, handle);
00100 if ( 1 != res ) {
00101
00102
00103 if ( ::strncasecmp(dllName.data()+dllName.length()-len,SHLIB_SUFFIX,len) == 0 ) {
00104 dllName = name.substr(0, name.length()-len);
00105 }
00106 #ifdef _WIN32
00107 if ( ::strncasecmp(dllName.data()+dllName.length()-3,"Shr",3) != 0 ) {
00108 dllName += "Shr";
00109 }
00110 #endif
00111 dllName += SHLIB_SUFFIX;
00112 res = doLoad(dllName, handle);
00113 }
00114 return res;
00115 }
00116
00117 static unsigned long loadWithEnvironment(const std::string& name, System::ImageHandle* handle) {
00118 unsigned long res = 0;
00119 std::string env = name;
00120 if ( 0 != ::getenv(env.c_str()) ) {
00121 std::string imgName = ::getenv(env.c_str());
00122 res = loadWithoutEnvironment(imgName, handle);
00123 }
00124 else {
00125 env += "Shr";
00126 if ( 0 != ::getenv(env.c_str()) ) {
00127 std::string imgName = ::getenv(env.c_str());
00128 res = loadWithoutEnvironment(imgName, handle);
00129 }
00130 }
00131 return res;
00132 }
00133
00135 unsigned long System::loadDynamicLib(const std::string& name, ImageHandle* handle) {
00136
00137
00138 unsigned long res = loadWithEnvironment(name, handle);
00139
00140 if ( 1 != res ) {
00141 res = loadWithoutEnvironment(name, handle);
00142 if ( 1 != res ) {
00143 std::string dllName = "lib" + name;
00144 #ifdef _WIN32
00145
00146 if ( ::strncasecmp(dllName.data()+dllName.length()-3,"Shr",3) != 0 ) {
00147 dllName += "Shr";
00148 }
00149 #endif
00150 dllName += SHLIB_SUFFIX;
00151 res = loadWithoutEnvironment(dllName, handle);
00152 }
00153 }
00154 if ( res != 1 ) {
00155 #if defined(linux) || defined(sun)
00156 errno = 0xAFFEDEAD;
00157 #endif
00158 std::cout << "System::loadDynamicLib>" << getLastErrorString() << std::endl;
00159 }
00160 return res;
00161 }
00162
00164 unsigned long System::unloadDynamicLib(ImageHandle handle) {
00165 #ifdef _WIN32
00166 if ( !::FreeLibrary((HINSTANCE)handle) ) {
00167 #elif defined(linux) || defined(sun)
00168 ::dlclose( handle );
00169 if ( 0 ) {
00170 #elif __hpux
00171
00172 Creator pFinalize = 0;
00173 if ( getProcedureByName(handle, "_fini", &pFinalize) ) {
00174 pFinalize();
00175 }
00176 HMODULE* mod = (HMODULE*)handle;
00177 if ( 0 == ::shl_unload( mod->dsc.handle ) ) {
00178 delete mod;
00179 }
00180 else {
00181 #endif
00182 return getLastError();
00183 }
00184 return 1;
00185 }
00186
00188 unsigned long System::getProcedureByName(ImageHandle handle, const std::string& name, EntryPoint* pFunction) {
00189 #ifdef _WIN32
00190 *pFunction = (EntryPoint)::GetProcAddress((HINSTANCE)handle, name.data());
00191 if ( 0 == *pFunction ) {
00192 return System::getLastError();
00193 }
00194 return 1;
00195 #elif defined(linux) || defined(sun)
00196 *pFunction = (EntryPoint)::dlsym(handle, name.c_str());
00197 if ( 0 == *pFunction ) {
00198 errno = 0xAFFEDEAD;
00199 std::cout << "System::getProcedureByName>" << getLastErrorString() << std::endl;
00200 return 0;
00201 }
00202 return 1;
00203 #elif __hpux
00204 HMODULE* mod = (HMODULE*)handle;
00205 if ( 0 != mod ) {
00206 long ll1 = name.length();
00207 for ( int i = 0; i < mod->numSym; i++ ) {
00208 long ll2 = strlen(mod->sym[i].name);
00209 if ( 0 != ::strncmp(mod->sym[i].name, name.c_str(), (ll1>ll2) ? ll1 : ll2)==0 ) {
00210 *pFunction = (EntryPoint) mod->sym[i].value;
00211 return 1;
00212 }
00213 }
00214 }
00215 return 0;
00216 #endif
00217 }
00218
00220 unsigned long System::getProcedureByName(ImageHandle handle, const std::string& name, Creator* pFunction) {
00221 return getProcedureByName(handle, name, (EntryPoint*)pFunction);
00222 }
00223
00225 unsigned long System::getLastError() {
00226 #ifdef _WIN32
00227 return ::GetLastError();
00228 #else
00229 return errno;
00230 #endif
00231 }
00232
00234 const std::string System::getLastErrorString() {
00235 const std::string errString = getErrorString(getLastError());
00236 return errString;
00237 }
00238
00240 const std::string System::getErrorString(unsigned long error) {
00241 std::string errString = "";
00242 #ifdef _WIN32
00243 LPVOID lpMessageBuffer;
00244 ::FormatMessage(
00245 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
00246 NULL,
00247 error,
00248 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00249 (LPTSTR) &lpMessageBuffer,
00250 0,
00251 NULL );
00252 errString = (const char*)lpMessageBuffer;
00253
00254 ::LocalFree( lpMessageBuffer );
00255 #else
00256
00257 if ( error == 0xAFFEDEAD ) {
00258 errString = ::dlerror();
00259 errno = 0;
00260 }
00261 else {
00262 errString = ::strerror(error);
00263 }
00264 #endif
00265 return errString;
00266 }
00267
00268
00269
00270
00271
00272
00273
00274
00275 std::string __typeName(char*& name);
00276 std::string __className(char*& name) {
00277 std::string result;
00278 int j = 0, k, i;
00279 if ( 't' == *name ) {
00280 goto Template;
00281 }
00282 for ( i = ::strtol(name, &name, 10); i > 0; i = ::strtol(name, &name, 10) ) {
00283 if ( j++ != 0 ) result.append("::",2);
00284 result.append(name, i);
00285 if ( *(name+=i) == 't' ) {
00286 result.append("::",2);
00287 Template:
00288 result.append(name, (i=::strtol(++name, &name, 10)));
00289 result.append("<");
00290 for (k = 0, i=::strtol(name+i, &name, 10); k < i; k++ ) {
00291 result += __typeName( ++name );
00292 if ( k+1 < i ) result += ",";
00293 }
00294 result.append(">");
00295 }
00296 }
00297 return result;
00298 }
00299
00300 std::string __typeName(char*& name) {
00301 if ( *name == 'Q' ) {
00302 if ( *(++name) == '_' )
00303 ::strtol(++name, &name, 10);
00304 return __className(++name);
00305 }
00306 else if ( 't' == *name ) {
00307 return __className(name);
00308 }
00309 else {
00310 std::string result;
00311 char* ptr;
00312 int i = ::strtol(name, &ptr, 10);
00313 if ( i <= 0 ) {
00314 name = ptr;
00315 while ( *name != 0 && *name != 'Z' ) {
00316 if ( *name == 'U' ) {
00317 result += "unsigned ";
00318 name++;
00319 }
00320 switch( *name++ ) {
00321 case 'c': result += "char"; break;
00322 case 's': result += "short"; break;
00323 case 'i': result += "int"; break;
00324 case 'l': result += "long"; break;
00325 case 'f': result += "float"; break;
00326 case 'd': result += "double"; break;
00327 default: result += *(name-1);
00328 }
00329 }
00330 return result;
00331 }
00332 else {
00333 return __className(name);
00334 }
00335 }
00336 }
00337
00338 const std::string System::typeinfoName( const std::type_info& tinfo) {
00339 const char* class_name = tinfo.name();
00340 std::string result;
00341 #ifdef _WIN32
00342 long off = 0;
00343 if ( ::strncmp(class_name, "class ", 6) == 0 ) {
00344
00345 off = 6;
00346 }
00347 if ( ::strncmp(class_name, "struct ", 7) == 0 ) {
00348
00349 off = 7;
00350 }
00351 if ( off > 0 ) {
00352 std::string tmp = class_name + off;
00353 long loc = 0;
00354 while( (loc = tmp.find("class ")) > 0 ) {
00355 tmp.erase(loc, 6);
00356 }
00357 loc = 0;
00358 while( (loc = tmp.find("struct ")) > 0 ) {
00359 tmp.erase(loc, 7);
00360 }
00361 result = tmp;
00362 }
00363 else {
00364 result = class_name;
00365 }
00366 #else
00367 char *name = const_cast<char*>(class_name);
00368 result = __typeName( name );
00369 #endif
00370 return result;
00371 }
00372
00374 const std::string& System::hostName() {
00375 static std::string host = "";
00376 if ( host == "" ) {
00377 char buffer[512];
00378 memset(buffer,0,sizeof(buffer));
00379 #ifdef _WIN32
00380 unsigned long len = sizeof(buffer);
00381 ::GetComputerName(buffer, &len);
00382 #else
00383 ::gethostname(buffer, sizeof(buffer));
00384 #endif
00385 host = buffer;
00386 }
00387 return host;
00388 }
00389
00391 const std::string& System::accountName() {
00392 static std::string account = "";
00393 if ( account == "" ) {
00394 #ifdef _WIN32
00395 char buffer[512];
00396 unsigned long buflen = sizeof(buffer);
00397 ::GetUserName(buffer, &buflen);
00398 account = buffer;
00399 #else
00400 const char* acct = ::getlogin();
00401 if ( 0 == acct ) acct = ::getenv("LOGNAME");
00402 if ( 0 == acct ) acct = ::getenv("USER");
00403 account = (acct) ? acct : "Unknown";
00404 #endif
00405 }
00406 return account;
00407 }
00408
00410 long System::numCmdLineArgs() {
00411 return cmdLineArgs().size();
00412 }
00413
00415 long System::argc() {
00416 return cmdLineArgs().size();
00417 }
00418
00420 const std::vector<std::string> System::cmdLineArgs() {
00421 if ( s_argvChars.size() == 0 ) {
00422 char exe[1024];
00423 #ifdef _WIN32
00424
00425
00426
00427
00428 char *next, *tmp1, *tmp2;
00429 for(LPTSTR cmd = ::GetCommandLine(); *cmd; cmd=next) {
00430 memset(exe,0,sizeof(exe));
00431 while ( *cmd == ' ' ) cmd++;
00432 next=::strchr(cmd,' ');
00433 if ( !next ) next = cmd + strlen(cmd);
00434 if ( (tmp1=::strchr(cmd,'\"')) > 0 && tmp1 < next ) {
00435 tmp2 = ::strchr(++tmp1,'\"');
00436 if ( tmp2 > 0 ) {
00437 next = ++tmp2;
00438 if ( cmd < tmp1 ) strncpy(exe, cmd, tmp1-cmd-1);
00439 strncpy(&exe[strlen(exe)], tmp1, tmp2-tmp1-1);
00440 }
00441 else {
00442 std::cout << "Mismatched \" in command line arguments" << std::endl;
00443 s_argvChars.erase(s_argvChars.begin(), s_argvChars.end());
00444 s_argvStrings.erase(s_argvStrings.begin(), s_argvStrings.end());
00445 return s_argvStrings;
00446 }
00447 }
00448 else {
00449 strncpy(exe, cmd, next-cmd);
00450 }
00451 s_argvStrings.push_back(exe);
00452 s_argvChars.push_back( s_argvStrings.back().c_str());
00453 }
00454 #elif defined(linux) || defined(sun)
00455 sprintf(exe, "/proc/%d/cmdline", ::getpid());
00456 FILE *cmdLine = ::fopen(exe,"r");
00457 char cmd[1024];
00458 if ( cmdLine ) {
00459 long len = fread(cmd, sizeof(char), sizeof(cmd), cmdLine);
00460 if ( len > 0 ) {
00461 cmd[len] = 0;
00462 for ( char* token = cmd; token-cmd < len; token += strlen(token)+1 ) {
00463 s_argvStrings.push_back(token);
00464 s_argvChars.push_back( s_argvStrings.back().c_str());
00465 }
00466 s_argvStrings[0] = exeName();
00467 s_argvChars[0] = s_argvStrings[0].c_str();
00468 }
00469 }
00470 ::fclose(cmdLine);
00471 #endif
00472 }
00473 return s_argvStrings;
00474 }
00475
00477 char** System::argv() {
00479 if( s_argvChars.empty() ) { cmdLineArgs(); }
00480
00481
00482 return (char**)&s_argvChars[0];
00483 }
00484