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