Panda3D
|
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 }