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( qboolean *usedot )
74 static char homeBuf[MAX_OS_PATH];
77 /* get the home environment variable */
78 home = getenv( "HOME" );
81 /* do some more digging */
84 while( (pwd = getpwent()) != NULL )
86 if( pwd->pw_uid == id )
95 snprintf(homeBuf, sizeof(homeBuf), "%s/.", home);
106 initializes some paths on linux/os x
109 void LokiInitPaths( char *argv0 )
116 home = LokiGetHomeDir();
125 /* this is kinda crap, but hey */
126 strcpy( installPath, "../" );
128 char temp[ MAX_OS_PATH ];
135 /* do some path divining */
136 strcpy( temp, argv0 );
137 if( strrchr( argv0, '/' ) )
138 argv0 = strrchr( argv0, '/' ) + 1;
141 /* get path environment variable */
142 path = getenv( "PATH" );
146 last[ 0 ] = path[ 0 ];
150 /* go through each : segment of path */
151 while( last[ 0 ] != '\0' && found == qfalse )
156 /* find next chunk */
157 last = strchr( path, ':' );
159 last = path + strlen( path );
161 /* found home dir candidate */
164 strcpy( temp, home );
169 if( last > (path + 1) )
171 strncat( temp, path, (last - path) );
174 strcat( temp, "./" );
175 strcat( temp, argv0 );
177 /* verify the path */
178 if( access( temp, X_OK ) == 0 )
185 if( realpath( temp, installPath ) )
187 /* q3map is in "tools/" */
188 *(strrchr( installPath, '/' )) = '\0';
189 *(strrchr( installPath, '/' ) + 1) = '\0';
198 cleans a dos path \ -> /
201 void CleanPath( char *path )
215 gets the game_t based on a -game argument
216 returns NULL if no match found
219 game_t *GetGame( char *arg )
225 if( arg == NULL || arg[ 0 ] == '\0' )
229 if( !Q_stricmp( arg, "quake1" ) ||
230 !Q_stricmp( arg, "quake2" ) ||
231 !Q_stricmp( arg, "unreal" ) ||
232 !Q_stricmp( arg, "ut2k3" ) ||
233 !Q_stricmp( arg, "dn3d" ) ||
234 !Q_stricmp( arg, "dnf" ) ||
235 !Q_stricmp( arg, "hl" ) )
237 Sys_Printf( "April fools, silly rabbit!\n" );
243 while( games[ i ].arg != NULL )
245 if( Q_stricmp( arg, games[ i ].arg ) == 0 )
250 /* no matching game */
257 AddBasePath() - ydnar
258 adds a base path to the list
261 void AddBasePath( char *path )
264 if( path == NULL || path[ 0 ] == '\0' || numBasePaths >= MAX_BASE_PATHS )
267 /* add it to the list */
268 basePaths[ numBasePaths ] = safe_malloc( strlen( path ) + 1 );
269 strcpy( basePaths[ numBasePaths ], path );
270 CleanPath( basePaths[ numBasePaths ] );
277 AddHomeBasePath() - ydnar
278 adds a base path to the beginning of the list, prefixed by ~/
281 void AddHomeBasePath( char *path )
284 char temp[ MAX_OS_PATH ];
291 if( path == NULL || path[ 0 ] == '\0' )
294 /* strip leading dot, if homePath does not end in /. */
295 homePathLen = strlen(homePath);
296 if(!strcmp(path, ".")
298 /* -fs_homebase . means that -fs_home is to be used as is */
299 strcpy(temp, homePath);
301 else if(homePathLen >= 2 && !strcmp(homePath + homePathLen - 2, "/."))
303 /* remove trailing /. of homePath */
306 /* concatenate home dir and path */
307 sprintf( temp, "%.*s/%s", homePathLen, homePath, path );
311 /* remove leading . of path */
315 /* concatenate home dir and path */
316 sprintf( temp, "%s/%s", homePath, path );
320 for( i = (MAX_BASE_PATHS - 2); i >= 0; i-- )
321 basePaths[ i + 1 ] = basePaths[ i ];
323 /* add it to the list */
324 basePaths[ 0 ] = safe_malloc( strlen( temp ) + 1 );
325 strcpy( basePaths[ 0 ], temp );
326 CleanPath( basePaths[ 0 ] );
333 AddGamePath() - ydnar
334 adds a game path to the list
337 void AddGamePath( char *path )
342 if( path == NULL || path[ 0 ] == '\0' || numGamePaths >= MAX_GAME_PATHS )
345 /* add it to the list */
346 gamePaths[ numGamePaths ] = safe_malloc( strlen( path ) + 1 );
347 strcpy( gamePaths[ numGamePaths ], path );
348 CleanPath( gamePaths[ numGamePaths ] );
351 /* don't add it if it's already there */
352 for (i = 0; i < numGamePaths - 1; i++)
354 if (strcmp(gamePaths[i], gamePaths[numGamePaths - 1]) == 0)
356 free(gamePaths[numGamePaths - 1]);
357 gamePaths[numGamePaths - 1] = NULL;
370 cleaned up some of the path initialization code from bsp.c
371 will remove any arguments it uses
374 void InitPaths( int *argc, char **argv )
376 int i, j, k, len, len2;
377 char temp[ MAX_OS_PATH ];
381 Sys_FPrintf( SYS_VRB, "--- InitPaths ---\n" );
383 /* get the install path for backup */
384 LokiInitPaths( argv[ 0 ] );
386 /* set game to default (q3a) */
391 /* parse through the arguments and extract those relevant to paths */
392 for( i = 0; i < *argc; i++ )
395 if( argv[ i ] == NULL )
399 if( strcmp( argv[ i ], "-game" ) == 0 )
402 Error( "Out of arguments: No game specified after %s", argv[ i - 1 ] );
403 argv[ i - 1 ] = NULL;
404 game = GetGame( argv[ i ] );
410 /* -fs_forbiddenpath */
411 else if( strcmp( argv[ i ], "-fs_forbiddenpath" ) == 0 )
414 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
415 argv[ i - 1 ] = NULL;
416 if(g_numForbiddenDirs < VFS_MAXDIRS)
418 strncpy(g_strForbiddenDirs[g_numForbiddenDirs], argv[i], PATH_MAX);
419 g_strForbiddenDirs[g_numForbiddenDirs][PATH_MAX] = 0;
420 ++g_numForbiddenDirs;
426 else if( strcmp( argv[ i ], "-fs_basepath" ) == 0 )
429 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
430 argv[ i - 1 ] = NULL;
431 AddBasePath( argv[ i ] );
436 else if( strcmp( argv[ i ], "-fs_game" ) == 0 )
439 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
440 argv[ i - 1 ] = NULL;
441 AddGamePath( argv[ i ] );
446 else if( strcmp( argv[ i ], "-fs_home" ) == 0 )
449 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
450 argv[ i - 1 ] = NULL;
456 else if( strcmp( argv[ i ], "-fs_homebase" ) == 0 )
459 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
460 argv[ i - 1 ] = NULL;
461 homeBasePath = argv[i];
465 /* -fs_homepath - sets both of them */
466 else if( strcmp( argv[ i ], "-fs_homepath" ) == 0 )
469 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
470 argv[ i - 1 ] = NULL;
477 /* remove processed arguments */
478 for( i = 0, j = 0, k = 0; i < *argc && j < *argc; i++, j++ )
480 for( ; j < *argc && argv[ j ] == NULL; j++ );
481 argv[ i ] = argv[ j ];
482 if( argv[ i ] != NULL )
487 /* add standard game path */
488 AddGamePath( game->gamePath );
490 /* if there is no base path set, figure it out */
491 if( numBasePaths == 0 )
493 /* this is another crappy replacement for SetQdirFromPath() */
494 len2 = strlen( game->magic );
495 for( i = 0; i < *argc && numBasePaths == 0; i++ )
497 /* extract the arg */
498 strcpy( temp, argv[ i ] );
500 len = strlen( temp );
501 Sys_FPrintf( SYS_VRB, "Searching for \"%s\" in \"%s\" (%d)...\n", game->magic, temp, i );
503 /* this is slow, but only done once */
504 for( j = 0; j < (len - len2); j++ )
506 /* check for the game's magic word */
507 if( Q_strncasecmp( &temp[ j ], game->magic, len2 ) == 0 )
509 /* now find the next slash and nuke everything after it */
510 while( temp[ ++j ] != '/' && temp[ j ] != '\0' );
513 /* add this as a base path */
520 /* add install path */
521 if( numBasePaths == 0 )
522 AddBasePath( installPath );
525 if( numBasePaths == 0 )
526 Error( "Failed to find a valid base path." );
529 /* this only affects unix */
531 AddHomeBasePath( homeBasePath );
533 AddHomeBasePath( game->homeBasePath );
535 /* initialize vfs paths */
536 if( numBasePaths > MAX_BASE_PATHS )
537 numBasePaths = MAX_BASE_PATHS;
538 if( numGamePaths > MAX_GAME_PATHS )
539 numGamePaths = MAX_GAME_PATHS;
541 /* walk the list of game paths */
542 for( j = 0; j < numGamePaths; j++ )
544 /* walk the list of base paths */
545 for( i = 0; i < numBasePaths; i++ )
547 /* create a full path and initialize it */
548 sprintf( temp, "%s/%s/", basePaths[ i ], gamePaths[ j ] );
549 vfsInitDirectory( temp );