| # Gaudi Framework, version v21r11 |

Home |  | Generated: 30 Sep 2010

# System.cpp

Go to the documentation of this file.

    00001 // $Id: System.cpp,v 1.45 2008/10/27 21:30:32 marcocle Exp $
    00002 //====================================================================
    00003 //      System.cpp
    00004 //--------------------------------------------------------------------
    00005 //
    00006 //      Package    : System (The LHCb System service)
    00007 //
    00008 //  Description: Implementation of Systems internals
    00009 //
    00010 //      Author     : M.Frank
    00011 //  Created    : 13/1/99
    00012 //      Changes    :
    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 // Note: __attribute__ is a GCC keyword available since GCC 3.4
    00061 #ifdef __GNUC__
    00062 #  if __GNUC__ < 3 || \
    00063       (__GNUC__ == 3 && (__GNUC_MINOR__ < 4 ))
    00064 // GCC < 3.4
    00065 #    define __attribute__(x)
    00066 #  endif
    00067 #else
    00068 // non-GCC
    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   // Add the suffix at the end of the library name only if necessary
    00112   // FIXME: cure the logic
    00113   if ((dllName.length() != 0) &&
    00114       ::strncasecmp(dllName.data()+dllName.length()-len, SHLIB_SUFFIX, len) != 0) {
    00115     dllName += SHLIB_SUFFIX;
    00116   }
    00117
    00118   // Load the library
    00119   return doLoad(dllName, handle);
    00120 }
    00121
    00123 unsigned long System::loadDynamicLib(const std::string& name, ImageHandle* handle) {
    00124   unsigned long res;
    00125   // if name is empty, just load it
    00126   if (name.length() == 0) {
    00127     res = loadWithoutEnvironment(name, handle);
    00128   } else {
    00129     // If the name is a logical name (environment variable), the try
    00130     // to load the corresponding library from there.
    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       // build the dll name
    00137       std::string dllName = name;
    00138 #if defined(linux) || defined(__APPLE__)
    00139       dllName = "lib" + dllName;
    00140 #endif
    00141       dllName += SHLIB_SUFFIX;
    00142       // try to locate the dll using the standard PATH
    00143       res = loadWithoutEnvironment(dllName, handle);
    00144     }
    00145     if ( res != 1 ) {
    00146 #if defined(linux) || defined(__APPLE__)
    00147       errno = 0xAFFEDEAD;
    00148 #endif
    00149      // std::cout << "System::loadDynamicLib>" << getLastErrorString() << std::endl;
    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   // On HP we have to run finalization ourselves.....
    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    // std::cout << "System::getProcedureByName>" << getLastErrorString() << std::endl;
    00198     return 0;
    00199   }
    00200   return 1;
    00201 #elif defined(__APPLE__)
    00202   *pFunction = (EntryPoint)::dlsym(handle, name.c_str());
    00203   if(!(*pFunction)) {
    00204     // Try with an underscore :
    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     //std::cout << "System::getProcedureByName> failure" << std::endl;
    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   // convert errno (int) to unsigned long
    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), //The user default language
    00262     (LPTSTR) &lpMessageBuffer,
    00263     0,
    00264     NULL );
    00265   errString = (const char*)lpMessageBuffer;
    00266   // Free the buffer allocated by the system
    00267   ::LocalFree( lpMessageBuffer );
    00268 #else
    00269   char *cerrString(0);
    00270   // Remember: for linux dl* routines must be handled differently!
    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 // This is a little bit complicated....but at least it gives
    00293 // usable results:
    00294 // Native class template:
    00295 //  Spac::templa<Spac::templa<Spac::templ<Spac::templa<AAA::a,Spac::templa<double,unsigned char>>>,B::bbb>,float>
    00296 // is translated under egcs to the unreadable string:
    00297 //  Q24Spact6templa2ZQ24Spact6templa2ZQ24Spact5templ1ZQ24Spact6templa2ZQ23AAA1aZQ24Spact6templa2ZdZUcZQ21B3bbbZf
    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' ) {              // Handle name spaces
    00326     if ( *(++name) == '_' )          // >= 10 nested name spaces
    00327       ::strtol(++name, &name, 10);   // type Q_##_...
    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     // The returned name is prefixed with "class "
    00370     off = 6;
    00371   }
    00372   if ( ::strncmp(class_name, "struct ", 7) == 0 )   {
    00373     // The returned name is prefixed with "struct "
    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   // Change any " *" to "*"
    00392   while ( (off=result.find(" *")) != std::string::npos ) {
    00393     result.replace(off, 2, "*");
    00394   }
    00395   // Change any " &" to "&"
    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       // See http://www.realitydiluted.com/mirrors/reality.sgi.com/dehnert_engr/cxx/abi.pdf
    00403       // for details
    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     // For compatibility with UNIX we CANNOT use strtok!
    00598     // If we would use strtok, options like -g="My world" at
    00599     // the command line level would result on NT in TWO options
    00600     // instead in one as in UNIX.
    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   // We rely here on the fact that a vector's allocation table is contiguous
    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 // Needed for _NSGetEnviron(void)
    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 // backtrace utilities
    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   // Always hide the first two levels of the stack trace (that's us)
    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   // UNIX version
    00786   return value.empty() ?
    00787     // remove if set to nothing (and return success)
    00788     ::unsetenv(name.c_str()) , 0 :
    00789     // set the value
    00790     ::setenv(name.c_str(),value.c_str(), overwrite);
    00791 #else
    00792   // Windows version
    00793   if ( value.empty() ) {
    00794     // equivalent to unsetenv
    00795     return ::_putenv((name+"=").c_str());
    00796   }
    00797   else {
    00798     if ( !getenv(name.c_str()) || overwrite ) {
    00799       // set if not yet present or overwrite is set (force)
    00800       return ::_putenv((name+"="+value).c_str());
    00801     }
    00802   }
    00803   return 0; // if we get here, we are trying to set a variable already set, but
    00804             // not to overwrite.
    00805             // It is considered a success on Linux (man P setenv)
    00806 #endif
    00807
    00808 }