15 #include "pandaVersion.h" 25 #include <sys/param.h> 31 #define getcwd _getcwd 45 #include <mach-o/dyld.h> 47 #include <crt_externs.h> 49 #define environ (*_NSGetEnviron()) 58 extern char **environ;
61 #include <sys/types.h> 62 #include <sys/sysctl.h> 65 #if defined(IS_LINUX) || defined(IS_FREEBSD) 75 #ifndef STATIC_INIT_GETENV 76 #define PREREAD_ENVIRONMENT 83 #if !defined(WIN32_VC) && defined(HAVE_GLOBAL_ARGV) && defined(PROTOTYPE_GLOBAL_ARGV) 84 extern char **GLOBAL_ARGV;
85 extern int GLOBAL_ARGC;
98 ExecutionEnvironment::
99 ExecutionEnvironment() {
100 read_environment_variables();
116 size_t dollar = str.find(
'$');
117 while (dollar != string::npos && dollar + 1 < str.length()) {
118 size_t start = dollar + 1;
120 if (str[start] ==
'$') {
122 result += str.substr(last, start - last);
129 if (str[start] ==
'{') {
131 end = str.find(
'}', start + 1);
132 if (end != string::npos) {
133 varname = str.substr(start + 1, end - (start + 1));
140 while (end < str.length() && (isalnum(str[end]) || str[end] ==
'_')) {
143 varname = str.substr(start, end - start);
147 result += str.substr(last, dollar - last);
152 dollar = str.find(
'$', last);
155 result += str.substr(last);
167 static size_t bufsize = 1024;
168 static wchar_t *buffer =
nullptr;
170 if (buffer ==
nullptr) {
171 buffer =
new wchar_t[bufsize];
174 while (_wgetcwd(buffer, bufsize) ==
nullptr) {
175 if (errno != ERANGE) {
180 bufsize = bufsize * 2;
181 buffer =
new wchar_t[bufsize];
182 assert(buffer !=
nullptr);
190 static size_t bufsize = 1024;
191 static char *buffer =
nullptr;
193 if (buffer ==
nullptr) {
194 buffer =
new char[bufsize];
197 while (getcwd(buffer, bufsize) ==
nullptr) {
198 if (errno != ERANGE) {
203 bufsize = bufsize * 2;
204 buffer =
new char[bufsize];
205 assert(buffer !=
nullptr);
218 bool ExecutionEnvironment::
219 ns_has_environment_variable(
const string &var)
const {
220 #ifdef PREREAD_ENVIRONMENT 221 return _variables.count(var) != 0;
223 return getenv(var.c_str()) !=
nullptr;
231 string ExecutionEnvironment::
232 ns_get_environment_variable(
const string &var)
const {
233 EnvironmentVariables::const_iterator evi;
234 evi = _variables.find(var);
235 if (evi != _variables.end()) {
236 return (*evi).second;
244 }
else if (var ==
"TEMP") {
246 }
else if (var ==
"USER_APPDATA") {
248 }
else if (var ==
"COMMON_APPDATA") {
250 }
else if (var ==
"MAIN_DIR") {
254 if (!_binary_name.empty()) {
256 main_dir.make_absolute();
257 return Filename(main_dir.get_dirname()).to_os_specific();
261 #ifndef PREREAD_ENVIRONMENT 262 const char *def = getenv(var.c_str());
263 if (def !=
nullptr) {
275 static struct {
int id;
const char *name; } csidl_table[] = {
276 { CSIDL_ADMINTOOLS,
"ADMINTOOLS" },
277 { CSIDL_ALTSTARTUP,
"ALTSTARTUP" },
278 { CSIDL_APPDATA,
"APPDATA" },
279 { CSIDL_BITBUCKET,
"BITBUCKET" },
280 { CSIDL_CDBURN_AREA,
"CDBURN_AREA" },
281 { CSIDL_COMMON_ADMINTOOLS,
"COMMON_ADMINTOOLS" },
282 { CSIDL_COMMON_ALTSTARTUP,
"COMMON_ALTSTARTUP" },
283 { CSIDL_COMMON_APPDATA,
"COMMON_APPDATA" },
284 { CSIDL_COMMON_DESKTOPDIRECTORY,
"COMMON_DESKTOPDIRECTORY" },
285 { CSIDL_COMMON_DOCUMENTS,
"COMMON_DOCUMENTS" },
286 { CSIDL_COMMON_FAVORITES,
"COMMON_FAVORITES" },
287 { CSIDL_COMMON_MUSIC,
"COMMON_MUSIC" },
288 { CSIDL_COMMON_OEM_LINKS,
"COMMON_OEM_LINKS" },
289 { CSIDL_COMMON_PICTURES,
"COMMON_PICTURES" },
290 { CSIDL_COMMON_PROGRAMS,
"COMMON_PROGRAMS" },
291 { CSIDL_COMMON_STARTMENU,
"COMMON_STARTMENU" },
292 { CSIDL_COMMON_STARTUP,
"COMMON_STARTUP" },
293 { CSIDL_COMMON_TEMPLATES,
"COMMON_TEMPLATES" },
294 { CSIDL_COMMON_VIDEO,
"COMMON_VIDEO" },
295 { CSIDL_COMPUTERSNEARME,
"COMPUTERSNEARME" },
296 { CSIDL_CONNECTIONS,
"CONNECTIONS" },
297 { CSIDL_CONTROLS,
"CONTROLS" },
298 { CSIDL_COOKIES,
"COOKIES" },
299 { CSIDL_DESKTOP,
"DESKTOP" },
300 { CSIDL_DESKTOPDIRECTORY,
"DESKTOPDIRECTORY" },
301 { CSIDL_DRIVES,
"DRIVES" },
302 { CSIDL_FAVORITES,
"FAVORITES" },
303 { CSIDL_FONTS,
"FONTS" },
304 { CSIDL_HISTORY,
"HISTORY" },
305 { CSIDL_INTERNET,
"INTERNET" },
306 { CSIDL_INTERNET_CACHE,
"INTERNET_CACHE" },
307 { CSIDL_LOCAL_APPDATA,
"LOCAL_APPDATA" },
308 { CSIDL_MYDOCUMENTS,
"MYDOCUMENTS" },
309 { CSIDL_MYMUSIC,
"MYMUSIC" },
310 { CSIDL_MYPICTURES,
"MYPICTURES" },
311 { CSIDL_MYVIDEO,
"MYVIDEO" },
312 { CSIDL_NETHOOD,
"NETHOOD" },
313 { CSIDL_NETWORK,
"NETWORK" },
314 { CSIDL_PERSONAL,
"PERSONAL" },
315 { CSIDL_PRINTERS,
"PRINTERS" },
316 { CSIDL_PRINTHOOD,
"PRINTHOOD" },
317 { CSIDL_PROFILE,
"PROFILE" },
318 { CSIDL_PROGRAM_FILES,
"PROGRAM_FILES" },
319 { CSIDL_PROGRAM_FILESX86,
"PROGRAM_FILESX86" },
320 { CSIDL_PROGRAM_FILES_COMMON,
"PROGRAM_FILES_COMMON" },
321 { CSIDL_PROGRAM_FILES_COMMONX86,
"PROGRAM_FILES_COMMONX86" },
322 { CSIDL_PROGRAMS,
"PROGRAMS" },
323 { CSIDL_RECENT,
"RECENT" },
324 { CSIDL_RESOURCES,
"RESOURCES" },
325 { CSIDL_RESOURCES_LOCALIZED,
"RESOURCES_LOCALIZED" },
326 { CSIDL_SENDTO,
"SENDTO" },
327 { CSIDL_STARTMENU,
"STARTMENU" },
328 { CSIDL_STARTUP,
"STARTUP" },
329 { CSIDL_SYSTEM,
"SYSTEM" },
330 { CSIDL_SYSTEMX86,
"SYSTEMX86" },
331 { CSIDL_TEMPLATES,
"TEMPLATES" },
332 { CSIDL_WINDOWS,
"WINDOWS" },
336 for (
int i = 0; csidl_table[i].name !=
nullptr; ++i) {
337 if (strcmp(var.c_str(), csidl_table[i].name) == 0) {
338 wchar_t buffer[MAX_PATH];
339 if (SHGetSpecialFolderPathW(
nullptr, buffer, csidl_table[i].
id,
true)) {
347 #elif !defined(__APPLE__) 351 if (var ==
"XDG_CONFIG_HOME") {
355 }
else if (var ==
"XDG_CACHE_HOME") {
359 }
else if (var ==
"XDG_DATA_HOME") {
372 void ExecutionEnvironment::
373 ns_set_environment_variable(
const string &var,
const string &value) {
374 _variables[var] = value;
375 string putstr = var +
"=" + value;
378 char *put = (
char *)malloc(putstr.length() + 1);
379 strcpy(put, putstr.c_str());
386 void ExecutionEnvironment::
387 ns_shadow_environment_variable(
const string &var,
const string &value) {
388 _variables[var] = value;
389 string putstr = var +
"=" + value;
395 void ExecutionEnvironment::
396 ns_clear_shadow(
const string &var) {
397 EnvironmentVariables::iterator vi = _variables.find(var);
398 if (vi == _variables.end()) {
402 #ifdef PREREAD_ENVIRONMENT 404 const char *def = getenv(var.c_str());
405 if (def !=
nullptr) {
408 _variables.erase(vi);
410 #endif // PREREAD_ENVIRONMENT 417 size_t ExecutionEnvironment::
418 ns_get_num_args()
const {
427 string ExecutionEnvironment::
428 ns_get_arg(
size_t n)
const {
429 assert(n < ns_get_num_args());
437 string ExecutionEnvironment::
438 ns_get_binary_name()
const {
439 if (_binary_name.empty()) {
449 string ExecutionEnvironment::
450 ns_get_dtool_name()
const {
451 if (_dtool_name.empty()) {
463 if (_global_ptr ==
nullptr) {
474 void ExecutionEnvironment::
475 read_environment_variables() {
476 #ifdef PREREAD_ENVIRONMENT 477 #if defined(IS_OSX) || defined(IS_FREEBSD) || defined(IS_LINUX) 482 for (envp = environ; envp && *envp; envp++) {
487 for (envc = *envp; envc && *envc && strncmp(envc,
"=", 1) != 0; envc++) {
488 variable += (char) *envc;
491 if (strncmp(envc,
"=", 1) == 0) {
492 for (envc++; envc && *envc; envc++) {
493 value += (char) *envc;
497 if (!variable.empty()) {
498 _variables[variable] = value;
501 #elif defined(HAVE_PROC_SELF_ENVIRON) 505 pifstream proc(
"/proc/self/environ");
507 cerr <<
"Cannot read /proc/self/environ; environment variables unavailable.\n";
512 while (!proc.eof() && !proc.fail()) {
516 while (!proc.eof() && !proc.fail() && ch !=
'=' && ch !=
'\0') {
517 variable += (char)ch;
523 while (!proc.eof() && !proc.fail() && ch !=
'\0') {
529 if (!variable.empty()) {
530 _variables[variable] = value;
535 cerr <<
"Warning: environment variables unavailable to dconfig.\n";
537 #endif // PREREAD_ENVIRONMENT 544 void ExecutionEnvironment::
551 HMODULE dllhandle = GetModuleHandle(
"libp3dtool_d.dll");
553 HMODULE dllhandle = GetModuleHandle(
"libp3dtool.dll");
555 if (dllhandle != 0) {
556 static const DWORD buffer_size = 1024;
557 wchar_t buffer[buffer_size];
558 DWORD size = GetModuleFileNameW(dllhandle, buffer, buffer_size);
567 #if defined(__APPLE__) 570 if (_dtool_name.empty()) {
571 uint32_t ic = _dyld_image_count();
572 for (uint32_t i = 0; i < ic; ++i) {
573 const char *buffer = _dyld_get_image_name(i);
574 const char *tail = strrchr(buffer,
'/');
575 if (tail && (strcmp(tail,
"/libp3dtool." PANDA_ABI_VERSION_STR
".dylib") == 0
576 || strcmp(tail,
"/libp3dtool.dylib") == 0)) {
577 _dtool_name = buffer;
583 #if defined(RTLD_DI_ORIGIN) 586 char origin[PATH_MAX + 1];
588 if (_dtool_name.empty()) {
589 void *dtool_handle = dlopen(
"libp3dtool.so." PANDA_ABI_VERSION_STR, RTLD_NOW | RTLD_NOLOAD);
590 if (dtool_handle !=
nullptr && dlinfo(dtool_handle, RTLD_DI_ORIGIN, origin) != -1) {
591 _dtool_name = origin;
592 _dtool_name +=
"/libp3dtool.so." PANDA_ABI_VERSION_STR;
595 dtool_handle = dlopen(
"libp3dtool.so", RTLD_NOW | RTLD_NOLOAD);
596 if (dtool_handle !=
nullptr && dlinfo(dtool_handle, RTLD_DI_ORIGIN, origin) != -1) {
597 _dtool_name = origin;
598 _dtool_name +=
"/libp3dtool.so";
604 #if !defined(RTLD_DI_ORIGIN) && defined(RTLD_DI_LINKMAP) 606 if (_dtool_name.empty()) {
607 struct link_map *map;
609 void *
self = RTLD_SELF;
611 void *
self = dlopen(NULL, RTLD_NOW | RTLD_NOLOAD);
613 dlinfo(
self, RTLD_DI_LINKMAP, &map);
615 while (map !=
nullptr) {
616 const char *tail = strrchr(map->l_name,
'/');
617 const char *head = strchr(map->l_name,
'/');
618 if (tail && head && (strcmp(tail,
"/libp3dtool.so." PANDA_ABI_VERSION_STR) == 0
619 || strcmp(tail,
"/libp3dtool.so") == 0)) {
627 #if defined(HAVE_PROC_SELF_MAPS) || defined(HAVE_PROC_CURPROC_MAP) 630 if (_dtool_name.empty()) {
631 #ifdef HAVE_PROC_CURPROC_MAP 632 pifstream maps(
"/proc/curproc/map");
634 pifstream maps(
"/proc/self/maps");
636 while (!maps.fail() && !maps.eof()) {
637 char buffer[PATH_MAX];
639 maps.getline(buffer, PATH_MAX);
640 const char *tail = strrchr(buffer,
'/');
641 const char *head = strchr(buffer,
'/');
642 if (tail && head && (strcmp(tail,
"/libp3dtool.so." PANDA_ABI_VERSION_STR) == 0
643 || strcmp(tail,
"/libp3dtool.so") == 0)) {
655 if (_binary_name.empty()) {
656 static const DWORD buffer_size = 1024;
657 wchar_t buffer[buffer_size];
658 DWORD size = GetModuleFileNameW(
nullptr, buffer, buffer_size);
667 #if defined(__APPLE__) 669 if (_binary_name.empty()) {
670 char *pathbuf =
new char[PATH_MAX];
671 uint32_t bufsize = PATH_MAX;
672 if (_NSGetExecutablePath(pathbuf, &bufsize) == 0) {
673 _binary_name = pathbuf;
679 #if defined(IS_FREEBSD) 682 if (_binary_name.empty()) {
683 size_t bufsize = 4096;
685 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
687 if (sysctl(mib, 4, (
void*) buffer, &bufsize,
nullptr, 0) == -1) {
690 _binary_name = buffer;
695 #if defined(HAVE_PROC_SELF_EXE) || defined(HAVE_PROC_CURPROC_FILE) 699 if (_binary_name.empty()) {
700 char readlinkbuf [PATH_MAX];
701 #ifdef HAVE_PROC_CURPROC_FILE 702 ssize_t pathlen = readlink(
"/proc/curproc/file", readlinkbuf, PATH_MAX - 1);
704 ssize_t pathlen = readlink(
"/proc/self/exe", readlinkbuf, PATH_MAX - 1);
707 readlinkbuf[pathlen] = 0;
708 _binary_name = readlinkbuf;
716 #if defined(WIN32_VC) 721 LPWSTR cmdline = GetCommandLineW();
723 LPWSTR *wargv = CommandLineToArgvW(cmdline, &argc);
725 if (wargv ==
nullptr) {
726 cerr <<
"CommandLineToArgvW failed; command-line arguments unavailable to config.\n";
732 for (
int i = 0; i < argc; ++i) {
733 std::wstring wtext(wargv[i]);
737 if (_binary_name.empty()) {
741 _args.push_back(encoder.
get_text());
748 #elif defined(IS_FREEBSD) 751 size_t bufsize = 4096;
753 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ARGS, 0};
755 if (sysctl(mib, 4, (
void*) buffer, &bufsize,
nullptr, 0) == -1) {
758 if (_binary_name.empty()) {
759 _binary_name = buffer;
761 size_t idx = strlen(buffer) + 1;
762 while (idx < bufsize) {
763 _args.push_back((
char*)(buffer + idx));
764 size_t newidx = strlen(buffer + idx);
769 #elif defined(HAVE_GLOBAL_ARGV) 770 int argc = GLOBAL_ARGC;
774 if (GLOBAL_ARGV !=
nullptr) {
775 if (_binary_name.empty() && argc > 0) {
776 _binary_name = GLOBAL_ARGV[0];
780 for (
int i = 1; i < argc; i++) {
781 _args.push_back(GLOBAL_ARGV[i]);
785 #elif defined(HAVE_PROC_SELF_CMDLINE) || defined(HAVE_PROC_CURPROC_CMDLINE) 791 #ifdef HAVE_PROC_CURPROC_CMDLINE 792 pifstream proc(
"/proc/curproc/cmdline");
794 cerr <<
"Cannot read /proc/curproc/cmdline; command-line arguments unavailable to config.\n";
796 pifstream proc(
"/proc/self/cmdline");
798 cerr <<
"Cannot read /proc/self/cmdline; command-line arguments unavailable to config.\n";
803 while (!proc.eof() && !proc.fail()) {
806 while (!proc.eof() && !proc.fail() && ch !=
'\0') {
812 if (_binary_name.empty())
815 _args.push_back(arg);
827 if (!_binary_name.empty()) {
828 char newpath [PATH_MAX + 1];
829 if (realpath(_binary_name.c_str(), newpath) !=
nullptr) {
830 _binary_name = newpath;
834 if (!_dtool_name.empty()) {
835 char newpath [PATH_MAX + 1];
836 if (realpath(_dtool_name.c_str(), newpath) !=
nullptr) {
837 _dtool_name = newpath;
842 if (_dtool_name.empty()) {
843 _dtool_name = _binary_name;
This class can be used to convert text between multiple representations, e.g.
bool make_true_case()
On a case-insensitive operating system (e.g.
static const Filename & get_home_directory()
Returns a path to the user's home directory, if such a thing makes sense in the current OS,...
static TextEncoder::Encoding get_filesystem_encoding()
Specifies the default encoding to be used for all subsequent Filenames objects.
The name of a file, such as a texture file or an Egg file.
static std::string expand_string(const std::string &str)
Reads the string, looking for environment variable names marked by a $.
std::string get_fullpath() const
Returns the entire filename: directory, basename, extension.
static const Filename & get_user_appdata_directory()
Returns a path to a system-defined directory appropriate for creating a subdirectory for storing appl...
static const Filename & get_temp_directory()
Returns a path to a system-defined temporary directory.
get_text
Returns the current text, as encoded via the current encoding system.
void set_encoding(Encoding encoding)
Specifies how the string set via set_text() is to be interpreted.
static const Filename & get_common_appdata_directory()
Returns a path to a system-defined directory appropriate for creating a subdirectory for storing appl...
Encapsulates access to the environment variables and command-line arguments at the time of execution.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::string to_os_specific() const
Converts the filename from our generic Unix-like convention (forward slashes starting with the root a...
static Filename from_os_specific_w(const std::wstring &os_specific, Type type=T_general)
The wide-string variant of from_os_specific().
void set_wtext(const std::wstring &wtext)
Changes the text that is stored in the encoder.
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,...
get_environment_variable
Returns the definition of the indicated environment variable, or the empty string if the variable is ...