1 /* -------------------------------------------------------------------------------
3 Copyright (C) 1999-2007 id Software, Inc. and contributors.
4 For a list of contributors, see the accompanying CONTRIBUTORS file.
6 This file is part of GtkRadiant.
8 GtkRadiant is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 GtkRadiant is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GtkRadiant; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 ----------------------------------------------------------------------------------
24 This code has been altered significantly from its original form, to support
25 several games based on the Quake III Arena engine, in the form of "Q3Map2."
27 ------------------------------------------------------------------------------- */
42 #define MAX_BASE_PATHS 10
43 #define MAX_GAME_PATHS 10
46 char installPath[ MAX_OS_PATH ];
49 char *basePaths[ MAX_BASE_PATHS ];
51 char *gamePaths[ MAX_GAME_PATHS ];
52 char *homeBasePath = NULL;
56 some of this code is based off the original q3map port from loki
57 and finds various paths. moved here from bsp.c for clarity.
62 gets the user's home dir (for ~/.q3a)
65 char *LokiGetHomeDir(void)
73 static char homeBuf[MAX_OS_PATH];
76 /* get the home environment variable */
77 home = getenv( "HOME" );
80 /* do some more digging */
83 while( (pwd = getpwent()) != NULL )
85 if( pwd->pw_uid == id )
94 snprintf(homeBuf, sizeof(homeBuf), "%s/.", home);
105 initializes some paths on linux/os x
108 void LokiInitPaths( char *argv0 )
115 home = LokiGetHomeDir();
126 /* this is kinda crap, but hey */
127 strcpy( installPath, "../" );
129 char temp[ MAX_OS_PATH ];
136 /* do some path divining */
137 strcpy( temp, argv0 );
138 if( strrchr( argv0, '/' ) )
139 argv0 = strrchr( argv0, '/' ) + 1;
142 /* get path environment variable */
143 path = getenv( "PATH" );
147 last[ 0 ] = path[ 0 ];
151 /* go through each : segment of path */
152 while( last[ 0 ] != '\0' && found == qfalse )
157 /* find next chunk */
158 last = strchr( path, ':' );
160 last = path + strlen( path );
162 /* found home dir candidate */
165 strcpy( temp, home );
170 if( last > (path + 1) )
172 strncat( temp, path, (last - path) );
175 strcat( temp, "./" );
176 strcat( temp, argv0 );
178 /* verify the path */
179 if( access( temp, X_OK ) == 0 )
186 if( realpath( temp, installPath ) )
188 /* q3map is in "tools/" */
189 *(strrchr( installPath, '/' )) = '\0';
190 *(strrchr( installPath, '/' ) + 1) = '\0';
199 cleans a dos path \ -> /
202 void CleanPath( char *path )
216 gets the game_t based on a -game argument
217 returns NULL if no match found
220 game_t *GetGame( char *arg )
226 if( arg == NULL || arg[ 0 ] == '\0' )
230 if( !Q_stricmp( arg, "quake1" ) ||
231 !Q_stricmp( arg, "quake2" ) ||
232 !Q_stricmp( arg, "unreal" ) ||
233 !Q_stricmp( arg, "ut2k3" ) ||
234 !Q_stricmp( arg, "dn3d" ) ||
235 !Q_stricmp( arg, "dnf" ) ||
236 !Q_stricmp( arg, "hl" ) )
238 Sys_Printf( "April fools, silly rabbit!\n" );
244 while( games[ i ].arg != NULL )
246 if( Q_stricmp( arg, games[ i ].arg ) == 0 )
251 /* no matching game */
258 AddBasePath() - ydnar
259 adds a base path to the list
262 void AddBasePath( char *path )
265 if( path == NULL || path[ 0 ] == '\0' || numBasePaths >= MAX_BASE_PATHS )
268 /* add it to the list */
269 basePaths[ numBasePaths ] = safe_malloc( strlen( path ) + 1 );
270 strcpy( basePaths[ numBasePaths ], path );
271 CleanPath( basePaths[ numBasePaths ] );
278 AddHomeBasePath() - ydnar
279 adds a base path to the beginning of the list, prefixed by ~/
282 void AddHomeBasePath( char *path )
285 char temp[ MAX_OS_PATH ];
292 if( path == NULL || path[ 0 ] == '\0' )
295 /* strip leading dot, if homePath does not end in /. */
296 homePathLen = strlen(homePath);
297 if(!strcmp(path, "."))
299 /* -fs_homebase . means that -fs_home is to be used as is */
300 strcpy(temp, homePath);
302 else if(homePathLen >= 2 && !strcmp(homePath + homePathLen - 2, "/."))
304 /* remove trailing /. of homePath */
307 /* concatenate home dir and path */
308 sprintf( temp, "%.*s/%s", homePathLen, homePath, path );
312 /* remove leading . of path */
316 /* concatenate home dir and path */
317 sprintf( temp, "%s/%s", homePath, path );
321 for( i = (MAX_BASE_PATHS - 2); i >= 0; i-- )
322 basePaths[ i + 1 ] = basePaths[ i ];
324 /* add it to the list */
325 basePaths[ 0 ] = safe_malloc( strlen( temp ) + 1 );
326 strcpy( basePaths[ 0 ], temp );
327 CleanPath( basePaths[ 0 ] );
334 AddGamePath() - ydnar
335 adds a game path to the list
338 void AddGamePath( char *path )
343 if( path == NULL || path[ 0 ] == '\0' || numGamePaths >= MAX_GAME_PATHS )
346 /* add it to the list */
347 gamePaths[ numGamePaths ] = safe_malloc( strlen( path ) + 1 );
348 strcpy( gamePaths[ numGamePaths ], path );
349 CleanPath( gamePaths[ numGamePaths ] );
352 /* don't add it if it's already there */
353 for (i = 0; i < numGamePaths - 1; i++)
355 if (strcmp(gamePaths[i], gamePaths[numGamePaths - 1]) == 0)
357 free(gamePaths[numGamePaths - 1]);
358 gamePaths[numGamePaths - 1] = NULL;
371 cleaned up some of the path initialization code from bsp.c
372 will remove any arguments it uses
375 void InitPaths( int *argc, char **argv )
377 int i, j, k, len, len2;
378 char temp[ MAX_OS_PATH ];
382 Sys_FPrintf( SYS_VRB, "--- InitPaths ---\n" );
384 /* get the install path for backup */
385 LokiInitPaths( argv[ 0 ] );
387 /* set game to default (q3a) */
392 /* parse through the arguments and extract those relevant to paths */
393 for( i = 0; i < *argc; i++ )
396 if( argv[ i ] == NULL )
400 if( strcmp( argv[ i ], "-game" ) == 0 )
403 Error( "Out of arguments: No game specified after %s", argv[ i - 1 ] );
404 argv[ i - 1 ] = NULL;
405 game = GetGame( argv[ i ] );
411 /* -fs_forbiddenpath */
412 else if( strcmp( argv[ i ], "-fs_forbiddenpath" ) == 0 )
415 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
416 argv[ i - 1 ] = NULL;
417 if(g_numForbiddenDirs < VFS_MAXDIRS)
419 strncpy(g_strForbiddenDirs[g_numForbiddenDirs], argv[i], PATH_MAX);
420 g_strForbiddenDirs[g_numForbiddenDirs][PATH_MAX] = 0;
421 ++g_numForbiddenDirs;
427 else if( strcmp( argv[ i ], "-fs_basepath" ) == 0 )
430 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
431 argv[ i - 1 ] = NULL;
432 AddBasePath( argv[ i ] );
437 else if( strcmp( argv[ i ], "-fs_game" ) == 0 )
440 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
441 argv[ i - 1 ] = NULL;
442 AddGamePath( argv[ i ] );
447 else if( strcmp( argv[ i ], "-fs_home" ) == 0 )
450 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
451 argv[ i - 1 ] = NULL;
457 else if( strcmp( argv[ i ], "-fs_homebase" ) == 0 )
460 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
461 argv[ i - 1 ] = NULL;
462 homeBasePath = argv[i];
466 /* -fs_homepath - sets both of them */
467 else if( strcmp( argv[ i ], "-fs_homepath" ) == 0 )
470 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
471 argv[ i - 1 ] = NULL;
478 /* remove processed arguments */
479 for( i = 0, j = 0, k = 0; i < *argc && j < *argc; i++, j++ )
481 for( ; j < *argc && argv[ j ] == NULL; j++ );
482 argv[ i ] = argv[ j ];
483 if( argv[ i ] != NULL )
488 /* add standard game path */
489 AddGamePath( game->gamePath );
491 /* if there is no base path set, figure it out */
492 if( numBasePaths == 0 )
494 /* this is another crappy replacement for SetQdirFromPath() */
495 len2 = strlen( game->magic );
496 for( i = 0; i < *argc && numBasePaths == 0; i++ )
498 /* extract the arg */
499 strcpy( temp, argv[ i ] );
501 len = strlen( temp );
502 Sys_FPrintf( SYS_VRB, "Searching for \"%s\" in \"%s\" (%d)...\n", game->magic, temp, i );
504 /* this is slow, but only done once */
505 for( j = 0; j < (len - len2); j++ )
507 /* check for the game's magic word */
508 if( Q_strncasecmp( &temp[ j ], game->magic, len2 ) == 0 )
510 /* now find the next slash and nuke everything after it */
511 while( temp[ ++j ] != '/' && temp[ j ] != '\0' );
514 /* add this as a base path */
521 /* add install path */
522 if( numBasePaths == 0 )
523 AddBasePath( installPath );
526 if( numBasePaths == 0 )
527 Error( "Failed to find a valid base path." );
530 /* this only affects unix */
532 AddHomeBasePath( homeBasePath );
534 AddHomeBasePath( game->homeBasePath );
536 /* initialize vfs paths */
537 if( numBasePaths > MAX_BASE_PATHS )
538 numBasePaths = MAX_BASE_PATHS;
539 if( numGamePaths > MAX_GAME_PATHS )
540 numGamePaths = MAX_GAME_PATHS;
542 /* walk the list of game paths */
543 for( j = 0; j < numGamePaths; j++ )
545 /* walk the list of base paths */
546 for( i = 0; i < numBasePaths; i++ )
548 /* create a full path and initialize it */
549 sprintf( temp, "%s/%s/", basePaths[ i ], gamePaths[ j ] );
550 vfsInitDirectory( temp );