Panda3D

executionEnvironment.cxx

00001 // Filename: executionEnvironment.cxx
00002 // Created by:  drose (15May00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "executionEnvironment.h"
00016 #include "pandaVersion.h"
00017 #include <assert.h>
00018 #include <errno.h>
00019 #include <stdio.h>  // for perror
00020 
00021 #ifdef WIN32_VC
00022 // Windows requires this for getcwd().
00023 #include <direct.h>
00024 #define getcwd _getcwd
00025 
00026 // And this is for GetModuleFileName().
00027 #include <windows.h>
00028 #endif
00029 
00030 #ifdef __APPLE__
00031 // This is for _NSGetExecutablePath() and _NSGetEnviron().
00032 #include <mach-o/dyld.h>
00033 #ifndef BUILD_IPHONE
00034 #include <crt_externs.h>  // For some reason, not in the IPhone SDK.
00035 #endif
00036 #define environ (*_NSGetEnviron())
00037 #endif
00038 
00039 #ifdef IS_LINUX
00040 // extern char **environ is defined here:
00041 #include <unistd.h>
00042 #endif
00043 
00044 #ifdef IS_FREEBSD
00045 extern char **environ;
00046 
00047 // This is for Link_map.
00048 #include <link.h>
00049 
00050 // This is for sysctl.
00051 #include <sys/types.h>
00052 #include <sys/sysctl.h>
00053 #endif
00054 
00055 #ifdef HAVE_PYTHON
00056 #include "Python.h"
00057 #endif
00058 
00059 // We define the symbol PREREAD_ENVIRONMENT if we cannot rely on
00060 // getenv() to read environment variables at static init time.  In
00061 // this case, we must read all of the environment variables directly
00062 // and cache them locally.
00063 
00064 #ifndef STATIC_INIT_GETENV
00065 #define PREREAD_ENVIRONMENT
00066 #endif
00067 
00068 
00069 // We define the symbol HAVE_GLOBAL_ARGV if we have global variables
00070 // named GLOBAL_ARGC/GLOBAL_ARGV that we can read at static init time
00071 // to determine our command-line arguments.
00072 
00073 #if defined(HAVE_GLOBAL_ARGV) && defined(PROTOTYPE_GLOBAL_ARGV)
00074 extern char **GLOBAL_ARGV;
00075 extern int GLOBAL_ARGC;
00076 #endif
00077 
00078 // Linux with GNU libc does have global argv/argc variables, but we
00079 // can't safely access them at stat init time--at least, not in libc5.
00080 // (It does seem to work with glibc2, however.)
00081 
00082 ExecutionEnvironment *ExecutionEnvironment::_global_ptr = NULL;
00083 
00084 
00085 ////////////////////////////////////////////////////////////////////
00086 //     Function: ExecutionEnvironment::Constructor
00087 //       Access: Private
00088 //  Description: You shouldn't need to construct one of these; there's
00089 //               only one and it constructs itself.
00090 ////////////////////////////////////////////////////////////////////
00091 ExecutionEnvironment::
00092 ExecutionEnvironment() {
00093   read_environment_variables();
00094   read_args();
00095 }
00096 
00097 ////////////////////////////////////////////////////////////////////
00098 //     Function: ExecutionEnviroment::expand_string
00099 //       Access: Public, Static
00100 //  Description: Reads the string, looking for environment variable
00101 //               names marked by a $.  Expands all such variable
00102 //               names.  A repeated dollar sign ($$) is mapped to a
00103 //               single dollar sign.
00104 //
00105 //               Returns the expanded string.
00106 ////////////////////////////////////////////////////////////////////
00107 string ExecutionEnvironment::
00108 expand_string(const string &str) {
00109   string result;
00110 
00111   size_t last = 0;
00112   size_t dollar = str.find('$');
00113   while (dollar != string::npos && dollar + 1 < str.length()) {
00114     size_t start = dollar + 1;
00115 
00116     if (str[start] == '$') {
00117       // A double dollar sign maps to a single dollar sign.
00118       result += str.substr(last, start - last);
00119       last = start + 1;
00120 
00121     } else {
00122       string varname;
00123       size_t end = start;
00124 
00125       if (str[start] == '{') {
00126         // Curly braces delimit the variable name explicitly.
00127         end = str.find('}', start + 1);
00128         if (end != string::npos) {
00129           varname = str.substr(start + 1, end - (start + 1));
00130           end++;
00131         }
00132       }
00133 
00134       if (end == start) {
00135         // Scan for the end of the variable name.
00136         while (end < str.length() && (isalnum(str[end]) || str[end] == '_')) {
00137           end++;
00138         }
00139         varname = str.substr(start, end - start);
00140       }
00141 
00142       string subst =
00143       result += str.substr(last, dollar - last);
00144       result += get_environment_variable(varname);
00145       last = end;
00146     }
00147 
00148     dollar = str.find('$', last);
00149   }
00150 
00151   result += str.substr(last);
00152 
00153   return result;
00154 }
00155 
00156 ////////////////////////////////////////////////////////////////////
00157 //     Function: ExecutionEnviroment::get_cwd
00158 //       Access: Public, Static
00159 //  Description: Returns the name of the current working directory.
00160 ////////////////////////////////////////////////////////////////////
00161 Filename ExecutionEnvironment::
00162 get_cwd() {
00163   // getcwd() requires us to allocate a dynamic buffer and grow it on
00164   // demand.
00165   static size_t bufsize = 1024;
00166   static char *buffer = NULL;
00167 
00168   if (buffer == (char *)NULL) {
00169     buffer = new char[bufsize];
00170   }
00171 
00172   while (getcwd(buffer, bufsize) == (char *)NULL) {
00173     if (errno != ERANGE) {
00174       perror("getcwd");
00175       return string();
00176     }
00177     delete[] buffer;
00178     bufsize = bufsize * 2;
00179     buffer = new char[bufsize];
00180     assert(buffer != (char *)NULL);
00181   }
00182 
00183   Filename cwd = Filename::from_os_specific(buffer);
00184   cwd.make_true_case();
00185   return cwd;
00186 }
00187 
00188 ////////////////////////////////////////////////////////////////////
00189 //     Function: ExecutionEnvironment::ns_has_environment_variable
00190 //       Access: Private
00191 //  Description: Returns true if the indicated environment variable
00192 //               is defined.  The nonstatic implementation.
00193 ////////////////////////////////////////////////////////////////////
00194 bool ExecutionEnvironment::
00195 ns_has_environment_variable(const string &var) const {
00196 #ifdef PREREAD_ENVIRONMENT
00197   return _variables.count(var) != 0;
00198 #else
00199   return getenv(var.c_str()) != (char *)NULL;
00200 #endif
00201 }
00202 
00203 ////////////////////////////////////////////////////////////////////
00204 //     Function: ExecutionEnvironment::ns_get_environment_variable
00205 //       Access: Private
00206 //  Description: Returns the definition of the indicated environment
00207 //               variable, or the empty string if the variable is
00208 //               undefined.  The nonstatic implementation.
00209 ////////////////////////////////////////////////////////////////////
00210 string ExecutionEnvironment::
00211 ns_get_environment_variable(const string &var) const {
00212   EnvironmentVariables::const_iterator evi;
00213   evi = _variables.find(var);
00214   if (evi != _variables.end()) {
00215     return (*evi).second;
00216   }
00217 
00218   // Some special case variables.  We virtually stuff these values
00219   // into the Panda environment, shadowing whatever values they have
00220   // in the true environment, so they can be used in config files.
00221   if (var == "HOME") {
00222     return Filename::get_home_directory().to_os_specific();
00223   } else if (var == "TEMP") {
00224     return Filename::get_temp_directory().to_os_specific();
00225   } else if (var == "USER_APPDATA") {
00226     return Filename::get_user_appdata_directory().to_os_specific();
00227   } else if (var == "COMMON_APPDATA") {
00228     return Filename::get_common_appdata_directory().to_os_specific();
00229   } else if (var == "MAIN_DIR") {
00230 #ifdef HAVE_PYTHON
00231     // If we're running from Python code, read out sys.argv.
00232     if (!ns_has_environment_variable("PANDA_INCOMPATIBLE_PYTHON") && Py_IsInitialized()) {
00233       PyObject* obj = PySys_GetObject((char*) "argv");
00234       if (obj) {
00235         Filename main_dir = Filename::from_os_specific(PyString_AsString(PyList_GetItem(obj, 0)));
00236         if (main_dir.empty()) {
00237           // We must be running in the Python interpreter directly, so return the CWD.
00238           return get_cwd().to_os_specific();
00239         }
00240         main_dir.make_absolute();
00241         return Filename(main_dir.get_dirname()).to_os_specific();
00242       }
00243     }
00244 #endif
00245 
00246     // Otherwise, Return the binary name's parent directory.
00247     if (!_binary_name.empty()) {
00248       Filename main_dir (_binary_name);
00249       main_dir.make_absolute();
00250       return Filename(main_dir.get_dirname()).to_os_specific();
00251     }
00252   }
00253 
00254 #ifdef PREREAD_ENVIRONMENT
00255   return string();
00256 #else
00257   const char *def = getenv(var.c_str());
00258   if (def != (char *)NULL) {
00259     return def;
00260   }
00261   return string();
00262 #endif
00263 }
00264 
00265 ////////////////////////////////////////////////////////////////////
00266 //     Function: ExecutionEnvironment::ns_set_environment_variable
00267 //       Access: Private
00268 //  Description: Changes the definition of the indicated environment
00269 //               variable.  The nonstatic implementation.
00270 ////////////////////////////////////////////////////////////////////
00271 void ExecutionEnvironment::
00272 ns_set_environment_variable(const string &var, const string &value) {
00273   _variables[var] = value;
00274   string putstr = var + "=" + value;
00275 
00276   // putenv() requires us to malloc a new C-style string.
00277   char *put = (char *)malloc(putstr.length() + 1);
00278   strcpy(put, putstr.c_str());
00279   putenv(put);
00280 }
00281 
00282 ////////////////////////////////////////////////////////////////////
00283 //     Function: ExecutionEnvironment::ns_shadow_environment_variable
00284 //       Access: Private
00285 //  Description:
00286 ////////////////////////////////////////////////////////////////////
00287 void ExecutionEnvironment::
00288 ns_shadow_environment_variable(const string &var, const string &value) {
00289   _variables[var] = value;
00290   string putstr = var + "=" + value;
00291 }
00292 
00293 ////////////////////////////////////////////////////////////////////
00294 //     Function: ExecutionEnvironment::ns_clear_shadow
00295 //       Access: Private
00296 //  Description:
00297 ////////////////////////////////////////////////////////////////////
00298 void ExecutionEnvironment::
00299 ns_clear_shadow(const string &var) {
00300   EnvironmentVariables::iterator vi = _variables.find(var);
00301   if (vi == _variables.end()) {
00302     return;
00303   }
00304 
00305 #ifdef PREREAD_ENVIRONMENT
00306   // Now we have to replace the value in the table.
00307   const char *def = getenv(var.c_str());
00308   if (def != (char *)NULL) {
00309     (*vi).second = def;
00310   } else {
00311     _variables.erase(vi);
00312   }
00313 #endif  // PREREAD_ENVIRONMENT
00314 }
00315 
00316 ////////////////////////////////////////////////////////////////////
00317 //     Function: ExecutionEnvironment::ns_get_num_args
00318 //       Access: Private
00319 //  Description: Returns the number of command-line arguments
00320 //               available, not counting arg 0, the binary name.  The
00321 //               nonstatic implementation.
00322 ////////////////////////////////////////////////////////////////////
00323 int ExecutionEnvironment::
00324 ns_get_num_args() const {
00325   return _args.size();
00326 }
00327 
00328 ////////////////////////////////////////////////////////////////////
00329 //     Function: ExecutionEnvironment::ns_get_arg
00330 //       Access: Private
00331 //  Description: Returns the nth command-line argument.  The index n
00332 //               must be in the range [0 .. get_num_args()).  The
00333 //               first parameter, n == 0, is the first actual
00334 //               parameter, not the binary name.  The nonstatic
00335 //               implementation.
00336 ////////////////////////////////////////////////////////////////////
00337 string ExecutionEnvironment::
00338 ns_get_arg(int n) const {
00339   assert(n >= 0 && n < ns_get_num_args());
00340   return _args[n];
00341 }
00342 
00343 ////////////////////////////////////////////////////////////////////
00344 //     Function: ExecutionEnvironment::ns_get_binary_name
00345 //       Access: Private
00346 //  Description: Returns the name of the binary executable that
00347 //               started this program, if it can be determined.  The
00348 //               nonstatic implementation.
00349 ////////////////////////////////////////////////////////////////////
00350 string ExecutionEnvironment::
00351 ns_get_binary_name() const {
00352   if (_binary_name.empty()) {
00353     return "unknown";
00354   }
00355   return _binary_name;
00356 }
00357 
00358 ////////////////////////////////////////////////////////////////////
00359 //     Function: ExecutionEnvironment::ns_get_dtool_name
00360 //       Access: Private
00361 //  Description: Returns the name of the libdtool DLL that
00362 //               is used in this program, if it can be determined.  The
00363 //               nonstatic implementation.
00364 ////////////////////////////////////////////////////////////////////
00365 string ExecutionEnvironment::
00366 ns_get_dtool_name() const {
00367   if (_dtool_name.empty()) {
00368     return "unknown";
00369   }
00370   return _dtool_name;
00371 }
00372 
00373 ////////////////////////////////////////////////////////////////////
00374 //     Function: ExecutionEnvironment::get_ptr
00375 //       Access: Private, Static
00376 //  Description: Returns a static pointer that may be used to access
00377 //               the global ExecutionEnvironment object.
00378 ////////////////////////////////////////////////////////////////////
00379 ExecutionEnvironment *ExecutionEnvironment::
00380 get_ptr() {
00381   if (_global_ptr == (ExecutionEnvironment *)NULL) {
00382     _global_ptr = new ExecutionEnvironment;
00383   }
00384   return _global_ptr;
00385 }
00386 
00387 
00388 ////////////////////////////////////////////////////////////////////
00389 //     Function: ExecutionEnvironment::read_environment_variables
00390 //       Access: Private
00391 //  Description: Fills up the internal table of existing environment
00392 //               variables, if we are in PREREAD_ENVIRONMENT mode.
00393 //               Otherwise, does nothing.
00394 ////////////////////////////////////////////////////////////////////
00395 void ExecutionEnvironment::
00396 read_environment_variables() {
00397 #ifdef PREREAD_ENVIRONMENT
00398 #if defined(IS_OSX) || defined(IS_FREEBSD) || defined(IS_LINUX)
00399   // In the case of Mac, we'll try reading _NSGetEnviron().
00400   // In the case of FreeBSD and Linux, use the "environ" variable.
00401 
00402   char **envp;
00403   for (envp = environ; envp && *envp; envp++) {
00404     string variable;
00405     string value;
00406 
00407     char *envc;
00408     for (envc = *envp; envc && *envc && strncmp(envc, "=", 1) != 0; envc++) {
00409       variable += (char) *envc;
00410     }
00411 
00412     if (strncmp(envc, "=", 1) == 0) {
00413       for (envc++; envc && *envc; envc++) {
00414         value += (char) *envc;
00415       }
00416     }
00417 
00418     if (!variable.empty()) {
00419       _variables[variable] = value;
00420     }
00421   }
00422 #elif defined(HAVE_PROC_SELF_ENVIRON)
00423   // In some cases, we may have a file called /proc/self/environ
00424   // that may be read to determine all of our environment variables.
00425 
00426   pifstream proc("/proc/self/environ");
00427   if (proc.fail()) {
00428     cerr << "Cannot read /proc/self/environ; environment variables unavailable.\n";
00429     return;
00430   }
00431 
00432   int ch = proc.get();
00433   while (!proc.eof() && !proc.fail()) {
00434     string variable;
00435     string value;
00436 
00437     while (!proc.eof() && !proc.fail() && ch != '=' && ch != '\0') {
00438       variable += (char)ch;
00439       ch = proc.get();
00440     }
00441 
00442     if (ch == '=') {
00443       ch = proc.get();
00444       while (!proc.eof() && !proc.fail() && ch != '\0') {
00445         value += (char)ch;
00446         ch = proc.get();
00447       }
00448     }
00449 
00450     if (!variable.empty()) {
00451       _variables[variable] = value;
00452     }
00453     ch = proc.get();
00454   }
00455 #else
00456   cerr << "Warning: environment variables unavailable to dconfig.\n";
00457 #endif
00458 #endif // PREREAD_ENVIRONMENT
00459 }
00460 
00461 ////////////////////////////////////////////////////////////////////
00462 //     Function: ExecutionEnvironment::read_args
00463 //       Access: Private
00464 //  Description: Reads all the command-line arguments and the name of
00465 //               the binary file, if possible.
00466 ////////////////////////////////////////////////////////////////////
00467 void ExecutionEnvironment::
00468 read_args() {
00469 
00470   // First, we need to fill in _dtool_name.  This contains
00471   // the full path to the p3dtool library.
00472 
00473 #ifdef WIN32_VC
00474 #ifdef _DEBUG
00475   HMODULE dllhandle = GetModuleHandle("libp3dtool_d.dll");
00476 #else
00477   HMODULE dllhandle = GetModuleHandle("libp3dtool.dll");
00478 #endif
00479   if (dllhandle != 0) {
00480     static const DWORD buffer_size = 1024;
00481     char buffer[buffer_size];
00482     DWORD size = GetModuleFileName(dllhandle, buffer, buffer_size);
00483     if (size != 0) {
00484       Filename tmp = Filename::from_os_specific(string(buffer, size));
00485       tmp.make_true_case();
00486       _dtool_name = tmp;
00487     }
00488   }
00489 #endif
00490 
00491 #if defined(__APPLE__)
00492   // And on OSX we don't have /proc/self/maps, but some _dyld_* functions.
00493 
00494   if (_dtool_name.empty()) {
00495     uint32_t ic = _dyld_image_count();
00496     for (uint32_t i = 0; i < ic; ++i) {
00497       const char *buffer = _dyld_get_image_name(i);
00498       const char *tail = strrchr(buffer, '/');
00499       if (tail && (strcmp(tail, "/libp3dtool." PANDA_ABI_VERSION_STR ".dylib") == 0
00500                 || strcmp(tail, "/libp3dtool.dylib") == 0
00501                 || strcmp(tail, "/libdtool.dylib") == 0)) {
00502         _dtool_name = buffer;
00503       }
00504     }
00505   }
00506 #endif
00507 
00508 #if defined(IS_FREEBSD)
00509   // On FreeBSD, we can use dlinfo to get the linked libraries.
00510 
00511   if (_dtool_name.empty()) {
00512     Link_map *map;
00513     dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &map);
00514 
00515     while (map != NULL) {
00516       char *tail = strrchr(map->l_name, '/');
00517       char *head = strchr(map->l_name, '/');
00518       if (tail && head && (strcmp(tail, "/libp3dtool.so." PANDA_ABI_VERSION_STR) == 0
00519                         || strcmp(tail, "/libp3dtool.so") == 0
00520                         || strcmp(tail, "/libdtool.so") == 0)) {
00521         _dtool_name = head;
00522       }
00523       map = map->l_next;
00524     }
00525   }
00526 #endif
00527 
00528 #if defined(HAVE_PROC_SELF_MAPS) || defined(HAVE_PROC_CURPROC_MAP)
00529   // Some operating systems provide a file in the /proc filesystem.
00530 
00531   if (_dtool_name.empty()) {
00532 #ifdef HAVE_PROC_CURPROC_MAP
00533     pifstream maps("/proc/curproc/map");
00534 #else
00535     pifstream maps("/proc/self/maps");
00536 #endif
00537     while (!maps.fail() && !maps.eof()) {
00538       char buffer[PATH_MAX];
00539       buffer[0] = 0;
00540       maps.getline(buffer, PATH_MAX);
00541       char *tail = strrchr(buffer, '/');
00542       char *head = strchr(buffer, '/');
00543       if (tail && head && (strcmp(tail, "/libp3dtool.so." PANDA_ABI_VERSION_STR) == 0
00544                         || strcmp(tail, "/libp3dtool.so") == 0
00545                         || strcmp(tail, "/libdtool.so") == 0)) {
00546         _dtool_name = head;
00547       }
00548     }
00549     maps.close();
00550   }
00551 #endif
00552 
00553   // Now, we need to fill in _binary_name.  This contains
00554   // the full path to the currently running executable.
00555 
00556 #ifdef WIN32_VC
00557   if (_binary_name.empty()) {
00558     static const DWORD buffer_size = 1024;
00559     char buffer[buffer_size];
00560     DWORD size = GetModuleFileName(NULL, buffer, buffer_size);
00561     if (size != 0) {
00562       Filename tmp = Filename::from_os_specific(string(buffer, size));
00563       tmp.make_true_case();
00564       _binary_name = tmp;
00565     }
00566   }
00567 #endif
00568 
00569 #if defined(__APPLE__)
00570   // And on Mac, we have _NSGetExecutablePath.
00571   if (_binary_name.empty()) {
00572     char *pathbuf = new char[PATH_MAX];
00573     uint32_t bufsize = PATH_MAX;
00574     if (_NSGetExecutablePath(pathbuf, &bufsize) == 0) {
00575       _binary_name = pathbuf;
00576     }
00577     delete[] pathbuf;
00578   }
00579 #endif
00580 
00581 #if defined(IS_FREEBSD)
00582   // In FreeBSD, we can use sysctl to determine the pathname.
00583 
00584   if (_binary_name.empty()) {
00585     size_t bufsize = 4096;
00586     char buffer[4096];
00587     int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
00588     mib[3] = getpid();
00589     if (sysctl(mib, 4, (void*) buffer, &bufsize, NULL, 0) == -1) {
00590       perror("sysctl");
00591     } else {
00592       _binary_name = buffer;
00593     }
00594   }
00595 #endif
00596 
00597 #if defined(HAVE_PROC_SELF_EXE) || defined(HAVE_PROC_CURPROC_FILE)
00598   // Some operating systems provide a symbolic link to the executable
00599   // in the /proc filesystem.  Use readlink to resolve that link.
00600 
00601   if (_binary_name.empty()) {
00602     char readlinkbuf [PATH_MAX];
00603 #ifdef HAVE_PROC_CURPROC_FILE
00604     int pathlen = readlink("/proc/curproc/file", readlinkbuf, PATH_MAX - 1);
00605 #else
00606     int pathlen = readlink("/proc/self/exe", readlinkbuf, PATH_MAX - 1);
00607 #endif
00608     if (pathlen > 0) {
00609       readlinkbuf[pathlen] = 0;
00610       _binary_name = readlinkbuf;
00611     }
00612   }
00613 #endif
00614 
00615   // Next we need to fill in _args, which is a vector containing
00616   // the command-line arguments that the executable was invoked with.
00617 
00618 #if defined(IS_FREEBSD)
00619   // In FreeBSD, we can use sysctl to determine the command-line arguments.
00620 
00621   size_t bufsize = 4096;
00622   char buffer[4096];
00623   int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ARGS, 0};
00624   mib[3] = getpid();
00625   if (sysctl(mib, 4, (void*) buffer, &bufsize, NULL, 0) == -1) {
00626     perror("sysctl");
00627   } else {
00628     if (_binary_name.empty()) {
00629       _binary_name = buffer;
00630     }
00631     int idx = strlen(buffer) + 1;
00632     while (idx < bufsize) {
00633       _args.push_back((char*)(buffer + idx));
00634       int newidx = strlen(buffer + idx);
00635       idx += newidx + 1;
00636     }
00637   }
00638 
00639 #elif defined(HAVE_GLOBAL_ARGV)
00640   int argc = GLOBAL_ARGC;
00641 
00642   if (_binary_name.empty() && argc > 0) {
00643     _binary_name = GLOBAL_ARGV[0];
00644     // This really needs to be resolved against PATH.
00645   }
00646 
00647   for (int i = 1; i < argc; i++) {
00648     _args.push_back(GLOBAL_ARGV[i]);
00649   }
00650 
00651 #elif defined(HAVE_PROC_SELF_CMDLINE) || defined(HAVE_PROC_CURPROC_CMDLINE)
00652   // In Linux, and possibly in other systems as well, we might not be
00653   // able to use the global ARGC/ARGV variables at static init time.
00654   // However, we may be lucky and have a file called
00655   // /proc/self/cmdline that may be read to determine all of our
00656   // command-line arguments.
00657 
00658 #ifdef HAVE_PROC_CURPROC_CMDLINE
00659   pifstream proc("/proc/curproc/cmdline");
00660   if (proc.fail()) {
00661     cerr << "Cannot read /proc/curproc/cmdline; command-line arguments unavailable to config.\n";
00662 #else
00663   pifstream proc("/proc/self/cmdline");
00664   if (proc.fail()) {
00665     cerr << "Cannot read /proc/self/cmdline; command-line arguments unavailable to config.\n";
00666 #endif
00667   } else {
00668     int ch = proc.get();
00669     int index = 0;
00670     while (!proc.eof() && !proc.fail()) {
00671       string arg;
00672 
00673       while (!proc.eof() && !proc.fail() && ch != '\0') {
00674         arg += (char)ch;
00675         ch = proc.get();
00676       }
00677 
00678       if (index == 0) {
00679         if (_binary_name.empty())
00680           _binary_name = arg;
00681       } else {
00682         _args.push_back(arg);
00683       }
00684       index++;
00685 
00686       ch = proc.get();
00687     }
00688   }
00689 #endif
00690 
00691 #ifndef WIN32
00692   // Try to use realpath to get cleaner paths.
00693 
00694   if (!_binary_name.empty()) {
00695     char newpath [PATH_MAX + 1];
00696     if (realpath(_binary_name.c_str(), newpath) != NULL) {
00697       _binary_name = newpath;
00698     }
00699   }
00700 
00701   if (!_dtool_name.empty()) {
00702     char newpath [PATH_MAX + 1];
00703     if (realpath(_dtool_name.c_str(), newpath) != NULL) {
00704       _dtool_name = newpath;
00705     }
00706   }
00707 #endif
00708 
00709   if (_dtool_name.empty()) {
00710     _dtool_name = _binary_name;
00711   }
00712 }
 All Classes Functions Variables Enumerations