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 ){
72 static char homeBuf[MAX_OS_PATH];
75 /* get the home environment variable */
76 home = getenv( "HOME" );
78 /* do some more digging */
81 while ( ( pwd = getpwent() ) != NULL )
83 if ( pwd->pw_uid == id ) {
91 snprintf( homeBuf, sizeof( homeBuf ), "%s/.", home );
102 initializes some paths on linux/os x
105 void LokiInitPaths( char *argv0 ){
110 home = LokiGetHomeDir();
111 if ( home == NULL ) {
123 /* this is kinda crap, but hey */
124 strcpy( installPath, "../" );
126 char temp[ MAX_OS_PATH ];
133 /* do some path divining */
134 strcpy( temp, argv0 );
135 if ( strrchr( argv0, '/' ) ) {
136 argv0 = strrchr( argv0, '/' ) + 1;
140 /* get path environment variable */
141 path = getenv( "PATH" );
145 last[ 0 ] = path[ 0 ];
149 /* go through each : segment of path */
150 while ( last[ 0 ] != '\0' && found == qfalse )
155 /* find next chunk */
156 last = strchr( path, ':' );
157 if ( last == NULL ) {
158 last = path + strlen( path );
161 /* found home dir candidate */
162 if ( *path == '~' ) {
163 strcpy( temp, home );
168 if ( last > ( path + 1 ) ) {
169 strncat( temp, path, ( last - path ) );
172 strcat( temp, "./" );
173 strcat( temp, argv0 );
175 /* verify the path */
176 if ( access( temp, X_OK ) == 0 ) {
184 if ( realpath( temp, installPath ) ) {
185 /* q3map is in "tools/" */
186 *( strrchr( installPath, '/' ) ) = '\0';
187 *( strrchr( installPath, '/' ) + 1 ) = '\0';
196 cleans a dos path \ -> /
199 void CleanPath( char *path ){
202 if ( *path == '\\' ) {
213 gets the game_t based on a -game argument
214 returns NULL if no match found
217 game_t *GetGame( char *arg ){
222 if ( arg == NULL || arg[ 0 ] == '\0' ) {
227 if ( !Q_stricmp( arg, "quake1" ) ||
228 !Q_stricmp( arg, "quake2" ) ||
229 !Q_stricmp( arg, "unreal" ) ||
230 !Q_stricmp( arg, "ut2k3" ) ||
231 !Q_stricmp( arg, "dn3d" ) ||
232 !Q_stricmp( arg, "dnf" ) ||
233 !Q_stricmp( arg, "hl" ) ) {
234 Sys_Printf( "April fools, silly rabbit!\n" );
240 while ( games[ i ].arg != NULL )
242 if ( Q_stricmp( arg, games[ i ].arg ) == 0 ) {
248 /* no matching game */
255 AddBasePath() - ydnar
256 adds a base path to the list
259 void AddBasePath( char *path ){
261 if ( path == NULL || path[ 0 ] == '\0' || numBasePaths >= MAX_BASE_PATHS ) {
265 /* add it to the list */
266 basePaths[ numBasePaths ] = safe_malloc( strlen( path ) + 1 );
267 strcpy( basePaths[ numBasePaths ], path );
268 CleanPath( basePaths[ numBasePaths ] );
275 AddHomeBasePath() - ydnar
276 adds a base path to the beginning of the list, prefixed by ~/
279 void AddHomeBasePath( char *path ){
281 char temp[ MAX_OS_PATH ];
289 if ( path == NULL || path[ 0 ] == '\0' ) {
293 /* strip leading dot, if homePath does not end in /. */
294 homePathLen = strlen( homePath );
295 if ( !strcmp( path, "." ) ) {
296 /* -fs_homebase . means that -fs_home is to be used as is */
297 strcpy( temp, homePath );
299 else if ( homePathLen >= 2 && !strcmp( homePath + homePathLen - 2, "/." ) ) {
300 /* remove trailing /. of homePath */
303 /* concatenate home dir and path */
304 sprintf( temp, "%.*s/%s", homePathLen, homePath, path );
308 /* remove leading . of path */
309 if ( path[0] == '.' ) {
313 /* concatenate home dir and path */
314 sprintf( temp, "%s/%s", homePath, path );
318 for ( i = ( MAX_BASE_PATHS - 2 ); i >= 0; i-- )
319 basePaths[ i + 1 ] = basePaths[ i ];
321 /* add it to the list */
322 basePaths[ 0 ] = safe_malloc( strlen( temp ) + 1 );
323 strcpy( basePaths[ 0 ], temp );
324 CleanPath( basePaths[ 0 ] );
331 AddGamePath() - ydnar
332 adds a game path to the list
335 void AddGamePath( char *path ){
339 if ( path == NULL || path[ 0 ] == '\0' || numGamePaths >= MAX_GAME_PATHS ) {
343 /* add it to the list */
344 gamePaths[ numGamePaths ] = safe_malloc( strlen( path ) + 1 );
345 strcpy( gamePaths[ numGamePaths ], path );
346 CleanPath( gamePaths[ numGamePaths ] );
349 /* don't add it if it's already there */
350 for ( i = 0; i < numGamePaths - 1; i++ )
352 if ( strcmp( gamePaths[i], gamePaths[numGamePaths - 1] ) == 0 ) {
353 free( gamePaths[numGamePaths - 1] );
354 gamePaths[numGamePaths - 1] = NULL;
367 cleaned up some of the path initialization code from bsp.c
368 will remove any arguments it uses
371 void InitPaths( int *argc, char **argv ){
372 int i, j, k, len, len2;
373 char temp[ MAX_OS_PATH ];
377 Sys_FPrintf( SYS_VRB, "--- InitPaths ---\n" );
379 /* get the install path for backup */
380 LokiInitPaths( argv[ 0 ] );
382 /* set game to default (q3a) */
387 /* parse through the arguments and extract those relevant to paths */
388 for ( i = 0; i < *argc; i++ )
391 if ( argv[ i ] == NULL ) {
396 if ( strcmp( argv[ i ], "-game" ) == 0 ) {
397 if ( ++i >= *argc ) {
398 Error( "Out of arguments: No game specified after %s", argv[ i - 1 ] );
400 argv[ i - 1 ] = NULL;
401 game = GetGame( argv[ i ] );
402 if ( game == NULL ) {
408 /* -fs_forbiddenpath */
409 else if ( strcmp( argv[ i ], "-fs_forbiddenpath" ) == 0 ) {
410 if ( ++i >= *argc ) {
411 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
413 argv[ i - 1 ] = NULL;
414 if ( g_numForbiddenDirs < VFS_MAXDIRS ) {
415 strncpy( g_strForbiddenDirs[g_numForbiddenDirs], argv[i], PATH_MAX );
416 g_strForbiddenDirs[g_numForbiddenDirs][PATH_MAX] = 0;
417 ++g_numForbiddenDirs;
423 else if ( strcmp( argv[ i ], "-fs_basepath" ) == 0 ) {
424 if ( ++i >= *argc ) {
425 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
427 argv[ i - 1 ] = NULL;
428 AddBasePath( argv[ i ] );
433 else if ( strcmp( argv[ i ], "-fs_game" ) == 0 ) {
434 if ( ++i >= *argc ) {
435 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
437 argv[ i - 1 ] = NULL;
438 AddGamePath( argv[ i ] );
443 else if ( strcmp( argv[ i ], "-fs_home" ) == 0 ) {
444 if ( ++i >= *argc ) {
445 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
447 argv[ i - 1 ] = NULL;
453 else if ( strcmp( argv[ i ], "-fs_homebase" ) == 0 ) {
454 if ( ++i >= *argc ) {
455 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
457 argv[ i - 1 ] = NULL;
458 homeBasePath = argv[i];
462 /* -fs_homepath - sets both of them */
463 else if ( strcmp( argv[ i ], "-fs_homepath" ) == 0 ) {
464 if ( ++i >= *argc ) {
465 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
467 argv[ i - 1 ] = NULL;
474 /* remove processed arguments */
475 for ( i = 0, j = 0, k = 0; i < *argc && j < *argc; i++, j++ )
477 for ( ; j < *argc && argv[ j ] == NULL; j++ ) ;
478 argv[ i ] = argv[ j ];
479 if ( argv[ i ] != NULL ) {
485 /* add standard game path */
486 AddGamePath( game->gamePath );
488 /* if there is no base path set, figure it out */
489 if ( numBasePaths == 0 ) {
490 /* this is another crappy replacement for SetQdirFromPath() */
491 len2 = strlen( game->magic );
492 for ( i = 0; i < *argc && numBasePaths == 0; i++ )
494 /* extract the arg */
495 strcpy( temp, argv[ i ] );
497 len = strlen( temp );
498 Sys_FPrintf( SYS_VRB, "Searching for \"%s\" in \"%s\" (%d)...\n", game->magic, temp, i );
500 /* this is slow, but only done once */
501 for ( j = 0; j < ( len - len2 ); j++ )
503 /* check for the game's magic word */
504 if ( Q_strncasecmp( &temp[ j ], game->magic, len2 ) == 0 ) {
505 /* now find the next slash and nuke everything after it */
506 while ( temp[ ++j ] != '/' && temp[ j ] != '\0' ) ;
509 /* add this as a base path */
516 /* add install path */
517 if ( numBasePaths == 0 ) {
518 AddBasePath( installPath );
522 if ( numBasePaths == 0 ) {
523 Error( "Failed to find a valid base path." );
527 /* this only affects unix */
528 if ( homeBasePath ) {
529 AddHomeBasePath( homeBasePath );
532 AddHomeBasePath( game->homeBasePath );
535 /* initialize vfs paths */
536 if ( numBasePaths > MAX_BASE_PATHS ) {
537 numBasePaths = MAX_BASE_PATHS;
539 if ( numGamePaths > MAX_GAME_PATHS ) {
540 numGamePaths = MAX_GAME_PATHS;
543 /* walk the list of game paths */
544 for ( j = 0; j < numGamePaths; j++ )
546 /* walk the list of base paths */
547 for ( i = 0; i < numBasePaths; i++ )
549 /* create a full path and initialize it */
550 sprintf( temp, "%s/%s/", basePaths[ i ], gamePaths[ j ] );
551 vfsInitDirectory( temp );