29 #include "prc_parameters.h" 34 #ifdef PRC_PUBLIC_KEYS_INCLUDE 35 #include PRC_PUBLIC_KEYS_INCLUDE 57 _loaded_implicit =
false;
58 _currently_loading =
false;
61 #ifdef PRC_PUBLIC_KEYS_INCLUDE 63 PrcKeyRegistry::get_global_ptr()->record_keys(prc_pubkeys, num_prc_pubkeys);
64 #endif // PRC_PUBLIC_KEYS_INCLUDE 72 ~ConfigPageManager() {
74 <<
"Internal error--ConfigPageManager destructor called!\n";
86 if (_currently_loading) {
91 _currently_loading =
true;
95 for (pi = _implicit_pages.begin(); pi != _implicit_pages.end(); ++pi) {
98 _implicit_pages.clear();
103 uint64_t blob_offset;
106 uint16_t num_pointers;
110 const void *module_table;
111 const char *prc_data;
112 const char *default_prc_dir;
113 const char *prc_dir_envvars;
114 const char *prc_path_envvars;
115 const char *prc_patterns;
116 const char *prc_encrypted_patterns;
117 const char *prc_encryption_key;
118 const char *prc_executable_patterns;
119 const char *prc_executable_args_envvar;
120 const char *main_dir;
121 const char *log_filename;
124 const BlobInfo *blobinfo = (
const BlobInfo *)GetProcAddress(GetModuleHandle(NULL),
"blobinfo");
125 #elif defined(RTLD_MAIN_ONLY) 126 const BlobInfo *blobinfo = (
const BlobInfo *)dlsym(RTLD_MAIN_ONLY,
"blobinfo");
130 const BlobInfo *blobinfo = (
const BlobInfo *)dlsym(dlopen(NULL, RTLD_NOW),
"blobinfo");
132 if (blobinfo !=
nullptr && (blobinfo->version == 0 || blobinfo->num_pointers < 10)) {
136 if (blobinfo !=
nullptr) {
137 if (blobinfo->num_pointers >= 11 && blobinfo->main_dir !=
nullptr) {
148 _prc_patterns.clear();
150 string prc_patterns = PRC_PATTERNS;
151 if (blobinfo !=
nullptr && blobinfo->prc_patterns !=
nullptr) {
152 prc_patterns = blobinfo->prc_patterns;
154 if (!prc_patterns.empty()) {
155 vector_string pat_list;
157 _prc_patterns.reserve(pat_list.size());
158 for (
size_t i = 0; i < pat_list.size(); ++i) {
165 _prc_patterns.push_back(glob);
170 _prc_encrypted_patterns.clear();
172 string prc_encrypted_patterns = PRC_ENCRYPTED_PATTERNS;
173 if (blobinfo !=
nullptr && blobinfo->prc_encrypted_patterns !=
nullptr) {
174 prc_encrypted_patterns = blobinfo->prc_encrypted_patterns;
176 if (!prc_encrypted_patterns.empty()) {
177 vector_string pat_list;
179 _prc_encrypted_patterns.reserve(pat_list.size());
180 for (
size_t i = 0; i < pat_list.size(); ++i) {
185 _prc_encrypted_patterns.push_back(glob);
190 _prc_executable_patterns.clear();
192 string prc_executable_patterns = PRC_EXECUTABLE_PATTERNS;
193 if (blobinfo !=
nullptr && blobinfo->prc_executable_patterns !=
nullptr) {
194 prc_executable_patterns = blobinfo->prc_executable_patterns;
196 if (!prc_executable_patterns.empty()) {
197 vector_string pat_list;
199 _prc_executable_patterns.reserve(pat_list.size());
200 for (
size_t i = 0; i < pat_list.size(); ++i) {
205 _prc_executable_patterns.push_back(glob);
210 _search_path.
clear();
215 string prc_dir_envvars = PRC_DIR_ENVVARS;
216 if (blobinfo !=
nullptr && blobinfo->prc_dir_envvars !=
nullptr) {
217 prc_dir_envvars = blobinfo->prc_dir_envvars;
219 if (!prc_dir_envvars.empty()) {
220 vector_string prc_dir_envvar_list;
222 for (
size_t i = 0; i < prc_dir_envvar_list.size(); ++i) {
224 if (!prc_dir.empty()) {
227 if (scan_auto_prc_dir(prc_dir_filename)) {
237 string prc_path_envvars = PRC_PATH_ENVVARS;
238 if (blobinfo !=
nullptr && blobinfo->prc_path_envvars !=
nullptr) {
239 prc_path_envvars = blobinfo->prc_path_envvars;
241 if (!prc_path_envvars.empty()) {
242 vector_string prc_path_envvar_list;
244 for (
size_t i = 0; i < prc_path_envvar_list.size(); ++i) {
247 while (p < path.length()) {
248 size_t q = path.find_first_of(DEFAULT_PATHSEP, p);
249 if (q == string::npos) {
254 if (scan_auto_prc_dir(prc_dir_filename)) {
271 string prc_path2_envvars = PRC_PATH2_ENVVARS;
272 if (!prc_path2_envvars.empty() && blobinfo ==
nullptr) {
273 vector_string prc_path_envvar_list;
275 for (
size_t i = 0; i < prc_path_envvar_list.size(); ++i) {
278 while (p < path.length()) {
279 size_t q = path.find_first_of(
' ', p);
280 if (q == string::npos) {
283 Filename prc_dir_filename = path.substr(p, q - p);
284 if (scan_auto_prc_dir(prc_dir_filename)) {
295 string default_prc_dir = DEFAULT_PRC_DIR;
296 if (blobinfo !=
nullptr && blobinfo->default_prc_dir !=
nullptr) {
297 default_prc_dir = blobinfo->default_prc_dir;
299 if (!default_prc_dir.empty()) {
301 Filename prc_dir_filename = default_prc_dir;
302 if (scan_auto_prc_dir(prc_dir_filename)) {
310 ConfigFiles config_files;
314 std::set<Filename> unique_dirnames;
323 if (unique_dirnames.insert(canonical).second) {
332 vector_string::reverse_iterator fi;
333 for (fi = files.rbegin(); fi != files.rend(); ++fi) {
335 Globs::const_iterator gi;
336 for (gi = _prc_patterns.begin();
337 gi != _prc_patterns.end();
339 if ((*gi).matches(*fi)) {
340 file_flags |= FF_read;
344 for (gi = _prc_encrypted_patterns.begin();
345 gi != _prc_encrypted_patterns.end();
347 if ((*gi).matches(*fi)) {
348 file_flags |= FF_read | FF_decrypt;
352 for (gi = _prc_executable_patterns.begin();
353 gi != _prc_executable_patterns.end();
355 if ((*gi).matches(*fi)) {
356 file_flags |= FF_execute;
360 if (file_flags != 0) {
362 file._file_flags = file_flags;
363 file._filename =
Filename(directory, (*fi));
364 config_files.push_back(file);
374 if (blobinfo !=
nullptr && blobinfo->prc_data !=
nullptr) {
377 _implicit_pages.push_back(page);
378 _pages_sorted =
false;
380 std::istringstream in(blobinfo->prc_data);
388 ConfigFiles::reverse_iterator ci;
389 for (ci = config_files.rbegin(); ci != config_files.rend(); ++ci) {
390 const ConfigFile &file = (*ci);
393 if ((file._file_flags & FF_execute) != 0 &&
398 string envvar = PRC_EXECUTABLE_ARGS_ENVVAR;
399 if (blobinfo !=
nullptr && blobinfo->prc_executable_args_envvar !=
nullptr) {
400 envvar = blobinfo->prc_executable_args_envvar;
402 if (!envvar.empty()) {
413 _implicit_pages.push_back(page);
414 _pages_sorted =
false;
418 }
else if ((file._file_flags & FF_decrypt) != 0) {
425 <<
"Unable to read " << filename <<
"\n";
429 _implicit_pages.push_back(page);
430 _pages_sorted =
false;
432 if (blobinfo !=
nullptr && blobinfo->prc_encryption_key !=
nullptr) {
439 }
else if ((file._file_flags & FF_read) != 0) {
446 <<
"Unable to read " << filename <<
"\n";
450 _implicit_pages.push_back(page);
451 _pages_sorted =
false;
458 if (!_loaded_implicit) {
459 config_initialized();
460 _loaded_implicit =
true;
463 _currently_loading =
false;
466 #ifdef USE_PANDAFILESTREAM 470 (
"newline-mode", PandaFileStreamBuf::NM_native,
471 PRC_DESC(
"Controls how newlines are written by Panda applications writing " 472 "to a text file. The default, \"native\", means to write newlines " 473 "appropriate to the current platform. You may also specify \"binary\", " 474 "to avoid molesting the file data, or one of \"msdos\", \"unix\", " 476 PandaFileStreamBuf::_newline_mode = newline_mode;
477 #endif // USE_PANDAFILESTREAM 483 (
"show-dll-error-dialog",
false,
484 PRC_DESC(
"Set this true to enable the Windows system dialog that pops " 485 "up when a DLL fails to load, or false to disable it. It is " 486 "normally false, but it may be useful to set it true to debug " 487 "why a DLL is not loading. (Note that this actually disables " 488 "*all* critical error messages, and that it's a global setting " 489 "that some other libraries might un-set.)"));
490 if (show_dll_error_dialog) {
493 SetErrorMode(SEM_FAILCRITICALERRORS);
508 _explicit_pages.push_back(page);
509 _pages_sorted =
false;
524 for (pi = _explicit_pages.begin(); pi != _explicit_pages.end(); ++pi) {
526 _explicit_pages.erase(pi);
538 void ConfigPageManager::
539 output(std::ostream &out)
const {
540 out <<
"ConfigPageManager, " 541 << _explicit_pages.size() + _implicit_pages.size()
548 void ConfigPageManager::
549 write(std::ostream &out)
const {
551 out << _explicit_pages.size() <<
" explicit pages:\n";
553 Pages::const_iterator pi;
554 for (pi = _explicit_pages.begin(); pi != _explicit_pages.end(); ++pi) {
562 out <<
" (invalid signature: ";
570 out <<
"\n" << _implicit_pages.size() <<
" implicit pages:\n";
571 for (pi = _implicit_pages.begin(); pi != _implicit_pages.end(); ++pi) {
579 out <<
" (invalid signature: ";
593 if (_global_ptr ==
nullptr) {
611 void ConfigPageManager::
616 _pages_sorted =
true;
629 bool ConfigPageManager::
630 scan_auto_prc_dir(
Filename &prc_dir)
const {
631 string prc_dir_string = prc_dir;
632 if (prc_dir_string.substr(0, 6) ==
"<auto>") {
633 Filename suffix = prc_dir_string.substr(6);
639 if (scan_up_from(prc_dir, dir, suffix)) {
645 if (scan_up_from(prc_dir, dir, suffix)) {
650 std::cerr <<
"Warning: unable to auto-locate config files in directory named by \"" 651 << prc_dir <<
"\".\n";
667 bool ConfigPageManager::
673 if (consider.is_directory()) {
674 if (consider.scan_directory(files)) {
675 vector_string::const_iterator fi;
676 for (fi = files.begin(); fi != files.end(); ++fi) {
677 Globs::const_iterator gi;
678 for (gi = _prc_patterns.begin();
679 gi != _prc_patterns.end();
681 if ((*gi).matches(*fi)) {
687 for (gi = _prc_executable_patterns.begin();
688 gi != _prc_executable_patterns.end();
690 if ((*gi).matches(*fi)) {
707 return scan_up_from(result, parent, suffix);
716 void ConfigPageManager::
717 config_initialized() {
722 (
"panda-package-version",
"local_dev",
723 PRC_DESC(
"This can be used to specify the value returned by " 724 "PandaSystem::get_package_version_str(), in development mode only, " 725 "and only if another value has not already been compiled in. This " 726 "is intended for developer convenience, to masquerade a development " 727 "build of Panda as a different runtime version. Use with caution."));
729 (
"panda-package-host-url",
"",
730 PRC_DESC(
"This can be used to specify the value returned by " 731 "PandaSystem::get_package_host_url(), in development mode only, " 732 "and only if another value has not already been compiled in. This " 733 "is intended for developer convenience, to masquerade a development " 734 "build of Panda as a different runtime version. Use with caution."));
737 panda_sys->set_package_version_string(panda_package_version);
738 panda_sys->set_package_host_url(panda_package_host_url);
743 (
"text-encoding", TextEncoder::E_utf8,
744 PRC_DESC(
"Specifies how international characters are represented in strings " 745 "of 8-byte characters presented to Panda. See TextEncoder::set_encoding()."));
749 (
"filesystem-encoding", TextEncoder::E_utf8,
750 PRC_DESC(
"Specifies the default encoding used for wide-character filenames."));
static PandaSystem * get_global_ptr()
Returns the global PandaSystem object.
std::string get_dirname() const
Returns the directory part of the filename.
get_name
Returns the name of the page.
static size_t extract_words(const std::string &str, vector_string &words)
Divides the string into a number of words according to whitespace.
This class is used as a namespace to group several global properties of Panda.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
set_case_sensitive
Sets whether the match is case sensitive (true) or case insensitive (false).
This is a convenience class to specialize ConfigVariable as a boolean type.
void clear()
Removes all the directories from the search list.
void set_binary()
Indicates that the filename represents a binary file.
void set_text()
Indicates that the filename represents a text file.
bool open_read(std::ifstream &stream) const
Opens the indicated ifstream for reading the file, if possible.
bool read_encrypted_prc(std::istream &in, const std::string &password)
Automatically decrypts and reads the stream, given the indicated password.
bool is_empty() const
Returns true if the search list is empty, false otherwise.
get_signature
Returns the raw binary signature that was found in the prc file, if any.
set_default_encoding
Specifies the default encoding to be used for all subsequently created TextEncoder objects...
bool make_canonical()
Converts this filename to a canonical name by replacing the directory part with the fully-qualified d...
bool make_true_case()
On a case-insensitive operating system (e.g.
get_dtool_name
Returns the name of the libdtool DLL that is used in this program, if it can be determined.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void append_directory(const Filename &directory)
Adds a new directory to the end of the search list.
static std::ostream & out()
A convenient way to get the ostream that should be written to for a Notify- type message.
get_trust_level
Returns the trust level associated with this page.
bool read_prc(std::istream &in)
Reads the contents of a complete prc file, as returned by the indicated istream, into the current pag...
static Notify * ptr()
Returns the pointer to the global Notify object.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A global object that maintains the set of ConfigPages everywhere in the world, and keeps them in sort...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static void set_filesystem_encoding(TextEncoder::Encoding encoding)
Specifies the default encoding to be used for all subsequent Filenames.
get_num_directories
Returns the number of directories on the search list.
bool is_executable() const
Returns true if the filename exists and is executable.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The name of a file, such as a texture file or an Egg file.
This is a convenience class to specialize ConfigVariable as a string type.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void reload_implicit_pages()
Searches the PRC_DIR and/or PRC_PATH directories for *.prc files and loads them in as pages...
ConfigPage * make_explicit_page(const std::string &name)
Creates and returns a new, empty ConfigPage.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This class specializes ConfigVariable as an enumerated type.
A page of ConfigDeclarations that may be loaded or unloaded.
bool is_directory() const
Returns true if the filename exists and is a directory name, false otherwise.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void config_initialized()
Intended to be called only by Config, this is a callback that indicates to Notify when Config has don...
get_directory
Returns the nth directory on the search list.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool scan_directory(vector_string &contents) const
Attempts to open the named filename as if it were a directory and looks for the non-hidden files with...
static void set_notify_ptr(std::ostream *ptr)
Sets the ostream that is used to write error messages to.
set_environment_variable
Changes the definition of the indicated environment variable.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool delete_explicit_page(ConfigPage *page)
Removes a previously-constructed ConfigPage from the set of active pages, and deletes it...
std::string to_os_specific() const
Converts the filename from our generic Unix-like convention (forward slashes starting with the root a...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void output_brief_signature(std::ostream &out) const
Outputs the first few hex digits of the signature.
static Filename from_os_specific(const std::string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes, and no drive letter) based on the supplied filename string that describes a filename in the local system conventions (for instance, on Windows, it may use backslashes or begin with a drive letter and a colon).
This class can be used to test for string matches against standard Unix- shell filename globbing conv...
get_environment_variable
Returns the definition of the indicated environment variable, or the empty string if the variable is ...