diff --git a/dtool/src/dtoolutil/executionEnvironment.I b/dtool/src/dtoolutil/executionEnvironment.I index 52ea458b67..4a1b4ac697 100644 --- a/dtool/src/dtoolutil/executionEnvironment.I +++ b/dtool/src/dtoolutil/executionEnvironment.I @@ -112,3 +112,14 @@ INLINE string ExecutionEnvironment:: get_binary_name() { return get_ptr()->ns_get_binary_name(); } + +//////////////////////////////////////////////////////////////////// +// Function: ExecutionEnvironment::get_dtool_name +// Access: Public, Static +// Description: Returns the name of the libdtool DLL that +// is used in this program, if it can be determined. +//////////////////////////////////////////////////////////////////// +INLINE string ExecutionEnvironment:: +get_dtool_name() { + return get_ptr()->ns_get_dtool_name(); +} diff --git a/dtool/src/dtoolutil/executionEnvironment.cxx b/dtool/src/dtoolutil/executionEnvironment.cxx index 7ac74a4882..23bafe4685 100644 --- a/dtool/src/dtoolutil/executionEnvironment.cxx +++ b/dtool/src/dtoolutil/executionEnvironment.cxx @@ -30,7 +30,6 @@ #include #endif - // We define the symbol PREREAD_ENVIRONMENT if we cannot rely on // getenv() to read environment variables at static init time. In // this case, we must read all of the environment variables directly @@ -291,6 +290,21 @@ ns_get_binary_name() const { return _binary_name; } +//////////////////////////////////////////////////////////////////// +// Function: ExecutionEnvironment::ns_get_dtool_name +// Access: Private +// Description: Returns the name of the libdtool DLL that +// is used in this program, if it can be determined. The +// nonstatic implementation. +//////////////////////////////////////////////////////////////////// +string ExecutionEnvironment:: +ns_get_dtool_name() const { + if (_dtool_name.empty()) { + return "unknown"; + } + return _dtool_name; +} + //////////////////////////////////////////////////////////////////// // Function: ExecutionEnvironment::get_ptr // Access: Private, Static @@ -365,9 +379,36 @@ read_environment_variables() { //////////////////////////////////////////////////////////////////// void ExecutionEnvironment:: read_args() { -#if defined(HAVE_GLOBAL_ARGV) - int argc = GLOBAL_ARGC; +#ifdef WIN32_VC + HMODULE dllhandle = GetModuleHandle("libdtool.dll"); + if (dllhandle != 0) { + static const DWORD buffer_size = 1024; + char buffer[buffer_size]; + DWORD size = GetModuleFileName(dllhandle, buffer, buffer_size); + if (size != 0) { + _dtool_name = Filename::from_os_specific(string(buffer,size)); + } + } +#endif + +#if defined(HAVE_PROC_SELF_MAPS) + // This is how you tell whether or not libdtool.so is loaded, + // and if so, where it was loaded from. + ifstream maps("/proc/self/maps"); + while (!maps.fail() && !maps.eof()) { + char buffer[PATH_MAX]; + buffer[0] = 0; + maps.getline(buffer, PATH_MAX); + char *tail = strrchr(buffer,'/'); + char *head = strchr(buffer,'/'); + if (tail && head && (strcmp(tail,"/libdtool.so")==0)) { + _dtool_name = head; + } + } + maps.close(); +#endif + #ifdef WIN32_VC static const DWORD buffer_size = 1024; char buffer[buffer_size]; @@ -377,10 +418,26 @@ read_args() { } #endif // WIN32_VC +#if defined(HAVE_PROC_SELF_EXE) + // This is more reliable than using (argc,argv), so it given precedence. + if (_binary_name.empty()) { + char readlinkbuf[PATH_MAX]; + int pathlen = readlink("/proc/self/exe",readlinkbuf,PATH_MAX-1); + if (pathlen > 0) { + readlinkbuf[pathlen] = 0; + _binary_name = readlinkbuf; + } + } +#endif + +#if defined(HAVE_GLOBAL_ARGV) + int argc = GLOBAL_ARGC; + if (_binary_name.empty() && argc > 0) { _binary_name = GLOBAL_ARGV[0]; + // This really needs to be resolved against PATH. } - + for (int i = 1; i < argc; i++) { _args.push_back(GLOBAL_ARGV[i]); } @@ -397,7 +454,7 @@ read_args() { cerr << "Cannot read /proc/self/cmdline; command-line arguments unavailable to config.\n"; return; } - + int ch = proc.get(); int index = 0; while (!proc.eof() && !proc.fail()) { @@ -409,7 +466,8 @@ read_args() { } if (index == 0) { - _binary_name = arg; + if (_binary_name.empty()) + _binary_name = arg; } else { _args.push_back(arg); } @@ -420,4 +478,7 @@ read_args() { #else cerr << "Warning: command line parameters unavailable to dconfig.\n"; #endif + + if (_dtool_name.empty()) + _dtool_name = _binary_name; } diff --git a/dtool/src/dtoolutil/executionEnvironment.h b/dtool/src/dtoolutil/executionEnvironment.h index 33cc896bb3..884762f929 100644 --- a/dtool/src/dtoolutil/executionEnvironment.h +++ b/dtool/src/dtoolutil/executionEnvironment.h @@ -52,6 +52,7 @@ public: INLINE static string get_arg(int n); INLINE static string get_binary_name(); + INLINE static string get_dtool_name(); static Filename get_cwd(); @@ -66,6 +67,7 @@ private: string ns_get_arg(int n) const; string ns_get_binary_name() const; + string ns_get_dtool_name() const; static ExecutionEnvironment *get_ptr(); @@ -80,6 +82,7 @@ private: CommandArguments _args; string _binary_name; + string _dtool_name; static ExecutionEnvironment *_global_ptr; }; diff --git a/dtool/src/prc/configPageManager.cxx b/dtool/src/prc/configPageManager.cxx index 24b8cfdb39..735de4207d 100644 --- a/dtool/src/prc/configPageManager.cxx +++ b/dtool/src/prc/configPageManager.cxx @@ -153,7 +153,7 @@ reload_implicit_pages() { } } } - + // PRC_PATH_ENVVARS lists one or more environment variables separated // by spaces. Pull them out, and then each one of those contains a // list of directories to search. Add each of those to the search @@ -163,13 +163,22 @@ reload_implicit_pages() { vector_string prc_path_envvar_list; ConfigDeclaration::extract_words(prc_path_envvars, prc_path_envvar_list); for (size_t i = 0; i < prc_path_envvar_list.size(); ++i) { - string prc_path = ExecutionEnvironment::get_environment_variable(prc_path_envvar_list[i]); - if (!prc_path.empty()) { - _search_path.append_path(prc_path); + string path = ExecutionEnvironment::get_environment_variable(prc_path_envvar_list[i]); + size_t p = 0; + while (p < path.length()) { + size_t q = path.find_first_of(DEFAULT_PATHSEP, p); + if (q == string::npos) { + q = path.length(); + } + Filename prc_dir_filename = path.substr(p, q - p); + if (scan_auto_prc_dir(prc_dir_filename)) { + _search_path.append_directory(prc_dir_filename); + } + p = q + 1; } } } - + if (_search_path.is_empty()) { // If nothing's on the search path (PRC_DIR and PRC_PATH were not // defined), then use the DEFAULT_PRC_DIR. @@ -444,8 +453,8 @@ scan_auto_prc_dir(Filename &prc_dir) const { Filename suffix = prc_dir_string.substr(6); // Start at the executable directory. - Filename binary = ExecutionEnvironment::get_binary_name(); - Filename dir = binary.get_dirname(); + Filename dtool = ExecutionEnvironment::get_dtool_name(); + Filename dir = dtool.get_dirname(); if (scan_up_from(prc_dir, dir, suffix)) { return true; diff --git a/dtool/src/prc/configVariableEnum.I b/dtool/src/prc/configVariableEnum.I index e1bf32545d..dcee1c8cdb 100644 --- a/dtool/src/prc/configVariableEnum.I +++ b/dtool/src/prc/configVariableEnum.I @@ -47,7 +47,7 @@ ConfigVariableEnum(const string &name, EnumType default_value, //////////////////////////////////////////////////////////////////// template INLINE ConfigVariableEnum:: -ConfigVariableEnum(const string &name, const string &adefault_value, +ConfigVariableEnum(const string &name, const string &default_value, const string &description, int flags) : #ifdef PRC_SAVE_DESCRIPTIONS ConfigVariable(name, ConfigVariableCore::VT_enum, description, flags),