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 ){
69 static char buf[ 4096 ];
70 struct passwd pw, *pwp;
72 static char homeBuf[MAX_OS_PATH];
75 /* get the home environment variable */
76 home = getenv( "HOME" );
78 /* look up home dir in password database */
81 if ( getpwuid_r( getuid(), &pw, buf, sizeof( buf ), &pwp ) == 0 ) {
86 snprintf( homeBuf, sizeof( homeBuf ), "%s/.", home );
97 initializes some paths on linux/os x
100 void LokiInitPaths( char *argv0 ){
105 home = LokiGetHomeDir();
106 if ( home == NULL ) {
118 /* this is kinda crap, but hey */
119 strcpy( installPath, "../" );
121 char temp[ MAX_OS_PATH ];
128 path = getenv( "PATH" );
130 /* do some path divining */
131 Q_strncpyz( temp, argv0, sizeof( temp ) );
132 if ( strrchr( temp, '/' ) ) {
133 argv0 = strrchr( argv0, '/' ) + 1;
139 /* go through each : segment of path */
140 while ( last[ 0 ] != '\0' && found == qfalse )
145 /* find next chunk */
146 last = strchr( path, ':' );
147 if ( last == NULL ) {
148 last = path + strlen( path );
151 /* found home dir candidate */
152 if ( *path == '~' ) {
153 Q_strncpyz( temp, home, sizeof( temp ) );
158 if ( last > ( path + 1 ) ) {
159 Q_strncat( temp, sizeof( temp ), path, ( last - path ) );
160 Q_strcat( temp, sizeof( temp ), "/" );
162 Q_strcat( temp, sizeof( temp ), "./" );
163 Q_strcat( temp, sizeof( temp ), argv0 );
165 /* verify the path */
166 if ( access( temp, X_OK ) == 0 ) {
174 if ( realpath( temp, installPath ) ) {
175 /* q3map is in "tools/" */
176 *( strrchr( installPath, '/' ) ) = '\0';
177 *( strrchr( installPath, '/' ) + 1 ) = '\0';
186 cleans a dos path \ -> /
189 void CleanPath( char *path ){
192 if ( *path == '\\' ) {
203 gets the game_t based on a -game argument
204 returns NULL if no match found
207 game_t *GetGame( char *arg ){
212 if ( arg == NULL || arg[ 0 ] == '\0' ) {
217 if ( !Q_stricmp( arg, "quake1" ) ||
218 !Q_stricmp( arg, "quake2" ) ||
219 !Q_stricmp( arg, "unreal" ) ||
220 !Q_stricmp( arg, "ut2k3" ) ||
221 !Q_stricmp( arg, "dn3d" ) ||
222 !Q_stricmp( arg, "dnf" ) ||
223 !Q_stricmp( arg, "hl" ) ) {
224 Sys_Printf( "April fools, silly rabbit!\n" );
230 while ( games[ i ].arg != NULL )
232 if ( Q_stricmp( arg, games[ i ].arg ) == 0 ) {
238 /* no matching game */
245 AddBasePath() - ydnar
246 adds a base path to the list
249 void AddBasePath( char *path ){
251 if ( path == NULL || path[ 0 ] == '\0' || numBasePaths >= MAX_BASE_PATHS ) {
255 /* add it to the list */
256 basePaths[ numBasePaths ] = safe_malloc( strlen( path ) + 1 );
257 strcpy( basePaths[ numBasePaths ], path );
258 CleanPath( basePaths[ numBasePaths ] );
265 AddHomeBasePath() - ydnar
266 adds a base path to the beginning of the list, prefixed by ~/
269 void AddHomeBasePath( char *path ){
271 char temp[ MAX_OS_PATH ];
279 if ( path == NULL || path[ 0 ] == '\0' ) {
283 /* strip leading dot, if homePath does not end in /. */
284 homePathLen = strlen( homePath );
285 if ( !strcmp( path, "." ) ) {
286 /* -fs_homebase . means that -fs_home is to be used as is */
287 strcpy( temp, homePath );
289 else if ( homePathLen >= 2 && !strcmp( homePath + homePathLen - 2, "/." ) ) {
290 /* remove trailing /. of homePath */
293 /* concatenate home dir and path */
294 sprintf( temp, "%.*s/%s", homePathLen, homePath, path );
298 /* remove leading . of path */
299 if ( path[0] == '.' ) {
303 /* concatenate home dir and path */
304 sprintf( temp, "%s/%s", homePath, path );
308 for ( i = ( MAX_BASE_PATHS - 2 ); i >= 0; i-- )
309 basePaths[ i + 1 ] = basePaths[ i ];
311 /* add it to the list */
312 basePaths[ 0 ] = safe_malloc( strlen( temp ) + 1 );
313 strcpy( basePaths[ 0 ], temp );
314 CleanPath( basePaths[ 0 ] );
321 AddGamePath() - ydnar
322 adds a game path to the list
325 void AddGamePath( char *path ){
329 if ( path == NULL || path[ 0 ] == '\0' || numGamePaths >= MAX_GAME_PATHS ) {
333 /* add it to the list */
334 gamePaths[ numGamePaths ] = safe_malloc( strlen( path ) + 1 );
335 strcpy( gamePaths[ numGamePaths ], path );
336 CleanPath( gamePaths[ numGamePaths ] );
339 /* don't add it if it's already there */
340 for ( i = 0; i < numGamePaths - 1; i++ )
342 if ( strcmp( gamePaths[i], gamePaths[numGamePaths - 1] ) == 0 ) {
343 free( gamePaths[numGamePaths - 1] );
344 gamePaths[numGamePaths - 1] = NULL;
357 cleaned up some of the path initialization code from bsp.c
358 will remove any arguments it uses
361 void InitPaths( int *argc, char **argv ){
362 int i, j, k, len, len2;
363 char temp[ MAX_OS_PATH ];
367 Sys_FPrintf( SYS_VRB, "--- InitPaths ---\n" );
369 /* get the install path for backup */
370 LokiInitPaths( argv[ 0 ] );
372 /* set game to default (q3a) */
377 /* parse through the arguments and extract those relevant to paths */
378 for ( i = 0; i < *argc; i++ )
381 if ( argv[ i ] == NULL ) {
386 if ( strcmp( argv[ i ], "-game" ) == 0 ) {
387 if ( ++i >= *argc ) {
388 Error( "Out of arguments: No game specified after %s", argv[ i - 1 ] );
390 argv[ i - 1 ] = NULL;
391 game = GetGame( argv[ i ] );
392 if ( game == NULL ) {
398 /* -fs_forbiddenpath */
399 else if ( strcmp( argv[ i ], "-fs_forbiddenpath" ) == 0 ) {
400 if ( ++i >= *argc ) {
401 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
403 argv[ i - 1 ] = NULL;
404 if ( g_numForbiddenDirs < VFS_MAXDIRS ) {
405 strncpy( g_strForbiddenDirs[g_numForbiddenDirs], argv[i], PATH_MAX );
406 g_strForbiddenDirs[g_numForbiddenDirs][PATH_MAX] = 0;
407 ++g_numForbiddenDirs;
413 else if ( strcmp( argv[ i ], "-fs_basepath" ) == 0 ) {
414 if ( ++i >= *argc ) {
415 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
417 argv[ i - 1 ] = NULL;
418 AddBasePath( argv[ i ] );
423 else if ( strcmp( argv[ i ], "-fs_game" ) == 0 ) {
424 if ( ++i >= *argc ) {
425 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
427 argv[ i - 1 ] = NULL;
428 AddGamePath( argv[ i ] );
433 else if ( strcmp( argv[ i ], "-fs_home" ) == 0 ) {
434 if ( ++i >= *argc ) {
435 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
437 argv[ i - 1 ] = NULL;
443 else if ( strcmp( argv[ i ], "-fs_homebase" ) == 0 ) {
444 if ( ++i >= *argc ) {
445 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
447 argv[ i - 1 ] = NULL;
448 homeBasePath = argv[i];
452 /* -fs_homepath - sets both of them */
453 else if ( strcmp( argv[ i ], "-fs_homepath" ) == 0 ) {
454 if ( ++i >= *argc ) {
455 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
457 argv[ i - 1 ] = NULL;
464 /* remove processed arguments */
465 for ( i = 0, j = 0, k = 0; i < *argc && j < *argc; i++, j++ )
467 for ( ; j < *argc && argv[ j ] == NULL; j++ ) ;
468 argv[ i ] = argv[ j ];
469 if ( argv[ i ] != NULL ) {
475 /* add standard game path */
476 AddGamePath( game->gamePath );
478 /* if there is no base path set, figure it out */
479 if ( numBasePaths == 0 ) {
480 /* this is another crappy replacement for SetQdirFromPath() */
481 len2 = strlen( game->magic );
482 for ( i = 0; i < *argc && numBasePaths == 0; i++ )
484 /* extract the arg */
485 strcpy( temp, argv[ i ] );
487 len = strlen( temp );
488 Sys_FPrintf( SYS_VRB, "Searching for \"%s\" in \"%s\" (%d)...\n", game->magic, temp, i );
490 /* this is slow, but only done once */
491 for ( j = 0; j < ( len - len2 ); j++ )
493 /* check for the game's magic word */
494 if ( Q_strncasecmp( &temp[ j ], game->magic, len2 ) == 0 ) {
495 /* now find the next slash and nuke everything after it */
496 while ( temp[ ++j ] != '/' && temp[ j ] != '\0' ) ;
499 /* add this as a base path */
506 /* add install path */
507 if ( numBasePaths == 0 ) {
508 AddBasePath( installPath );
512 if ( numBasePaths == 0 ) {
513 Error( "Failed to find a valid base path." );
517 /* this only affects unix */
518 if ( homeBasePath ) {
519 AddHomeBasePath( homeBasePath );
522 AddHomeBasePath( game->homeBasePath );
525 /* initialize vfs paths */
526 if ( numBasePaths > MAX_BASE_PATHS ) {
527 numBasePaths = MAX_BASE_PATHS;
529 if ( numGamePaths > MAX_GAME_PATHS ) {
530 numGamePaths = MAX_GAME_PATHS;
533 /* walk the list of game paths */
534 for ( j = 0; j < numGamePaths; j++ )
536 /* walk the list of base paths */
537 for ( i = 0; i < numBasePaths; i++ )
539 /* create a full path and initialize it */
540 sprintf( temp, "%s/%s/", basePaths[ i ], gamePaths[ j ] );
541 vfsInitDirectory( temp );