From 822c833d1372bdd62dcc3400a529ac107fabe99a Mon Sep 17 00:00:00 2001 From: Steven Noonan Date: Sun, 20 Sep 2009 20:33:43 -0700 Subject: initfile.cc: improve accuracy of crawl_base variable Windows, Mac OS X and Linux all provide handy ways to retrieve the absolute path of the running executable. This is especially useful since argv[0] can be a relative path. This fixes a bug on the Mac OS X build where the app cannot locate the graphics resources when when they're needed, so the application bombs out instead. Signed-off-by: Steven Noonan --- crawl-ref/source/initfile.cc | 49 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index af96637427..d3dda61ca3 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -11,6 +11,15 @@ REVISION("$Rev$"); #include "initfile.h" +// For finding the executable's path +#if defined ( WIN32CONSOLE ) || defined ( WIN32TILES ) +#include +#elif defined ( __linux__ ) +#include +#elif defined ( __MACH__ ) +extern char **NXArgv; +#endif + #include #include #include @@ -3424,9 +3433,47 @@ static const char *cmd_ops[] = { const int num_cmd_ops = CLO_NOPS; bool arg_seen[num_cmd_ops]; +std::string find_executable_path() +{ + char tempPath[2048]; + + // A lot of OSes give ways to find the location of the running app's + // binary executable. This is useful, because argv[0] can be relative + // when we really need an absolute path in order to locate the game's + // resources. + + // Faster than a memset, and counts as a null-terminated string! + tempPath[0] = 0; + +#if defined ( _MSC_VER ) + + int retval = GetModuleFileName ( NULL, tempPath, sizeof(tempPath) ); + +#elif defined ( __linux__ ) + + int retval = readlink ( "/proc/self/exe", tempPath, sizeof(tempPath) ); + +#elif defined ( __MACH__ ) + + strncpy ( tempPath, NXArgv[0], sizeof(tempPath) ); + +#else + + // We don't know how to find the executable's path on this OS. + +#endif + + return std::string(tempPath); +} + bool parse_args( int argc, char **argv, bool rc_only ) { - set_crawl_base_dir(argv[0]); + std::string exe_path = find_executable_path(); + + if (!exe_path.empty()) + set_crawl_base_dir(exe_path.c_str()); + else + set_crawl_base_dir(argv[0]); SysEnv.rcdirs.clear(); -- cgit v1.2.3-54-g00ecf