From 69faefcab4f8ac6599f47173b9a0eba80aaa10a6 Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Sun, 23 Aug 2015 16:08:58 -0400 Subject: Make IWAD search paths compliant with XDG spec. The XDG Base Directory Specification defines standard directories that are searched for data files via the XDG_DATA_HOME and XDG_DATA_DIRS environment variables: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html To make Chocolate Doom a good citizen, use these directories to determine some of the locations in which to look for IWAD files. This includes /usr/share/games/doom, which is absorbed under the default value of the XDG_DATA_DIRS variable. We also now support the alternative ~/.local/share/games/doom as a user-writeable path in the user's home directory that doesn't require root privileges. This is part of #597 (thanks to @chungy for the suggestion). --- src/d_iwad.c | 128 ++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 82 insertions(+), 46 deletions(-) diff --git a/src/d_iwad.c b/src/d_iwad.c index 2d6460bc..3777bab6 100644 --- a/src/d_iwad.c +++ b/src/d_iwad.c @@ -509,55 +509,96 @@ static GameMission_t IdentifyIWADByName(char *name, int mask) return mission; } -// -// Add directories from the list in the DOOMWADPATH environment variable. -// - -static void AddDoomWadPath(void) +// Add IWAD directories parsed from splitting a path string containing +// paths separated by PATH_SEPARATOR. 'suffix' is a string to concatenate +// to the end of the paths before adding them. +static void AddIWADPath(char *path, char *suffix) { - char *doomwadpath; - char *p; - - // Check the DOOMWADPATH environment variable. - - doomwadpath = getenv("DOOMWADPATH"); - - if (doomwadpath == NULL) - { - return; - } + char *left, *p; - doomwadpath = M_StringDuplicate(doomwadpath); - - // Add the initial directory - - AddIWADDir(doomwadpath); + path = M_StringDuplicate(path); // Split into individual dirs within the list. - - p = doomwadpath; + left = path; for (;;) { - p = strchr(p, PATH_SEPARATOR); - + p = strchr(left, PATH_SEPARATOR); if (p != NULL) { - // Break at the separator and store the right hand side + // Break at the separator and use the left hand side // as another iwad dir - *p = '\0'; - p += 1; - AddIWADDir(p); + AddIWADDir(M_StringJoin(left, suffix, NULL)); + left = p + 1; } else { break; } } + + AddIWADDir(M_StringJoin(left, suffix, NULL)); + + free(path); } +// Add standard directories where IWADs are located on Unix systems. +// To respect the freedesktop.org specification we support overriding +// using standard environment variables. See the XDG Base Directory +// Specification: +// +static void AddXdgDirs(void) +{ + char *env, *tmp_env; + + // Quote: + // > $XDG_DATA_HOME defines the base directory relative to which + // > user specific data files should be stored. If $XDG_DATA_HOME + // > is either not set or empty, a default equal to + // > $HOME/.local/share should be used. + env = getenv("XDG_DATA_HOME"); + tmp_env = NULL; + + if (env == NULL) + { + char *homedir = getenv("HOME"); + if (homedir == NULL) + { + homedir = "/"; + } + + tmp_env = M_StringJoin(homedir, "/.local/share", NULL); + env = tmp_env; + } + + // We support $XDG_DATA_HOME/games/doom (which will usually be + // ~/.local/share/games/doom) as a user-writeable extension to + // the usual /usr/share/games/doom location. + AddIWADDir(M_StringJoin(env, "/games/doom", NULL)); + free(tmp_env); + + // Quote: + // > $XDG_DATA_DIRS defines the preference-ordered set of base + // > directories to search for data files in addition to the + // > $XDG_DATA_HOME base directory. The directories in $XDG_DATA_DIRS + // > should be seperated with a colon ':'. + // > + // > If $XDG_DATA_DIRS is either not set or empty, a value equal to + // > /usr/local/share/:/usr/share/ should be used. + env = getenv("XDG_DATA_DIRS"); + if (env == NULL) + { + // (Trailing / omitted from paths, as it is added below) + env = "/usr/local/share:/usr/share"; + } + + // The "standard" location for IWADs on Unix that is supported by most + // source ports is /usr/share/games/doom - we support this through the + // XDG_DATA_DIRS mechanism, through which it can be overridden. + AddIWADPath(env, "/games/doom"); +} // // Build a list of IWAD files @@ -565,7 +606,7 @@ static void AddDoomWadPath(void) static void BuildIWADDirList(void) { - char *doomwaddir; + char *env; if (iwad_dirs_built) { @@ -573,21 +614,21 @@ static void BuildIWADDirList(void) } // Look in the current directory. Doom always does this. - AddIWADDir("."); // Add DOOMWADDIR if it is in the environment - - doomwaddir = getenv("DOOMWADDIR"); - - if (doomwaddir != NULL) + env = getenv("DOOMWADDIR"); + if (env != NULL) { - AddIWADDir(doomwaddir); - } - - // Add dirs from DOOMWADPATH + AddIWADDir(env); + } - AddDoomWadPath(); + // Add dirs from DOOMWADPATH: + env = getenv("DOOMWADPATH"); + if (env != NULL) + { + AddIWADPath(env, ""); + } #ifdef _WIN32 @@ -603,12 +644,7 @@ static void BuildIWADDirList(void) CheckSteamGUSPatches(); #else - - // Standard places where IWAD files are installed under Unix. - - AddIWADDir("/usr/share/games/doom"); - AddIWADDir("/usr/local/share/games/doom"); - + AddXdgDirs(); #endif // Don't run this function again. -- cgit v1.2.3