+ }
+ else {
+ home = homePath;
+ }
+
+ #if GDEF_OS_MACOS
+ char *subPath = "/Library/Application Support";
+ macLibraryApplicationSupportPath = safe_malloc( sizeof( char ) * ( strlen( home ) + strlen( subPath ) ) + 1 );
+ sprintf( macLibraryApplicationSupportPath, "%s%s", home, subPath );
+ #elif GDEF_OS_XDG
+ xdgDataHomePath = getenv( "XDG_DATA_HOME" );
+
+ if ( xdgDataHomePath == NULL ) {
+ char *subPath = "/.local/share";
+ xdgDataHomePath = safe_malloc( sizeof( char ) * ( strlen( home ) + strlen( subPath ) ) + 1 );
+ sprintf( xdgDataHomePath, "%s%s", home, subPath );
+ }
+ #endif // GDEF_OS_XDG
+
+ #if GDEF_OS_WINDOWS
+ /* this is kinda crap, but hey */
+ strcpy( installPath, "../" );
+ #else // !GDEF_OS_WINDOWS
+
+ char temp[ MAX_OS_PATH ];
+ char *path;
+ char *last;
+ qboolean found;
+
+
+ path = getenv( "PATH" );
+
+ /* do some path divining */
+ Q_strncpyz( temp, argv0, sizeof( temp ) );
+ if ( strrchr( temp, '/' ) ) {
+ argv0 = strrchr( argv0, '/' ) + 1;
+ }
+ else if ( path != NULL ) {
+
+ /*
+ This code has a special behavior when q3map2 is a symbolic link.
+
+ For each dir in ${PATH} (example: "/usr/bin", "/usr/local/bin" if ${PATH} == "/usr/bin:/usr/local/bin"),
+ it looks for "${dir}/q3map2" (file exists and is executable),
+ then it uses "dirname(realpath("${dir}/q3map2"))/../" as installPath.
+
+ So, if "/usr/bin/q3map2" is a symbolic link to "/opt/radiant/tools/q3map2",
+ it will find the installPath "/usr/share/radiant/",
+ so q3map2 will look for "/opt/radiant/baseq3" to find paks.
+
+ More precisely, it looks for "${dir}/${argv[0]}",
+ so if "/usr/bin/q3map2" is a symbolic link to "/opt/radiant/tools/q3map2",
+ and if "/opt/radiant/tools/q3ma2" is a symbolic link to "/opt/radiant/tools/q3map2.x86_64",
+ it will use "dirname("/opt/radiant/tools/q3map2.x86_64")/../" as path,
+ so it will use "/opt/radiant/" as installPath, which will be expanded later to "/opt/radiant/baseq3" to find paks.
+ */
+
+ found = qfalse;
+ last = path;
+
+ /* go through each : segment of path */
+ while ( last[ 0 ] != '\0' && found == qfalse )
+ {
+ /* null out temp */
+ temp[ 0 ] = '\0';
+
+ /* find next chunk */
+ last = strchr( path, ':' );
+ if ( last == NULL ) {
+ last = path + strlen( path );
+ }
+
+ /* found home dir candidate */
+ if ( *path == '~' ) {
+ Q_strncpyz( temp, home, sizeof( temp ) );
+ path++;
+ }
+
+ /* concatenate */
+ if ( last > ( path + 1 ) ) {
+ // +1 hack: Q_strncat calls Q_strncpyz that expects a len including '\0'
+ // so that extraneous char will be rewritten by '\0', so it's ok.
+ // Also, in this case this extraneous char is always ':' or '\0', so it's ok.
+ Q_strncat( temp, sizeof( temp ), path, ( last - path + 1) );
+ Q_strcat( temp, sizeof( temp ), "/" );
+ }
+ Q_strcat( temp, sizeof( temp ), argv0 );
+
+ /* verify the path */
+ if ( access( temp, X_OK ) == 0 ) {
+ found = qtrue;
+ }
+ path = last + 1;
+ }
+ }
+
+ /* flake */
+ if ( realpath( temp, installPath ) ) {
+ /*
+ if "q3map2" is "/opt/radiant/tools/q3map2",
+ installPath is "/opt/radiant"
+ */
+ *( strrchr( installPath, '/' ) ) = '\0';
+ *( strrchr( installPath, '/' ) ) = '\0';
+ }
+ #endif // !GDEF_OS_WINDOWS