13 #define SYSTEM_SYSTEM_CPP
23 #include "GaudiKernel/System.h"
27 #define strcasecmp _stricmp
28 #define strncasecmp _strnicmp
29 #define getpid _getpid
36 static const char* SHLIB_SUFFIX =
".dll";
37 #else // UNIX...: first the EGCS stuff, then the OS dependent includes
38 static const char* SHLIB_SUFFIX =
".so";
41 #include "sys/times.h"
46 #if defined(__linux) || defined(__APPLE__)
48 #include <sys/utsname.h>
63 # if __GNUC__ < 3 || \
64 (__GNUC__ == 3 && (__GNUC_MINOR__ < 4 ))
66 # define __attribute__(x)
70 # define __attribute__(x)
73 static std::vector<std::string> s_argvStrings;
74 static std::vector<const char*> s_argvChars;
78 void* mh = ::LoadLibrary( name.length() == 0 ?
System::exeName().c_str() : name.c_str());
81 const char*
path = name.c_str();
82 #if defined(__linux) || defined(__APPLE__)
83 void *mh = ::dlopen(name.length() == 0 ?
nullptr :
path, RTLD_LAZY | RTLD_GLOBAL);
86 shl_t mh = ::shl_load(name.length() == 0 ? 0 :
path, BIND_IMMEDIATE | BIND_VERBOSE, 0);
87 HMODULE*
mod =
new HMODULE;
89 if ( 0 != ::shl_gethandle_r(mh, &mod->dsc) ) {
90 std::cout <<
"System::loadDynamicLib>" << ::strerror(
getLastError()) << std::endl;
93 typedef void* (*___all)();
94 ___all _alloc = (___all)malloc;
95 mod->numSym = ::shl_getsymbols(mod->dsc.handle, TYPE_PROCEDURE, EXPORT_SYMBOLS, malloc, &mod->sym);
109 std::string dllName =
name;
110 long len = strlen(SHLIB_SUFFIX);
114 if ((dllName.length() != 0) &&
115 ::strncasecmp(dllName.data()+dllName.length()-len, SHLIB_SUFFIX, len) != 0) {
116 dllName += SHLIB_SUFFIX;
120 return doLoad(dllName, handle);
127 if (name.length() == 0) {
128 res = loadWithoutEnvironment(name, handle);
133 if (
getEnv(name, imgName) ) {
134 res = loadWithoutEnvironment(imgName, handle);
137 std::string dllName =
name;
141 if (dllName.find(
'/') == std::string::npos) {
142 #if defined(__linux) || defined(__APPLE__)
143 if (dllName.compare(0, 3,
"lib") != 0)
144 dllName =
"lib" + dllName;
146 if (dllName.find(SHLIB_SUFFIX) == std::string::npos)
147 dllName += SHLIB_SUFFIX;
150 res = loadWithoutEnvironment(dllName, handle);
153 #if defined(__linux) || defined(__APPLE__)
165 if ( !::FreeLibrary((HINSTANCE)handle) ) {
166 #elif defined(__linux) || defined(__APPLE__)
175 HMODULE*
mod = (HMODULE*)handle;
176 if ( 0 == ::shl_unload( mod->dsc.handle ) ) {
191 *pFunction = (
EntryPoint)::GetProcAddress((HINSTANCE)handle, name.data());
192 if ( 0 == *pFunction ) {
196 #elif defined(__linux)
198 *pFunction = (
EntryPoint)::dlsym(handle, name.c_str());
200 *pFunction = FuncPtrCast<EntryPoint>(::dlsym(handle, name.c_str()));
202 if ( ! *pFunction ) {
208 #elif defined(__APPLE__)
209 *pFunction = (
EntryPoint)::dlsym(handle, name.c_str());
213 *pFunction = (
EntryPoint)::dlsym(handle, sname.c_str());
215 if ( 0 == *pFunction ) {
223 HMODULE* mod = (HMODULE*)handle;
225 long ll1 = name.length();
226 for (
int i = 0;
i < mod->numSym;
i++ ) {
227 long ll2 = strlen(mod->sym[
i].name);
228 if ( 0 != ::strncmp(mod->sym[
i].name, name.c_str(), (ll1>ll2) ? ll1 : ll2)==0 ) {
246 return ::GetLastError();
249 return static_cast<unsigned long>(
static_cast<unsigned int>(errno));
261 std::string errString =
"";
263 LPVOID lpMessageBuffer;
265 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
268 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
269 (LPTSTR) &lpMessageBuffer,
272 errString = (
const char*)lpMessageBuffer;
274 ::LocalFree( lpMessageBuffer );
276 char *cerrString(
nullptr);
278 if ( error == 0xAFFEDEAD ) {
279 cerrString = (
char*)::dlerror();
280 if ( !cerrString ) cerrString = ::strerror(error);
282 cerrString = (
char *)
"Unknown error. No information found in strerror()!";
285 errString = std::string(cerrString);
290 cerrString = ::strerror(error);
291 errString = std::string(cerrString);
305 if ( ::strncmp(class_name,
"class ", 6) == 0 ) {
309 if ( ::strncmp(class_name,
"struct ", 7) == 0 ) {
314 std::string tmp = class_name + off;
316 while( (loc = tmp.find(
"class ")) > 0 ) {
320 while( (loc = tmp.find(
"struct ")) > 0 ) {
329 while ( (off=result.find(
" *")) != std::string::npos ) {
330 result.replace(off, 2,
"*");
333 while ( (off=result.find(
" &")) != std::string::npos ) {
334 result.replace(off, 2,
"&");
337 #elif defined(__linux) || defined(__APPLE__)
338 if ( ::strlen(class_name) == 1 ) {
341 switch(class_name[0]) {
355 result =
"signed char";
358 result =
"unsigned char";
364 result =
"unsigned short";
370 result =
"unsigned int";
376 result =
"unsigned long";
379 result =
"long long";
382 result =
"unsigned long long";
388 result =
"unsigned __int128";
397 result =
"long double";
400 result =
"__float128";
409 auto realname = std::unique_ptr<char,decltype(free)*>( abi::__cxa_demangle(class_name,
nullptr,
nullptr, &status), std::free );
410 if (!realname)
return class_name;
411 result = std::string{realname.get()};
413 std::string::size_type pos = result.find(
", ");
414 while( std::string::npos != pos ) {
415 result.replace( pos , 2 ,
"," ) ;
416 pos = result.find(
", ");
424 std::string init_hostName() {
425 std::array<char,512> buffer;
426 std::fill_n(buffer.begin(),buffer.size(),0);
428 unsigned long len = buffer.size();
429 ::GetComputerName(buffer.data(), &len);
431 ::gethostname(buffer.data(), buffer.size());
433 return { buffer.data() };
439 static const std::string host = init_hostName();
445 static std::string osname =
"";
450 if (uname(&ut) == 0) {
462 static std::string osver =
"";
465 ut.dwOSVersionInfoSize =
sizeof(OSVERSIONINFO);
467 std::ostringstream ver;
468 ver << ut.dwMajorVersion <<
'.' << ut.dwMinorVersion;
472 if (uname(&ut) == 0) {
483 static std::string mach =
"";
486 ::GetSystemInfo(&ut);
487 std::ostringstream arch;
488 arch << ut.wProcessorArchitecture;
492 if (uname(&ut) == 0) {
512 static std::string account =
"";
513 if ( account ==
"" ) {
516 unsigned long buflen =
sizeof(buffer);
517 ::GetUserName(buffer, &buflen);
520 const char* acct = ::getlogin();
521 if ( !acct ) acct = ::getenv(
"LOGNAME");
522 if ( !acct ) acct = ::getenv(
"USER");
523 account = (acct) ? acct :
"Unknown";
541 if ( s_argvChars.size() == 0 ) {
546 #pragma warning(push)
547 #pragma warning(disable:4996)
552 char *next, *tmp1, *tmp2;
553 for(LPTSTR cmd = ::GetCommandLine(); *cmd; cmd=next) {
554 memset(exe,0,
sizeof(exe));
555 while ( *cmd ==
' ' ) cmd++;
556 next=::strchr(cmd,
' ');
557 if ( !next ) next = cmd + strlen(cmd);
558 if ( (tmp1=::strchr(cmd,
'\"')) > 0 && tmp1 < next ) {
559 tmp2 = ::strchr(++tmp1,
'\"');
562 if ( cmd < tmp1 ) strncpy(exe, cmd, tmp1-cmd-1);
563 strncpy(&exe[strlen(exe)], tmp1, tmp2-tmp1-1);
566 std::cout <<
"Mismatched \" in command line arguments" << std::endl;
567 s_argvChars.erase(s_argvChars.begin(), s_argvChars.end());
568 s_argvStrings.erase(s_argvStrings.begin(), s_argvStrings.end());
569 return s_argvStrings;
573 strncpy(exe, cmd, next-cmd);
575 s_argvStrings.push_back(exe);
576 s_argvChars.push_back( s_argvStrings.back().c_str());
579 #elif defined(__linux) || defined(__APPLE__)
580 sprintf(exe,
"/proc/%d/cmdline", ::getpid());
581 FILE *cmdLine = ::fopen(exe,
"r");
584 long len = fread(cmd,
sizeof(
char),
sizeof(cmd), cmdLine);
587 for (
char* token = cmd; token-cmd < len; token += strlen(token)+1 ) {
588 s_argvStrings.push_back(token);
589 s_argvChars.push_back( s_argvStrings.back().c_str());
592 s_argvChars[0] = s_argvStrings[0].c_str();
598 return s_argvStrings;
607 return (
char**)&s_argvChars[0];
613 #pragma warning(disable:4996)
619 if ( (env = getenv(var)) !=
nullptr ) {
629 if ( (env = getenv(var)) !=
nullptr ) {
638 return getenv(var) !=
nullptr;
642 #if defined(__APPLE__)
644 #include "crt_externs.h"
648 # define environ _environ
649 #elif defined(__APPLE__)
650 static char **environ = *_NSGetEnviron();
652 std::vector<std::string> vars;
653 for (
int i=0; environ[
i] !=
nullptr; ++
i) {
654 vars.push_back(environ[
i]);
663 #include <execinfo.h>
672 int count = backtrace( addresses, depth );
673 return count > 0 ? count : 0;
675 #else // windows and osx parts not implemented
685 const int totalOffset = offset + 2;
686 const int totalDepth = depth + totalOffset;
688 std::string fnc, lib;
690 std::vector<void*> addresses( totalDepth,
nullptr );
692 for (
int i = totalOffset;
i < count; ++
i) {
693 void *addr =
nullptr;
696 std::ostringstream ost;
697 ost <<
"#" << std::setw(3) << std::setiosflags( std::ios::left ) << i-totalOffset+1;
698 ost << std::hex << addr << std::dec <<
" " << fnc <<
" [" << lib <<
"]" << std::endl;
703 }
catch (
const std::bad_alloc& e ) {
718 if ( dladdr( addresses, &info ) && info.dli_fname
719 && info.dli_fname[0] !=
'\0' ) {
720 const char* symbol = info.dli_sname
721 && info.dli_sname[0] !=
'\0' ? info.dli_sname :
nullptr;
723 lib = info.dli_fname;
724 addr = info.dli_saddr;
728 auto dmg = std::unique_ptr<char,decltype(free)*>( abi::__cxa_demangle(symbol,
nullptr,
nullptr,&stat), std::free );
729 fnc = (stat == 0) ? dmg.get() : symbol;
738 #else // not implemented for windows and osx
749 return value.empty() ?
751 ::unsetenv(name.c_str()) , 0 :
753 ::setenv(name.c_str(),value.c_str(), overwrite);
756 if ( value.empty() ) {
758 return ::_putenv((name+
"=").c_str());
761 if ( !getenv(name.c_str()) || overwrite ) {
763 return ::_putenv((name+
"="+value).c_str());
GAUDI_API const std::string & osName()
OS name.
GAUDI_API unsigned long getProcedureByName(ImageHandle handle, const std::string &name, EntryPoint *pFunction)
Get a specific function defined in the DLL.
GAUDI_API bool getStackLevel(void *addresses, void *&addr, std::string &fnc, std::string &lib)
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
GAUDI_API unsigned long getLastError()
Get last system known error.
void * ImageHandle
Definition of an image handle.
GAUDI_API const std::string & exeName()
Name of the executable file running.
GAUDI_API long argc()
Number of arguments passed to the commandline (==numCmdLineArgs()); just to match argv call...
GAUDI_API int backTrace(void **addresses, const int depth)
GAUDI_API int setEnv(const std::string &name, const std::string &value, int overwrite=1)
Set an environment variables.
GAUDI_API const std::string getErrorString(unsigned long error)
Retrieve error code as string for a given error.
int instrset_detect(void)
GAUDI_API bool isEnvSet(const char *var)
Check if an environment variable is set or not.
GAUDI_API std::string getEnv(const char *var)
get a particular environment variable (returning "UNKNOWN" if not set)
GAUDI_API int instructionsetLevel()
Instruction Set "Level".
GAUDI_API const std::string & machineType()
Machine type.
void *(* Creator)()
Definition of the "generic" DLL entry point function.
GAUDI_API long numCmdLineArgs()
Number of arguments passed to the commandline.
GAUDI_API const std::string & hostName()
Host name.
GAUDI_API char ** argv()
char** command line arguments including executable name as arg[0]; You may not modify them! ...
GAUDI_API const std::string getLastErrorString()
Get last system error as string.
GAUDI_API const std::string & accountName()
User login name.
GAUDI_API unsigned long loadDynamicLib(const std::string &name, ImageHandle *handle)
Load dynamic link library.
GAUDI_API unsigned long unloadDynamicLib(ImageHandle handle)
unload dynamic link library
unsigned long(* EntryPoint)(const unsigned long iid, void **ppvObject)
Definition of the "generic" DLL entry point function.
GAUDI_API const std::vector< std::string > cmdLineArgs()
Command line arguments including executable name as arg[0] as vector of strings.
GAUDI_API const std::string & osVersion()
OS version.